深度解析:Rest.li API、GMA 存储与元数据服务架构)
DataHub 通用元数据服务GMS深度解析Rest.li API、GMA 存储与元数据服务架构【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub本文基于仓库 docs/what/gms.md 展开。GMSGeneralized Metadata Service是 DataHub 中承载元数据读写能力的微服务层它对外暴露 Rest.li API对内通过 GMA DAO 访问底层元数据存储。读完本文你将理解 GMS 在 DataHub 整体架构中的位置、它与 GMAGeneralized Metadata Architecture及元数据图Metadata Graph的关系、其事件驱动的数据流转链路MCP → MCL → 索引/图更新并能结合仓库源码定位到对应的服务实现与配置文件。什么是 GMSGMS 全称Generalized Metadata Service通用元数据服务。在 DataHub 的元数据架构中凡是 onboarded 到 GMA 的 实体entities 元数据都由一类名为 GMS 的微服务对外提供访问。GMS 具有两个关键特征对外提供 Rest.li APIRest.li 是 LinkedIn 开源的 RESTful 框架rest.liGMS 以 Rest.li 资源Resource的形式暴露元数据的读写接口例如实体 CRUD、Aspect 查询、关系查询等。通过 GMA DAO 访问元数据GMS 自身不直接操作数据库而是依赖 GMA DAO 这一数据访问抽象层来读写底层存储。从源码看GMS 的 Rest.li 资源实现集中在 metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/ 目录下例如EntityResource.java实体Entity的 CRUD 与批量操作EntityV2Resource.java实体 V2 接口支持 Aspect 级读写EntityVersionedV2Resource.java带版本信息的实体接口AspectResource.java单个 Aspect 的读写Relationships.java关系/血缘查询UsageStats.java 与 Analytics.java使用统计与分析。这些资源类统一由 Spring 装配进 GMS 的 Web 容器war 模块见 metadata-service/war共同构成对外可访问的 Rest.li API 面。GMS 与 GMA分布式设计下的元数据服务要理解 GMS必须先理解其背后的架构理念——GMAGeneralized Metadata Architecture见 docs/what/gma.md。GMA 是 DataHub 的后端基础设施它的核心主张是不试图用单一存储满足所有查询而是让多种专用存储各司其职以高效支撑元数据领域最常见的四类查询模式查询模式语义对应存储Document-oriented CRUD以主键如dataset-urn为中心的文档读写文档存储MySQL / Postgres / Cassandra 等 RDBMSComplex queries复杂查询包括跨分布式表的关联关系型/文档存储 搜索索引Graph traversal图遍历血缘、上下游、成员关系图索引Neo4j 等图数据库详见 graph.mdFulltext search and autocomplete全文检索与自动补全搜索索引Elasticsearch详见 search-index.mdGMA 同时拥抱分布式模型每个团队可以拥有、开发并运营自己的元数据服务也就是自己的 GMS 实例而元数据会被自动聚合填充到中央的 元数据图metadata graph 与 搜索索引search index 中。这套机制之所以可行是因为 GMA标准化了元数据模型与访问层——模型统一用 PDL 定义访问统一走 DAO 抽象。而 GMS 文档所描述的正是这一理念下的落地形态GMA 被设计为支持一个分布式的 GMS 集群fleet每个 GMS 服务于 GMA 图中的一部分实体。不过为了简化部署DataHub 当前包含一个集中的、单一的 GMS来服务所有实体。也就是说虽然架构上支持多 GMS 各管一摊但开箱即用的 DataHub 默认以单 GMS 部署方式提供完整功能。这条设计取舍是理解 GMS 定位的关键它是服务实体子集的通用模式也是开箱即用的单例实现。GMS 背后的元数据模型实体、Aspect、关系GMS 对外读写的最小单元不是实体这个整体而是Aspect元数据切面。理解这一层模型才能看懂 GMS 的 API 设计与事件流转。实体Entity一个被建模的元数据类型如 Dataset、Dashboard、CorpUser、Group 等每个实体有唯一的 URN 标识。Aspect元数据切面见 docs/what/aspect.md一个 Aspect 是 PDL 定义的record代表某一类特定元数据例如Ownership所有权、SchemaMetadata表结构、UpstreamLineage血缘上游。Aspect 本身没有意义必须挂载在某个实体上谁的 ownership。Aspect 默认不可变immutable每次更新都产生新版本可配置保留策略例如只保留最近 X 个版本或最近 30 天的变更。关系Relationship见 docs/what/relationship.md关系是两个实体之间的具名有向关联例如Group到User的HasMember。关系中比较实用的建模方式是外键式——在 Aspect 中以 URN 数组保存关联实体再通过Relationship注解显式声明关系类型与目标实体类型图索引会据此生成边。GMS 的 Aspect 级 API如EntityV2Resource、AspectResource正是围绕实体 Aspect的模型设计的客户端提交对某实体某 Aspect 的修改请求GMS 校验并落库再对外广播变更事件。GMS 的读写链路MCP 提案与 MCL 日志GMS 的写入与读取不是孤立的它处于一条完整的事件驱动链路中。这条链路由 docs/what/mxe.md 详细定义核心事件如下Metadata Change ProposalMCP一个变更提案表示请求修改某实体的某个 Aspect。MCP 可以由低层摄取 API 的客户端如各类 ingestion source发出DataHub Python API 也提供发送 MCP 的接口。默认 Kafka topic 为MetadataChangeProposal_v1。GMS 的存储层监听 MCP尝试将其应用到元数据图上。Metadata Change LogMCL一个已提交变更日志在变更成功写入持久化存储后立即发到 Kafka。MCL 分两种Versioned版本化记录 Aspect 的最新状态如所有权、文档默认 topic 为MetadataChangeLog_Versioned_v1Timeseries时间序列记录某一时刻发生的事件型元数据如数据画像profiling默认 topic 为MetadataChangeLog_Timeseries_v1。Platform EventPEDataHub 自身产生的业务事件例如实体变更事件Entity Change Event是 Actions 框架的重要输入默认 topic 为PlatformEvent_v1。一次典型的元数据写入在 GMS 侧的流转是客户端发送 MCP → GMS 存储层校验并写入文档存储 → 提交成功后发出 MCLversioned 或 timeseries→ 下游消费者据此更新图索引与搜索索引。值得注意的是并非每个 MCP 都会产生 MCLGMS 服务层会忽略对元数据的重复变更即幂等去重这一点在 docs/architecture/metadata-serving.md 中有明确说明。Serving 层组件GMS 如何协同工作在 Serving 架构docs/architecture/metadata-serving.md中围绕 GMS 有以下核心组件协同工作组件职责仓库位置Metadata Storage将元数据持久化到文档存储MySQL / Postgres / Cassandra 等 RDBMS见 metadata-ioMetadata Change Log StreamMCL变更提交后经 Kafka 广播 MCL是公开 API外部系统如 Actions 框架可订阅并实时响应见 docs/what/mxe.mdMetadata Index Appliermae-consumer-job消费 MCL将变更应用到图索引与搜索索引metadata-jobs/mae-consumer-jobMetadata Query Serving按查询类型路由到对应存储主键读走文档存储二级索引/全文/高级搜索走搜索索引血缘等复杂图查询走图索引见下节其中mae-consumer-job是一个实体无关entity-agnostic的 Spring 作业它根据变更的 Aspect 类型调用对应的图/搜索索引 Builder 来更新索引。为了保证处理顺序正确MCL 按实体 URN 进行 key 分区——同一实体的所有变更会被单个线程顺序处理从而避免乱序导致的索引不一致。查询路由GMS 面对四类读请求的路径GMS 在提供查询能力时会根据查询类型将请求路由到不同的后端见 metadata-serving.md主键读取例如根据dataset-urn获取表结构元数据→ 路由到文档存储二级索引读取→ 路由到搜索索引也可使用强一致的二级索引支持全文与高级搜索→ 路由到搜索索引复杂图查询如血缘→ 路由到图索引。这套路由背后的抽象是DAOData Access Object体系包括文档存储 DAO、Search DAO 与 Graph DAO。GMS 只依赖 DAO 接口而不关心底层具体是哪种数据库实现这正是标准化访问层的直接体现也是 GMA 文档中distributed model 下各团队可自由选择存储实现能成立的原因。从源码验证 GMS 的实现在仓库中可以找到 GMS 落地实现的关键证据Rest.li 资源层metadata-service/restli-servlet-impl 下以RestLiCollection/RestLiSimpleResource注解声明了一批资源类EntityResource、EntityV2Resource、AspectResource、Relationships、UsageStats、Analytics等它们就是GMS 对外提供 Rest.li API这句话的源码对应。服务装配层metadata-service/factories 与 metadata-service/war 负责把这些资源与 DAO、存储、Kafka 生产者/消费者装配成可运行的 GMS 应用。索引应用作业metadata-jobs/mae-consumer-job 实现了消费 MCL → 更新图与搜索索引的链路对应上文 Metadata Index Applier 组件。DAO 抽象GMA DAO 的说明见 metadata-serving.md它同时支持本地 DAO 与面向远程 GMS 的 Remote DAO——后者意味着客户端进程可以通过 Remote DAO 把读写请求转发到运行中的 GMS这也是多 GMS 分布式部署模式下客户端接入的方式。小结GMS 是 DataHub 元数据服务的门面对内它封装了 GMA 多存储架构的复杂度对外通过标准化的 Rest.li API 提供实体/Aspect 的读写与查询事件机制MCP/MCL让它既能接收外部摄取的数据又能把变更实时广播给索引应用作业与 Actions 框架。理解 GMS就等于理解了 DataHub 元数据平面的主干。想要继续深入可以按以下路径阅读仓库文档元数据模型metadata-model.md、extending-the-metadata-model.md底层架构gma.md、graph.md、search-index.md、urn.md事件体系mxe.mdServing 架构metadata-serving.md元数据摄取metadata-ingestion.md【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考