librdkafka问题小记

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;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.java的Java类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值