
OpenMetadata 分布式搜索索引多节点测试环境架构、运维与故障恢复实战【免费下载链接】OpenMetadataThe Open Context Layer for Data and AI , OpenMetadata is the open platform for building trusted data context and business semantics for humans, AI assistants, and agents.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMetadata本文围绕 OpenMetadata 仓库中的docker/development/distributed-test/目录展开讲解如何用 Docker Compose 或本地 JVM 方式搭建「3 个 OpenMetadata Server 共享同一 MySQL 与 OpenSearch」的分布式搜索索引Distributed Search Indexing测试环境。读完本文你将掌握该环境的拓扑结构、端口规划、快速启动与数据加载流程、IDE 断点调试方法并能通过源码级的分片协调机制数据库锁、分区认领、孤儿任务恢复验证多节点下的分区分布与服务器故障恢复行为。1. 环境目标三节点集群下的分布式重建索引该目录的定位在 README 开篇即有说明包含用于测试分布式搜索索引功能的脚本与配置让多个 OpenMetadata Server 共享同一个数据库以此验证索引重建工作能否被正确拆分、认领并在节点间协调完成。整体测试环境架构如下引自 README┌─────────────────────────────────────────────────────────────────┐ │ Test Environment │ ├─────────────────────────────────────────────────────────────────┤ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ OM Server│ │ OM Server│ │ OM Server│ │ │ │ :8585 │ │ :8587 │ │ :8589 │ │ │ │ SERVER-1 │ │ SERVER-2 │ │ SERVER-3 │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ └─────────────┼─────────────┘ │ │ ┌──────┴──────┐ │ │ │ Polling │ (DB-based coordination) │ │ └──────┬──────┘ │ │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ │ │ ┌─────────┐ ┌───────────┐ │ │ │ MySQL │ │ OpenSearch│ │ │ │ :3306 │ │ :9200 │ │ │ └─────────┘ └───────────┘ │ └─────────────────────────────────────────────────────────────────┘关键设计点在于「Polling DB-based coordination」三个节点之间没有直接的集群通信层所有协调状态任务、分区、锁都落在共享的 MySQL 中各服务器轮询数据库来认领工作、刷新心跳、检测失效节点。这与源码中PollingJobNotifier见 distributed 包的实现形态一致。2. 环境拓扑docker-compose.yml 中的五个服务完整环境定义 由 5 个服务组成全部挂在自定义 bridge 网络distributed_test_network上并使用mysql-data、opensearch-data两个命名卷持久化数据服务镜像 / 构建容器名说明mysqlmysql:8.0distributed_test_mysql共享元数据库启动参数--sort_buffer_size10M --max_connections500宿主机端口默认 3306opensearchopensearchproject/opensearch:3.4.0distributed_test_opensearch单节点模式discovery.typesingle-nodeplugins.security.disabledtrue默认堆 512m宿主机端口 9200另映射 9600 传输端口migrate基于 开发镜像 构建distributed_test_migrate一次性迁移服务执行./bootstrap/openmetadata-ops.sh -d migrate --force在 MySQL/OpenSearch 健康后才启动openmetadata-server-1/2/3同上构建distributed_test_om_server_1/2/3三个 OpenMetadata Server各自注入唯一的OM_SERVER_IDserver-1/2/3几个值得注意的配置细节容器内端口相同宿主机端口错开。三个 OM 容器内部都使用SERVER_PORT: 8585/SERVER_ADMIN_PORT: 8586通过宿主机端口映射区分server-1 为8585:8585/8586:8586server-2 为8587:8585/8588:8586server-3 为8589:8585/8590:8586。节点身份。每个容器注入OM_SERVER_IDserver-1/server-2/server-3作为分布式索引中的唯一服务器标识OPENMETADATA_CLUSTER_NAME统一为distributed-test。测试裁剪。PIPELINE_SERVICE_CLIENT_ENABLED: false关闭 Airflow 流水线服务客户端认证采用 basic providerAUTHORIZER_ADMIN_PRINCIPALS: [admin]AUTHENTICATION_PUBLIC_KEYS分别指向本节点自己的 jwks 端点如 server-1 指向http://localhost:8585/api/v1/system/config/jwks。启动顺序与依赖。mysql和opensearch都带健康检查mysqladmin pingOpenSearch 检查_cluster/health为 green/yellowmigrate服务要求两者service_healthy三个 OM 容器则要求migrateservice_completed_successfully。OM 容器自身的健康检查为wget -q --spider http://localhost:8586/healthcheck。JVM 堆。通过OPENMETADATA_HEAP_OPTS环境变量控制默认-Xmx1G -Xms1G。MySQL 初始化由挂载的 mysql-init.sql 完成创建openmetadata_db数据库与openmetadata_user用户密码openmetadata_password并授予该库及全局ALL PRIVILEGES。该初始化脚本仅在数据卷首次初始化时由 MySQL 官方镜像自动执行这与三台服务器共享同一份库表结构含search_index_job、search_index_partition、search_reindex_lock等协调表的设计相呼应。3. 快速开始Docker Compose 五步走README 给出的标准工作流是「启动 → 灌数据 → 触发重建 → 观察日志 → 停止」以下按其原文整理。需要注意README 文档化的./scripts/*.sh便捷入口与.env在仓库当前目录树中并未随附目录实际包含docker-compose.yml、config/、local/与 README因此下文同时给出等价的docker compose原生命令可直接对照执行。3.1 启动环境cd docker/development/distributed-test # README 文档化用法启动全部服务首次运行会构建镜像 ./scripts/start.sh # 或强制重新构建 ./scripts/start.sh --build # 等价的原生命令 docker compose up -d # 强制重建 docker compose --build up -d3.2 加载测试数据# 默认加载 10,000 张表 ./scripts/perf-test.sh # 或指定规模 ./scripts/perf-test.sh --tables 50000 --databases 50数据规模可通过 README 描述的.env变量控制例如TEST_DATA_TABLES10000。3.3 触发重建索引# 在 server 1 上触发 reindex ./scripts/trigger-reindex.sh # 带索引重建先写 staged index成功后切换别名 ./scripts/trigger-reindex.sh --recreate # 仅重建指定实体类型 ./scripts/trigger-reindex.sh --entities table,dashboard从源码看触发入口对应 SearchResource 中的POST /reindexEntities端点operationId: reindexOnlySelectedEntities请求体可指定实体集合等参数分布式机制本身是常开的见 DISTRIBUTED_INDEXING.md 中 Distributed indexing is always enabled因此任何一次 reindex 请求在多节点环境中都会走分区协调流程。3.4 监控进度# 跟随所有服务器日志 ./scripts/logs.sh -f # 按模式过滤 ./scripts/logs.sh -f --grep partition # 只看单台服务器 ./scripts/logs.sh -f --server 1等价的原生命令docker logs -f distributed_test_om_server_1 distributed_test_om_server_2 distributed_test_om_server_3 docker compose logs -f3.5 停止环境# 停止容器保留数据卷 ./scripts/stop.sh # 停止并清理数据卷 ./scripts/stop.sh --clean等价命令docker compose down保留卷或docker compose down -v连同卷清理。4. 本地开发模式IDE 断点调试多节点当需要打断点排查协调逻辑时README 建议「OM 服务器跑在本地 JVMMySQL 与 OpenSearch 用 Docker」。4.1 只启动依赖cd docker/development/distributed-test docker compose -f local/docker-compose-deps.yml up -dlocal/docker-compose-deps.yml 与完整环境的 MySQL、OpenSearch 服务定义完全一致同样的镜像、端口、健康检查与初始化脚本挂载只是去掉了 migrate 与 OM 服务。4.2 首次运行迁移cd /path/to/openmetadata ./bootstrap/openmetadata-ops.sh -d migrate --forcebootstrap/openmetadata-ops.sh 是官方运维入口-d migrate --force执行数据库迁移。4.3 方案 A终端批量启动# 启动全部 3 台服务器每个一台新终端窗口 ./local/run-local-servers.sh # 或只启动指定编号 ./local/run-local-servers.sh 1 2run-local-servers.sh 的内置逻辑值得细看它把「手动多节点调试」自动化了先在openmetadata-service/target下查找openmetadata-service-*.jar找不到就自动执行mvn clean package -DskipTests -pl openmetadata-service -am构建探测本机 3306/9200 端口MySQL 未起时自动拉起docker-compose-deps.yml并轮询mysqladmin ping直到就绪支持--migrate参数以PropertiesLauncher migrate --force方式直接调用 JAR 内迁移入口按编号计算 API 端口8583 n*2即 server-1 → 8585server-2 → 8587server-3 → 8589并给每台服务器注入不同的日志前缀-Ddw.logging.appenders[0].logFormat[SERVER-$n] ...配合local/serverN.yaml中additionalFields: server: server-N的日志字段使三台节点的日志在聚合查看时不会混淆优先使用 macOS Terminal / gnome-terminal / xterm 开新窗口均不可用时回退为后台进程日志写入/tmp/om-server-N.log服务器之间以 2 秒间隔错峰启动。4.4 方案 BIDE Run Configuration在 IntelliJ IDEA 中为每个节点各建一个配置README 原文Server 1主类org.openmetadata.service.OpenMetadataApplication程序参数server docker/development/distributed-test/local/server1.yamlVM 参数-Xmx1G -Xms512M工作目录为项目根目录。Server 2 / Server 3同上仅把配置文件换成 server2.yaml / server3.yaml。server1.yaml 是一份功能完整的本地配置要点包括clusterName: distributed-testAPI 端口默认SERVER_PORT:-8585、管理端口SERVER_ADMIN_PORT:-8586数据库 URL 默认指向本机依赖容器jdbc:mysql://localhost:3306/openmetadata_db?allowPublicKeyRetrievaltrueuseSSLfalseserverTimezoneUTC用户openmetadata_userHikariCP 连接池maxSize: 100、minSize: 20搜索后端searchType: opensearchlocalhost:9200批量参数batchSize: 100、payLoadSize: 1048576010MB日志 pattern 固定携带节点前缀[server-1] %level [%d{ISO8601,UTC}] ...额外提供enableVirtualThreadsJava 21 虚拟线程、cache.provider默认 none、bulkOperation线程池等与生产配置同构的开关方便在调试环境中对照行为。5. 端口规划与可配置项三个节点的端口映射README 原文表格ServerAPI PortAdmin PortServer 185858586Server 285878588Server 385898590MySQL 占用 3306OpenSearch 占用 9200/9600。README 描述的.env可配置项# 测试数据表数量 TEST_DATA_TABLES10000 # 日志级别 LOG_LEVELINFO # 每服务器堆大小 OPENMETADATA_HEAP_OPTS-Xmx1G -Xms1G另外从 compose 文件可见更多带默认值的变量MYSQL_PORT、OPENSEARCH_PORT、DB_USER/DB_USER_PASSWORD、OM_DATABASE、OPENSEARCH_JAVA_OPTS等均可通过环境变量覆盖便于与已有基础设施共存。6. 底层机制基于数据库的分布式协调理解本测试环境「为什么三台普通服务器就能协作」需要看分布式索引的实现源码。核心实现位于 openmetadata-service 的 distributed 包设计文档见 DISTRIBUTED_INDEXING.md。6.1 三张协调表所有协调状态存于共享 MySQL共三张表search_index_job任务元数据与聚合统计状态、总/成功/失败记录数、staged 索引前缀、创建者、时间戳、错误信息等search_index_partition工作单元表每个分区记录entityType、rangeStart/rangeEnd、priority、status、assignedServer、claimedAt、lastUpdateAt心跳、retryCount等字段search_reindex_lock分布式锁字段含lockKey、jobId、serverId、lastHeartbeat、expiresAt用于保证「同一时刻只有一个 reindex 任务」。6.2 关键组件与职责从源码结构看各组件分工如下组件文件职责DistributedSearchIndexCoordinatorDistributedSearchIndexCoordinator.java任务/分区/锁的管理中枢聚合分区统计输出Claimed partition: table_0-999 (1000 records)等日志DistributedSearchIndexExecutorDistributedSearchIndexExecutor.java单节点上的作业编排建任务、算分区、管 worker 线程、刷锁与心跳PartitionWorkerPartitionWorker.java处理单个分区分页读库、批量写 ES/OS、更新游标、失败退避重试PartitionCalculatorPartitionCalculator.java按实体计数与复杂度因子估算工作量用 LPT最长处理时间优先算法做负载均衡并受分区上限约束JobRecoveryManagerJobRecoveryManager.java启动时的崩溃恢复识别无主任务、把卡死的 PROCESSING 分区重置回 PENDINGPollingJobNotifier/OrphanJobMonitor同目录DB 轮询通知与孤儿任务监控对应架构图中的 Polling (DB-based coordination)6.3 原子分区认领与过期检测多节点抢任务不会产生竞态因为认领使用FOR UPDATE SKIP LOCKED的原子 UPDATEDISTRIBUTED_INDEXING.md 原文UPDATE search_index_partition SET status PROCESSING, assignedServer ?, claimedAt ?, startedAt ?, lastUpdateAt ? WHERE id ( SELECT id FROM search_index_partition WHERE jobId ? AND status PENDING ORDER BY priority DESC, entityType, partitionIndex LIMIT 1 FOR UPDATE SKIP LOCKED )分区状态机为PENDING → PROCESSING → COMPLETED / FAILED另有超时回退分区心跳过期lastUpdateAt now - 5 分钟且重试次数未达上限时重置为 PENDING超限则标记 FAILED。关键常量设计文档表格常量值含义LOCK_TIMEOUT_MS5 分钟分布式锁 TTLLOCK_REFRESH_INTERVAL_MS1 分钟锁心跳间隔PARTITION_CLAIM_TIMEOUT_MS5 分钟分区过期阈值MAX_PARTITION_RETRIES3每分区最大重试次数MAX_PARTITIONS_PER_ENTITY_TYPE10,000单实体类型分区上限MAX_TOTAL_PARTITIONS50,000单任务分区总数上限索引写入采用 staged 模式reindex 期间数据只写入暂存索引处理成功后才提升别名避免在线索引在批量重建期间被直接改写。7. 验证分布式行为三个测试场景7.1 验证分区在三节点间的分布启动全部 3 台服务器加载测试数据./scripts/perf-test.sh --tables 10000触发重建./scripts/trigger-reindex.sh --recreate观察日志./scripts/logs.sh -f --grep partition。预期看到各节点交错认领不同分区README 示例[SERVER-1] INFO Claimed partition: table_0-999 (1000 records) [SERVER-2] INFO Claimed partition: table_1000-1999 (1000 records) [SERVER-3] INFO Claimed partition: table_2000-2999 (1000 records) [SERVER-1] INFO Completed partition: table_0-999 ...这些日志对应DistributedSearchIndexCoordinator中的分区认领/完成事件。7.2 测试服务器故障恢复以较多分区启动一次重建中途停掉一台docker stop distributed_test_om_server_2观察其余服务器如何接管其「孤儿分区」验证整个任务最终成功完成。对应源码机制节点崩溃后其锁在LOCK_TIMEOUT_MS5 分钟后过期JobRecoveryManager的启动恢复逻辑performStartupRecovery()会把心跳过期的分区重置回 PENDING由其他存活节点的 worker 认领网络分区场景下则走「锁过期 → 孤儿任务检测 → 恢复或失败旧任务」路径。7.3 检查任务状态# 通过 API 查询 SearchIndexingApplication 状态 curl -s http://localhost:8585/api/v1/apps/name/SearchIndexingApplication/status | jq # 直接查分区表 docker exec -it distributed_test_mysql mysql -uopenmetadata_user -popenmetadata_password openmetadata_db \ -e SELECT status, COUNT(*) FROM search_index_partition GROUP BY statusAPI 端点对应 AppResource 中的/name/{name}/status路径apps资源而search_index_partition正是 6.1 节的工作单元表。设计文档还给出更细的监控 SQL例如按assignedServer, status聚合查看分区分布、以及用lastUpdateAt (UNIX_TIMESTAMP() * 1000 - 300000)找出过期分区进度还会每 2 秒经 WebSocket 频道searchIndexJobStatus广播任务级与实体级统计。8. 故障排查README 的 Troubleshooting 章节覆盖四类常见问题命令均可直接复用服务器无法启动—— 先确认端口是否被占用lsof -i :8585 lsof -i :8587 lsof -i :8589数据库连接问题—— 验证 MySQL 可达性与凭据docker exec -it distributed_test_mysql mysql -uopenmetadata_user -popenmetadata_password -e SELECT 1OpenSearch 未就绪—— 检查集群健康curl http://localhost:9200/_cluster/health?pretty查看完整日志# 所有容器日志 docker compose logs -f # 特定容器 docker logs -f distributed_test_om_server_1若三个 OM 容器长期卡在 unhealthy可按依赖顺序排查OpenSearch 健康检查green/yellow→migrate服务是否completeddocker inspect distributed_test_migrate→ 各 OM 容器的 8586 端口/healthcheck。9. 目录结构与延伸阅读README 描述的目录组织含文档化的scripts/与.env实际以当前仓库文件为准distributed-test/ ├── docker-compose.yml # Full environment (3 OM servers deps) ├── config/ │ └── mysql-init.sql # Database initialization ├── scripts/ # start.sh / stop.sh / logs.sh / trigger-reindex.sh / perf-test.sh ├── local/ │ ├── docker-compose-deps.yml # Dependencies only (for IDE debugging) │ ├── server1.yaml # Server 1 config (port 8585) │ ├── server2.yaml # Server 2 config (port 8587) │ ├── server3.yaml # Server 3 config (port 8589) │ └── run-local-servers.sh # Start servers locally └── README.md想进一步深入分布式索引本身建议按此顺序阅读仓库源码DISTRIBUTED_INDEXING.md —— 任务生命周期INITIALIZING → READY → RUNNING → COMPLETED / COMPLETED_WITH_ERRORS / FAILED / STOPPED、分区状态机、超时与限制、恢复场景服务器崩溃、网络分区、ES 过载的完整设计DistributedSearchIndexCoordinator.java 与 PartitionWorker.java —— 协调与执行的落点JobRecoveryManager.java —— 启动恢复与孤儿检测SearchResource.java —— reindex API 入口/reindexEntities。设计文档同时明确了该机制的边界条件同一时刻只允许一个 reindex 任务由search_reindex_lock强制reindex 期间实体增删会使计数略有偏差性能上建议单分区 5,000–10,000 个实体、每节点 worker 线程与 CPU 核数匹配常见 4–8水平扩展通过增加节点完成。本测试环境正是为验证这些承诺而搭建的。【免费下载链接】OpenMetadataThe Open Context Layer for Data and AI , OpenMetadata is the open platform for building trusted data context and business semantics for humans, AI assistants, and agents.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMetadata创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考