Kafka常见故障分析总结

      最近的项目用Kafka比较多,之前碰到很多问题都是网上搜索解决的,我将我近期踩坑爬坑的一些情况稍微总结一下,希望对后面的同学有点帮助。有错误的地方欢迎留言。

 

kafka基础知识可以参考这里

https://www.w3cschool.cn/apache_kafka/apache_kafka_quick_guide.html

 

本文kafka针对版本kafka_2.12-2.1.0, 不同版本可能现象和配置有差异。

 

  1. Kafka连接类故障 

故障现象:kafka正常启动后,连接不上kafka服务

Kafka服务安装好(很多数据库默认安装之后远程访问是关闭的)之后,一般是监听的

本地的IP端口,需要进server.config修改配置:

advertised.listeners=SASL_PLAINTEXT://192.168.1.227:9092

listeners=SASL_PLAINTEXT://0.0.0.0:9092

   重启后观察端口监听状态,如果监听的不是127.0.0.1,则非本机也可以进行连接了。

 

[root@XX]# netstat -an|grep 9092

tcp        0      0 192.168.1.227:44692     192.168.1.227:9092      ESTABLISHED

tcp6       0      0 :::9092                 :::*                    LISTEN

如果还是无法连接,关注下系统防火墙的端口情况。

  2. 无法消费数据或发送数据异常

2.1 故障现象: 配置多个消费者但只有一个消费者能消费

       Kafka默认安装完,同一个group只能有一个消费者,如果需要多个消费者同时负载消费同一类数据,需要先在kafka server中设置分片。

       kafka服务未设置分片,修改server.config配置文件

       num.partitions=4

  

2.2 故障- 发送数据大于1MB则报错

org.apache.kafka.common.errors.RecordTooLargeException: The request included a message larger than the max message size the server will accept.

修改kafka服务器server.config配置文件,新增配置

message.max.bytes=200000000

replica.fetch.max.bytes=200000000

 

  producer生产者配置:

    max.request.size:   52428800

 

3. 数据重复消费或遗漏

如果数据offset提交失败可能会造成数据重复消费。

3.1 故障现象:消费者无法commit offset.

org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.

这个问题就需要看为什么group被reblacance了。看上文内容是说可能是pool()获取的records后,调用下一次poll的间隔时间太长了,超过了max.poll.interval.ms 。

可以通过将max.pool.interval.ms修改来进行优化,更好的方式是采用多线程的方式来进行处理。接收消息和处理消费在不同的线程中进行处理,这样pool()中只需要将数据提交到一个内存队列中即可。

 

  while(true){
            try {
				ConsumerRecords records = 
                consumer.poll(Duration.ofMillis(50));
				for (ConsumerRecord record : records){
                    KafkaExObject kafkaExObject = null;
					try {
                        kafkaExObject = new KafkaExObject(record.value());
                        //解码后提交到另外的线程处理
                        kafkaProtoProcessManage.addMsg(kafkaExObject);
					}
					catch (Exception ex){
                        logger.error("recv  kafka protocol message decode exception:" , ex );
					}
				}
                  // 接收完消息
				if(!kafkaConfig.getEnableAutoCommit()){
                    consumer.commitSync();
                  }
                  /****如果实际业务处理线程忙不过来,即处理消息的速度慢与接收消息的速度,这里控 
             制一下速度,不要让数据驻留内存太多。 判断是否积压需要根据业务情况来,确保这个poll() 
              调用的间隔不会过大(超过max.poll.interval.ms)而报错。***/
                while (kafkaProtoProcessManage.isBlocked()){
                    logger.warn("Kafka process list may be blocked, have a rest.");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
			} catch (Exception e) {
				e.printStackTrace();
                  logger.error("ProcessProtocolTask ConsumerRecords meet exception:",e);
				// TODO: handle exception
			}
		}

 

 3.2 故障现象:Kafka consumer经常被rebalanced.

实际的生产环境通常比较复杂。对于多台集群多topic多group的场景,通常有以下几种情况。

Kafka在数据多分片的情况数据下,当有新的consumer上下线的时候,对于同一个group的成员来说,需要进行数据的重新分配。简单理解就是家里没来客人的时候,一个方形桌子可以每人坐一边。来了客人的话,大家要挤一挤,都要挪挪位置。

可以通过命令来查看指定group当前有多少消费者,先确保配置没有配错。

原则是不同的topic不要用相同的groupid. 如果是相同的groupId就表示是干同一件事情。

./kafka-consumer-groups.sh  --bootstrap-server 127.0.0.1:9092 --command-config ../config/consumer.properties --group XXXGROUP --describe

 

Kafka常见故障分析总结_第1张图片 

注:command-config命令是在有认证的场景下的参数,如果没有安全认证可以去掉这段。

 

3.3 消费的数据为什么比kafka服务器上的少

     3.3.1 一种常见的情况是配置存在错误,导致一个group存在多个消费者。即数据被其他消费者消费了。

     对于一些复杂业务的场景,公用的一个kafka服务器,多个不同的topic之间配置了相同的groupid, 不同的服务之间交叉使用,这样也会导致kafka经常莫名其妙的被reblance了。

 

     3.3.2 另外一种常见的场景是,生产者提交数据的时候消费者并没有启动,这个时候消费者第一次消费一个新group的数据的时候,可以指定从哪里开始消费。如果历史数据产生了,指定从最新的偏移量开始消费,则表面上看起来消费处理的数据比实际的少。

/***
 * earliest: 从最早的开始消费
 * latest: 从最新的偏移量开始消费
 * kafka 默认缓存7天的数据,如果改成earliest,可以获取7天内的所有数据
 */
propsMap.put("auto.offset.reset", "latest");

 

你可能感兴趣的:(Java,Linux及脚本,数据库)