介绍
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,发送数据步骤如下。
初始化 client
GetTopic 或者 ListSchema 获取 schema 信息
ListShard 获取 shard 信息,并筛选出 ACTIVE 状态的 shard
数据发送前攒批
选择一个 shard 调用 PutRecordsByShard 写入数据
发送成功,继续步骤 4
发送失败,根据相应错误做出判断,若可重试,重新步骤 5,若不可重试,做出相应处理
周期性调用 ListShard 更新 shard 信息
使用 Producer ,发送数据步骤如下(以异步方式发送为例)
初始化 Producer 并注册回调函数
异步发送 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 消费流程:
初始化 client
GetTopic 或者 ListSchema 获取 schema 信息
ListShard 获取 shard 信息,并给每个任务手动分配需要消费的 shard
OpenOffsetSession 开启消费,并获取服务端保存的 offset
通过 offset 调用 GetCusor 获取消费的 cusor 信息
根据 cursor 调用 GetRecords 读取数据
读取数据为空,sleep 一段时间,继续步骤 6
读取数据不为空,处理数据并更新 cursor,继续步骤 6
周期性调用 ListShard 更新 shard 信息,周期性调用 CommitOffset 更新消费点位
Consumer 消费流程
初始化 Consumer,初始化好以后会自动给每个节点分配好消费的 shard,并自动获取服务端保存的点位
调用 Read 读取数据
读取数据为空,继续步骤 2,客户端内部控制间隔
读取数据不为空,处理数据,并继续步骤 2
Consumer 的优势除了易用性之外,最重要的是解决了上面提到的几个比较棘手的问题。相对于 Low-Level SDK,Consumer 的优势整理如下。
逻辑简单,易用性更强
稳定性更好,对于网络抖动等可重试异常,客户端内部直接重试,并且重试次数可配置
自动感知扩缩容,并可以完善处理好消费顺序的问题
动态分配 shard,节点的加入和退出都可以动态调整 shard 分配,用户无需做额外操作
自动维护点位信息,用户无需做额外操作。
SDK 状态
语言 | Low-Level | Hig-Level |
JAVA | 支持 | 支持 |
C++ | 支持 | 支持 |
Python | 支持 | 支持 |
Golang | 支持 | 暂不支持 |