librdkafka问题小纪
本文介绍在使用kafka的C++客户端librdkafka时遇到的一些问题及解决方法。
1.生产者报“消息尺寸太大导致生成失败”,类似错误如下:
Produce failed: Broker: Message size to large
解决:
通过打印librdkafka的默认配置,知:
message.max.bytes=1000000 //生产者的单条消息的最大尺寸约为1M
fetch.message.max.bytes=1048576 //消费者单条消息最大为1M
因此,当生产者的单条消息大于默认配置时,就会导致如上的错误,解决这个问题要同时考虑producer,broker,consumer的配置。
producer,可以在代码中通过如下的配置修改默认值:
RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
string errstr;
//将生产者的单条消息最大设置为10M
if(conf->set("message.max.bytes","10485760",errstr))
{
std::cout<<errstr<<std::endl;
}
broker端,需要修改broker的配置,并重启kafka集群:
message.max.bytes (默认:1000000) – broker能接收消息的最大字节数,这个值应该比消费端的fetch.message.max.bytes更小才对,否则broker就会因为消费端无法使用这个消息而挂起。
replica.fetch.max.bytes (默认: 1MB) – broker可复制的消息的最大字节数。这个值应该比message.max.bytes大,否则broker会接收此消息,但无法将此消息复制出去,从而造成数据丢失。
consumer端:调整取消息的尺寸
RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
string errstr;
//将消费者的单条消息最大设置为10M
if(conf->set("fetch.message.max.bytes ","10485760",errstr))
{
std::cout<<errstr<<std::endl;
}
当然消息的大小会影响kafka的性能,具体可以参考博客(http://www.cnblogs.com/doubletree/p/4264969.html)
2.因为没有定期回调poll(),导致本地队列满了,发送失败,如果生产者设置了回调函数,可能的错误如下:
Produce failed: Local: Queue full
librdkafka中poll的原型如下:
/*
* Polls the provided kafka handle for events.
* Returns the number of events served.
*/
virtual int poll (int timeout_ms) = 0;
头文件中强调了,必须定期调用poll()函数,这样客户端产生的回调事件才能有机会被调用,如果一直不调用poll()那么类似于生产者成功发送消息的这类事件就不会被回调,导致消息一直被积压
3.关于librdkafka的默认配置
当出现问题时,应该检查下客户端及broker的配置,网络上会给出一些默认配置,但更应该通过代码打印出实际的默认配置,librdkafka的默认示例已经给出了相关代码,可以参考。
RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
int pass;
for (pass = 0 ; pass < 2 ; pass++)
{
std::list<std::string> *dump;
if (pass == 0) {
dump = conf->dump();
std::cout << "# Global config" << std::endl;
} else {
dump = tconf->dump();
std::cout << "# Topic config" << std::endl;
}
for (std::list<std::string>::iterator it = dump->begin();it != dump->end(); )
{
std::cout << *it << " = ";
it++;
std::cout << *it << std::endl;
it++;
}
std::cout << std::endl;
}