概述
- librdkafka 是kafka官方推荐的C客户端库,提供生产者API、低级和高级消费者API。根据librdkafka提供的文档介绍,其性能也是蛮不错的。近期因项目需要,简单阅读了librdkafka-0.11.1.x版本topic配置和全局配置相关的一些代码,并整理了一些笔记。
- librdkafka 下载地址: https://github.com/edenhill/librdkafka
全局配置和topic配置
配置项分配全局配置和topic配置两类。
- 全局配置如
socket.timeout.ms
,error_cb
,log_cb
,group.id
,rebalance_cb
等. - topic配置如
request.timeout.ms
,auto.commit.enable
,auto.commit.interval.ms
,auto.offset.reset
,offset.store.method
等
- 全局配置如
支持配置项介绍
- 官方介绍 https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md
- 翻译的中文版本网上也有很多,而且基本上和kafka本身的配置是对应的。比如: https://blog.youkuaiyun.com/blackocular/article/details/56677325
相关API
全局配置项主要通过
rd_kafka_conf_set
进行设置,例如:char* group = "rdkafka_consumer_example"; if (rd_kafka_conf_set(conf, "group.id", group, errstr, sizeof(errstr)) != RD_KAFKA_CONF_OK) { fprintf(stderr, "%% %s\n", errstr); exit(1); }
熟悉C的读者可能会有疑问,C没有类似java的反射机制,如何通过一个通用的接口,将字符串描述的配置项映射到结构体的相关字段呢?比如说
"group.id"
这个字符串,如何知道应该把对应的值赋给rd_kafka_conf_s::group_id_str
这个字段呢? 我们后面会看到,这里主要是通过rd_kafka_property
结构的offset和type字段来实现的。topic相关配置主要通过
rd_kafka_topic_conf_set
进行设置,例如:/* Kafka topic configuration */ topic_conf = rd_kafka_topic_conf_new(); rd_kafka_topic_conf_set(topic_conf, "auto.offset.reset", "earliest", NULL, 0);
对于callback以及其他指针类(比如透传参数opaque)的设置,提供了一组专门的设置接口,如:
// 全局配置 rd_kafka_conf_set_dr_msg_cb rd_kafka_conf_set_consume_cb rd_kafka_conf_set_rebalance_cb rd_kafka_conf_set_offset_commit_cb rd_kafka_conf_set_error_cb rd_kafka_conf_set_throttle_cb rd_kafka_conf_set_log_cb rd_kafka_conf_set_stats_cb rd_kafka_conf_set_socket_cb rd_kafka_conf_set_connect_cb rd_kafka_conf_set_closesocket_cb rd_kafka_conf_set_open_cb rd_kafka_conf_set_opaque // topic 配置 rd_kafka_topic_conf_set_opaque rd_kafka_topic_conf_set_partitioner_cb
PS:额外补充一句,librdkafka针对网络异常(如连接失败、通信过程中socket异常),都是通过回调方式通知上层应用的。如果需要处理这些错误,则必须设置相应的回调函数。否则应用程序将无法及时感知到这些网络错误,有可能会出现前面接口一路调用都没有返回错误,但最后生产消息却发送失败的情况。
源码分析
结构体定义
rd_kafka_conf_t
和 rd_kafka_topic_conf_t
- 该结构中的字段基本上与文档中的配置项对应,这里不再详细罗列,有兴趣可直接阅读源码。
rd_kafka_property
- 这个结构用来记录
rd_kafka_conf_t
和rd_kafka_topic_conf_t
的默认值,以及提供一种通用的方法来读取和设置上述两个结构体中的各字段值。换言之,就是为了避免针对这两个conf类型的每一个字段开一个set/get的API,或者虽然提供了一个看似通用的接口,但在其内部通过大量的else if
语句罗列每个字段。 - 有一个该类型的全局数组,定义了所有全局配置项和topic配置项(这意味着,尽管针对全局配置和topic配置的入口API不同,但最终调用的内部实现基本都是一样的。只是根据
scope
字段进行过滤区分)的默认值:
static const struct rd_kafka_property rd_kafka_properties[]
- 每个
rd_kafka_property
结构对应一条配置项. 该结构体定义如下:
struct rd_kafka_property { rd_kafka_conf_scope_t scope; const char *name; enum { _RK_C_STR, _RK_C_INT, _RK_C_S2I, /* String to Integer mapping. * Supports limited canonical str->int mappings * using s2i[] */ _RK_C_S2F, /* CSV String to Integer flag mapping (OR:ed) */ _RK_C_BOOL, _RK_C_PTR, /* Only settable through special set