当前位置: 首页 > news >正文

OpenMetadata社区贡献实战:我是如何为它新增Doris连接器并成功合并PR的

OpenMetadata社区贡献实战:从零实现Doris连接器的完整指南

第一次在GitHub上看到OpenMetadata项目时,我就被它优雅的元数据管理架构所吸引。作为一个长期与数据打交道的开发者,我深知统一元数据管理的重要性。然而当我尝试将公司使用的Apache Doris接入时,却发现1.2版本尚未支持这个新兴的OLAP引擎。这成为了我向OpenMetadata提交第一个PR的契机——下面我将完整分享这次技术贡献的全过程,包括技术实现细节和社区协作经验。

1. 理解OpenMetadata连接器架构

在动手编码前,我花了三天时间系统阅读OpenMetadata的文档和源码。这个项目采用模块化设计,每个数据源连接器都由四个核心部分组成:

  1. JSON Schema定义- 位于openmetadata-spec/src/main/resources/json/schema目录,定义连接参数的验证规则
  2. 前端UI组件- 在openmetadata-ui中实现数据源配置界面
  3. Python元数据提取逻辑- 位于ingestion/src/metadata/ingestion/source/database
  4. 测试用例- 包含连接测试和元数据提取测试

以MySQL连接器为参考,我梳理出需要实现的文件结构:

openmetadata-spec/ └── src/main/resources/json/schema/ ├── entity/services/connections/database/ │ └── dorisConnection.json └── entity/data/table.json ingestion/ ├── setup.py └── src/metadata/ingestion/source/database/ └── doris/ ├── __init__.py ├── connection.py ├── metadata.py └── queries.py openmetadata-ui/ └── src/main/resources/ui/src/ ├── assets/img/service-icon-doris.png └── utils/ServiceUtils/ └── ServiceUtil.tsx

提示:在开始编码前,务必仔细阅读项目的CONTRIBUTING.md文件,了解代码风格、提交规范等要求。我最初就因为没遵循提交信息规范而被要求修改。

2. 定义Doris连接规范

创建dorisConnection.json时,我参考了MySQL的实现但做了Doris特有的调整。关键配置项包括:

{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "DorisConnection", "type": "object", "properties": { "hostPort": { "description": "格式为host:port,Doris默认FE端口为9030", "type": "string" }, "httpPort": { "description": "HTTP API端口,默认为8030", "type": "integer", "default": 8030 }, "queryPort": { "description": "MySQL协议查询端口,默认为9030", "type": "integer", "default": 9030 } }, "required": ["hostPort", "queryPort"] }

Doris特有的数据类型需要在table.json中补充:

{ "definitions": { "dataType": { "enum": [ "HLL", "BITMAP", "QUANTILE_STATE", "LARGEINT", "AGG_STATE" ] } } }

3. 实现Python元数据提取层

在Python实现部分,核心是继承Source基类并实现以下方法:

# ingestion/src/metadata/ingestion/source/database/doris/connection.py from metadata.ingestion.source.database.common_db_source import CommonDbSource class DorisSource(CommonDbSource): @classmethod def create(cls, config_dict, metadata_config): return cls(config_dict, metadata_config) def get_schema_names(self) -> Iterable[str]: query = "SHOW DATABASES" results = self.engine.execute(query) return [row[0] for row in results if row[0] not in ('information_schema')]

Doris特有的元数据查询语句放在queries.py中:

# queries.py GET_TABLE_STATISTICS = """ SELECT COUNT(*) AS row_count, SUM(data_size) AS data_size FROM information_schema.tables WHERE table_schema = %(schema)s AND table_name = %(table)s """

4. 前端集成实战

UI部分需要新增Doris的Logo和配置表单。关键步骤:

  1. 将Doris图标放入src/assets/img目录
  2. ServiceUtil.tsx中注册新的服务类型:
// ServiceUtil.tsx export enum ServiceTypes { DORIS = 'Doris', // ...其他服务类型 } export const serviceTypesConfig = { [ServiceTypes.DORIS]: { label: 'Apache Doris', value: ServiceTypes.DORIS, logo: '/assets/img/service-icon-doris.png', docLink: 'https://doris.apache.org' } };
  1. 创建连接表单组件:
<Form.Item name={['config', 'queryPort']} label="Query Port" rules={[{ required: true }]} initialValue={9030} > <InputNumber min={1} max={65535} /> </Form.Item>

5. 测试与CI/CD挑战

编写测试用例时,我遇到了几个典型问题:

  1. 连接超时:发现Doris的默认连接超时太短,需要在测试配置中调整:
testConnection: timeout: 30000 # 30秒超时
  1. 类型映射问题:Doris的BITMAP类型需要特殊处理:
def get_column_type(self, column_type: str): if 'BITMAP' in column_type: return 'ARRAY<BIGINT>' return super().get_column_type(column_type)
  1. CI环境依赖:需要在.github/workflows中添加pydoris依赖:
- name: Install dependencies run: | pip install pydoris==0.1.0 pip install -e ".[doris]"

6. 社区协作经验

PR提交后,我与维护者进行了多轮有价值的讨论:

  1. 代码审查意见

    • 建议将HTTP端口配置改为可选参数
    • 要求补充完整的单元测试覆盖率
    • 提示需要更新文档中的支持数据源列表
  2. 有效沟通技巧

    • 对每个审查意见都给出明确回应
    • 复杂修改拆分为独立commit
    • 在PR描述中详细说明测试方案
  3. 解决冲突:当主干有更新时,使用rebase而非merge:

git fetch upstream git rebase upstream/main git push -f origin doris-connector

最终PR被合并时,我总结了几个关键收获:

  • 提前在GitHub Issue中讨论方案能减少返工
  • 保持小颗粒度的提交便于审查
  • 完善的测试用例是获得信任的关键
  • 及时响应社区反馈能加速合并流程

这次贡献经历让我深刻体会到,参与开源不仅是提交代码,更是学习工程规范和协作文化的过程。当看到自己的代码被合并到主干时,那种成就感远超预期。

http://www.jsqmd.com/news/569607/

相关文章:

  • 如何快速配置TranslucentTB:Windows任务栏美化终极教程
  • 超高压输电线路空载运行时的电压升高现象解析
  • 使用fetchEventSource构建高效AI智能助手:文件搜索场景的完整实现与深度解析
  • 别再死记公式了!用PyTorch的loss.backward()和optimizer.step()理解反向传播的‘自动挡’
  • 人工智能的拐点:从规模竞赛到智能效率
  • 如何实现格式保留翻译?Hunyuan MT1.5结构化文本处理实战解析
  • 开源工具DLSS Swapper效率提升指南:三步掌握配置技巧与性能优化
  • MT5工具集成指南:如何将文本增强API融入你的工作流
  • 2026年热门的多通道插回损测试仪/多波长检测插回损测试仪/极性一体检测插回损测试仪/光器件在线监控系统插回损测试仪精选厂家 - 品牌宣传支持者
  • ROS插件开发避坑实录:从global_planner插件注册失败到成功加载的完整排错流程
  • Phi-4-mini-reasoning案例展示:Chainlit前端实时显示思维链(CoT)生成过程
  • 智能电表DLMS协议入门避坑指南:从物理层到应用层的5个常见错误
  • ECharts进阶技巧:动态markLine(阈值线、警戒线)与箭头标记的实战应用
  • 智能体AI崛起:本体论如何赋能药物研发新纪元?——2026智能体年深度解析
  • Phi-4-mini-reasoning步骤详解:supervisorctl管理服务全命令解析
  • 如何在5分钟内掌握winget-install?开源命令行工具安装指南
  • 2026年靠谱的S砖/C70S砖源头工厂推荐 - 品牌宣传支持者
  • 如何让老旧Flash内容重获新生?CefFlashBrowser开源工具给出完美答案
  • 如何找到一家靠谱的SEO文章代写网站
  • SiameseAOE模型多模态扩展探索:结合图像信息的属性抽取
  • 多模态AI:当机器真正“看懂”世界
  • TranslucentTB高效配置与本地化实践指南
  • 通俗解读:GPU和NPU,在AI中分别扮演什么角色
  • 技术突破:Bypass Paywalls Clean内容访问解决方案深度解析
  • Cmsemicon中微 BAT32G133GC20SA TSSOP20 嵌入式闪存
  • SentrySearch:开启自然语言检索原生 MP4 视频新时代
  • Mac用户福音:Qwen3-TTS声音克隆在ComfyUI上的M芯片优化方案
  • 别再手动写接口了!用Flask+Ngrok快速给MySQL做个API,Dify直接调用
  • 浏览器中的SQLite管理革命:本地数据库查看工具的创新实践
  • Java微服务集成SmallThinker-3B-Preview实战:SpringBoot构建AI服务