搜狗开源框架发布纯自研 C++ Kafka 客户端
搜狗于今年 7 月发布了 C++异步调度服务器引擎——Workflow,除了计算通信融为一体的高性能特点以外,还集成了多种常用的网络协议,包括:Http、Redis、MySQL,所有协议都是纯自研自解析,无需依赖第三方库,而具体协议所对应的资源复用和线程调度等都由 Workflow 以统一的方式去进行管理,目前获得了越来越多开发者的青睐和肯定。而最近,Workflow 又支持并发布了一项复杂的通用网络协议:Kafka,使得所有使用 Workflow 及其生态项目的开发者都可以通过统一而简便的方式与 Kafka 交互,这也是业内唯一一款使用 C++语言实现的 Kafka 客户端,值引得开源社区开发者们的关注。
一、开发背景
在 Workflow 发布 Kafka 客户端之前,业内用得比较多的是 librdkafka,但这个纯 C 的 kafka 客户端有许多不足,以下是我们原先使用时遇到的部分问题:
1、线程资源和网络资源消耗比较多
2、接口设计比较复杂臃肿,使用成本比较高
3、Kafka 版本兼容性不是很好
4、消耗资源高,但是性能却不高
5、broker 主从切换低版本出现服务 hang 住情况,高版本偶发丢数据问题
6、异步同步偶发出现丢数据情况
针对这些问题,更好的替代方案是 Workflow 的 Kafka 客户端:https://github.com/sogou/workflow
由于实现在 Workflow 的基础上,作为 Kafka 客户端即具有超高性能、超大吞吐和极省的资源占用等特点,且和其他协议的接口一样,此 Kafka 客户端还具有接口清晰,代码可读性强等优点,不仅节省机器成本还节省人力维护成本,非常值得一试。
二、新一代高性能 C++ Kafka 客户端
Workflow 的 Kafka 客户端使用接口非常简洁,首先需要创建一个 client 对象:
其他使用方式与框架内的其他任务无异,使用 Workflow 的同学可以瞬间上手:
为什么 Workflow 的 Kafka 客户端能有以上的优点呢?主要得益于以下三方面的细节:
一. 内部基于 Workflow 的任务流实现。Workflow 的核心设计理念是将任务抽象成"任务流"的概念,这样一个任意复杂的任务可以拆分成若干个并行任务流和串行任务流,它们之间通过串联、并联等方式组成一个或者多个串并联图,然后由 Workflow 内部的引擎高效异步地执行。
以 Kafka 协议的 fetch 消息为例,下图是执行过程中任务流的串并联图:
一个 fetch 消息的任务由一组任务组成,其中包括获取 Kafka Broker 的 Meta 任务、一系列的消费者组相关的任务、获取 offset 的任务和真正的拉取消息的任务。前面的多个任务由于有依赖关系,所以组成串联任务;而最终拉取消息的任务和 Broker 的个数有关,因此可以将它转换成一个 broker 数目相同的并行任务。这样做一方面可以使得逻辑很清晰,同时也可以保证执行的高效性。
二. 连接复用。传统的网络通信往往是在程序初始化的时候,创建大规模连接池来提高网络吞吐,这么做的一个弊端是系统资源占用过多,会导致降低程序的鲁棒性。而目前这个 Kafka 客户端由于内部是基于 Workflow 框架,Workflow 对连接的管理做了很多优化,可以在保证高效高吞吐的同时,将资源控制在一个合理的范围内。
三.内存管理。为了方便用户的使用,内部的所有对象都基于计数实现,通过工厂方法创建任务后,在回调函数中实现处理逻辑即可。内存的分配和释放都是框架自动完成,全程无需手动操作任务级别的内存,非常方便;同时它的逻辑又是完备自洽的,保证了高效可靠。
三、插件式发布,与 Workflow 完美融合
基于 Workflow 精巧的层次结构,Kafka 协议是以插件式发布的,即无需安装 Kafka 的用户不会把 Kafka 相关代码编译进去,由此可以看出 Workflow 本身的架构解耦和模块对称性都做得非常优秀。
而 Kafka 的协议由于需要多次交互,Workflow 复合任务又天生支持内部交互的隐藏,使得整体使用上对用户非常简洁透明。基于二级工厂模式也可以把许多全局信息统一管理到内存中,也是工程上结合的一大亮点。
可以说,Kafka 协议与 Workflow 的融合相当完美,且目前在搜狗已经大规模使用,经得住工业级检索系统大规模请求的实际考验,欢迎业内需要的开发同学积极尝试并与我们热心的开发小组进行技术交流。
评论