SDK 概述

介绍

DataHub 的 SDK 目前主要分为两种,分别是 Low-Level 和 High-Level,Low-Level 实现了 DataHub 服务端定义的 API,一般适合做资源的管理;High-Level SDK 一般称为 client-library,分为两个大模块 Producer 和 Consumer,是对 Low-Level SDK 读写相关 API 的上层封装,更合适做数据的读写。

Low-Level SDK 介绍

DataHub 是 RESTful  风格 的 API ,Low-Level SDK 的每个接口都会对应一个服务端的 API。

以创建 Project 的 API 为例,API 如下所示。

  POST /projects/<ProjectName> HTTP/1.1
  x-datahub-client-version: 1.1
  Date: Tue, 08 May 2018 09:47:48 GMT
  Authorization: AuthorizationString
  Content-Type: application/json
  Content-Length: xxx
  {
      "Comment": "test project"
  }

对应的 JAVA SDK 的 API 为。

/**
* Create a datahub project.
*
* @param projectName The name of the project.
* @param comment     The comment of the project.
* @throws DatahubClientException Throws DatahubClientException
*/
CreateProjectResult createProject(String projectName, String comment);

High-Level SDK 介绍

Low-Level SDK 除了资源管理之外,最主要的功能就是写入和消费,但是单个 API 是无法完成写入和消费,需要多个 API 进行组合才能完成,并且每个 API 使用不合理都可能会造成导致最终无法读写,即使最终可以运行,但是使用不合理,也会给客户端或者服务端造成一些不必要的压力,出于这些考虑,我们在 Low-Level SDK 的基础上,封装了一层 High-Level SDK,最主要目的就是在读写这个最主要的场景下,简化用户操作,提升 SDK 易用性和稳定性。

Producer

写入数据的场景,我们对比一下一下使用 Low-Level SDK 和 High-Level SDK 的区别,这里只列举使用到的 API。

使用 Low-Level SDK,发送数据步骤如下。

  1. 初始化 client

  2. GetTopic 或者 ListSchema 获取 schema 信息

  3. ListShard 获取 shard 信息,并筛选出 ACTIVE 状态的 shard

  4. 数据发送前攒批

  5. 选择一个 shard 调用 PutRecordsByShard 写入数据

  6. 发送成功,继续步骤 4

  7. 发送失败,根据相应错误做出判断,若可重试,重新步骤 5,若不可重试,做出相应处理

  8. 周期性调用 ListShard 更新 shard 信息

使用 Producer ,发送数据步骤如下(以异步方式发送为例)

  1. 初始化 Producer 并注册回调函数

  2. 异步发送 sendAsync

从上面的对比可以看出,Producer 在写入场景,更加易用和稳定,下面是 High-Level 相较于 Low-Level 的优势整理。

  • 逻辑简单,易用性更强

  • 稳定性更好,对于网络抖动等可重试异常,客户端内部直接重试,并且重试次数可配置

  • 自动感知扩缩容

Consumer

对于消费的场景,使用 Low-Level SDK 使用会更复杂,因为除了相关的 meta 信息外,还需要解决几个更棘手的问题。

  • 每个 shard 都会有消费点位,点位需要提交到周期性提交到服务端,并在启动的时候从服务端获取

  • 单个 shard 是无法在多个节点消费的,如果多个节点是的消费场景,那么 shard 如何分配是一个非常棘手的问题

  • 对于消费顺序有严格要求的场景,如果发生 shard 分裂/合并,假设 shard0 分裂成了 shard1 和 shard2,这个时候 shard1 和 shard2 会平均分配 shard0 的 hash range,shard0 变为只读状态,消费必须先消费完 shard0 的数据以后,再消费 shard1 和 shard2 才能严格保证顺序

Low-Level SDK 消费流程:

  1. 初始化 client

  2. GetTopic 或者 ListSchema 获取 schema 信息

  3. ListShard 获取 shard 信息,并给每个任务手动分配需要消费的 shard

  4. OpenOffsetSession 开启消费,并获取服务端保存的 offset

  5. 通过 offset 调用 GetCusor 获取消费的 cusor 信息

  6. 根据 cursor 调用 GetRecords 读取数据

  7. 读取数据为空,sleep 一段时间,继续步骤 6

  8. 读取数据不为空,处理数据并更新 cursor,继续步骤 6

  9. 周期性调用 ListShard 更新 shard 信息,周期性调用 CommitOffset 更新消费点位

Consumer 消费流程

  1. 初始化 Consumer,初始化好以后会自动给每个节点分配好消费的 shard,并自动获取服务端保存的点位

  2. 调用 Read 读取数据

  3. 读取数据为空,继续步骤 2,客户端内部控制间隔

  4. 读取数据不为空,处理数据,并继续步骤 2

Consumer 的优势除了易用性之外,最重要的是解决了上面提到的几个比较棘手的问题。相对于 Low-Level SDK,Consumer 的优势整理如下。

  • 逻辑简单,易用性更强

  • 稳定性更好,对于网络抖动等可重试异常,客户端内部直接重试,并且重试次数可配置

  • 自动感知扩缩容,并可以完善处理好消费顺序的问题

  • 动态分配 shard,节点的加入和退出都可以动态调整 shard 分配,用户无需做额外操作

  • 自动维护点位信息,用户无需做额外操作。

SDK 状态

语言

Low-Level

Hig-Level

JAVA

支持

支持

C++

支持

支持

Python

支持

支持

Golang

支持

暂不支持