转发请注明原创地址:https://www.cnblogs.com/dongxiao-yang/p/10602799.html

某日晚高峰忽然集群某个大流量业务收到lag报警,查看客户端日志发现reblance一直无法成功,日志如下

根据客户端日志显示consumer在尝试joingroup的过程中收到了服务端COORDINATOR状态不正常的信息,怀疑是服务端负责这个consumer-group的broker在coordinator元信息管理上出现了问题。

于是跑到对应的节点上看一下server日志,发现在一台刚才有过重启的服务节点上产生如下日志

Failed to append 363 tombstones to __consumer_offsets-38 for expired/deleted offsets and/or metadata for group consumer-group. (kafka.coordinator.GroupMetadataManager)
org.apache.kafka.common.errors.NotLeaderForPartitionException: Leader not local for partition __consumer_offsets-38 on broker 。

怀疑是这个服务重启的过程中__consumer_offset分区有部分数据或者文件有异常导致coordinator无法提供服务导致,停掉有问题节点后发现客户端reblance很快就成功了,于是怀疑问题节点产生了坏文件,后续删除对应分区可以重启成功服务,但是对应group的业务又开始报错

20 Mar 2019 15:31:32,000 INFO  [PollableSourceRunner-KafkaSource-bl_app_event_detail_source] (org.apache.kafka.clients.consumer.internals.ConsumerCoordinator$OffsetCommitResponseHandler.handle:542)  - Offset commit for group consumer-group failed due to NOT_COORDINATOR_FOR_GROUP, will find new coordinator and retry
20 Mar 2019 15:31:32,001 INFO  [PollableSourceRunner-KafkaSource-bl_app_event_detail_source] (org.apache.kafka.clients.consumer.internals.AbstractCoordinator.coordinatorDead:529)  - Marking the coordinator 2147483543 dead.

kafka 自从0.9以来摒弃了consumer把offset存在zk的做法而是都存到了__consumer_offsets这个系统topic里面,同时consumer端的reblance都是依靠server端的coordinator负责调度协调。至于每个group怎么选择对应broker节点是根据下面这个简单的hashcode对__consumer_offsets分区数取模的算法得出来的,

  def partitionFor(groupId: String): Int = Utils.abs(groupId.hashCode) % groupMetadataTopicPartitionCount

所以看上去是重启节点拉起来后客户端发现对应的offset分区leader又活了,但是活过来的leader却告知客户端NOT_COORDINATOR_FOR_GROUP这个矛盾。但是明明有问题的offset文件已经被手动删除掉了,重新拉副本也成功了,为什么还是会有join group不成功的现象呢。

继续查看问题节点,发现问题节点在Loading group metadata for之类的日志的时候一直没有输出对应的问题group相关日志,初步判断broker重启过程中load group信息的时效出了问题。

  def onLeadershipChange(updatedLeaders: Iterable[Partition], updatedFollowers: Iterable[Partition]) {
// for each new leader or follower, call coordinator to handle consumer group migration.
// this callback is invoked under the replica state change lock to ensure proper order of
// leadership changes
updatedLeaders.foreach { partition =>
if (partition.topic == GROUP_METADATA_TOPIC_NAME)
groupCoordinator.handleGroupImmigration(partition.partitionId)
else if (partition.topic == TRANSACTION_STATE_TOPIC_NAME)
txnCoordinator.handleTxnImmigration(partition.partitionId, partition.getLeaderEpoch)
}

如上述代码所示,kafka在offset分区重新被选举为leader的时候才会去加载对应的group信息,而且所有新leader是foreach单线程循环,如果其中有一个慢的剩下的group都会受到影响。查看问题节点果然除了被删掉的offset分区还有一个分区offset历史文件很多,多到500G的体量,这和offset这种只保存最新数据的场景明显是不符合的,这个大小会导致服务端加载offset信息长到无法接受的程度。

为了尽快回复offset元信息,把问题节点的offset partition全都重新分配到其他节点,在重分配的过程中发现新的副本会不断的删除同步过来的过期数据最后结束后整个分区的大小只有几十M,于是坚定了原来分区大小不正常的判断 。对于__consumer_offsets这种compact策略的topic,kafka内部是有一个专门的logcleaner线程负责日志的合并,但是刚开始出问题的节点经过了几次重启,原始的现场早已不存在,于是把整个集群每个服务挨个查了一遍,果然在另一台看似正常的机器上同样发现了一个很大的offset分区,jstack了一下,发现kafka-log-cleaner-thread这个线程已经没了!重启该服务后发现问题分区的日志也开始正常删除。可惜的是由于服务日志只保留了最近7天的,kafka-log-cleaner-thread的错误日志已经找不到了,这个有待后续复现确认。

回顾了一下处理问题过程中出现的其他现象,其实都是有提示的,像是关掉问题节点的时候server日志会报

WARN Map failed (kafka.utils.CoreUtils$)
java.io.IOException: Map failed
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:940)
at kafka.log.AbstractIndex$$anonfun$resize$1.apply(AbstractIndex.scala:111)
at kafka.log.AbstractIndex$$anonfun$resize$1.apply(AbstractIndex.scala:101)

以及kafka jvm第一次崩掉的hs_err_pid日志会提示内存不足

Native memory allocation (mmap) failed to map 65536 bytes for committing reserved memory

由于kafka使用的mmap方式映射了数据文件以及索引,这个mmap failed就已经提示了文件过多。

结论:kafka的offset数据每个group会根据hash取模的方式发到一个固定的_consumer_offsets分区中,_consumer_offsets分区的leader负责对应groupid的coordinator服务,_consumer_offsets

的删除是由kafka-log-cleaner-thread执行的,这个线程个数默认是1,如果线程崩掉了offset历史分区文件会一直无法删除,导致jvm崩掉并且服务恢复的时候group元信息长时间的无法加载导致reblacne报错。

记一次kafka客户端NOT_COORDINATOR_FOR_GROUP处理过程的更多相关文章

  1. 【原创】大叔问题定位分享(5)Kafka客户端报错SocketException: Too many open files 打开的文件过多

    kafka0.8.1 一 问题 10月22号应用系统忽然报错: [2014/12/22 11:52:32.738]java.net.SocketException: 打开的文件过多 [2014/12/ ...

  2. python confluent kafka客户端配置kerberos认证

    kafka的认证方式一般有如下3种: 1. SASL/GSSAPI  从版本0.9.0.0开始支持 2. SASL/PLAIN   从版本0.10.0.0开始支持 3. SASL/SCRAM-SHA- ...

  3. 解Bug之路-记一次存储故障的排查过程

    解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...

  4. Kafka客户端内存缓冲GC处理机制--客户端内存

    1.Kafka的客户端缓冲机制 首先,先得给大家明确一个事情,那就是在客户端发送消息给kafka服务器的时候,一定是有一个内存缓冲机制的. 也就是说,消息会先写入一个内存缓冲中,然后多条消息组成了一个 ...

  5. SpringMVC处理客户端请求的过程

    SpringMVC处理客户端请求的过程 以程序部署在Tomcat上为例,网站程序使用SpringMVC框架开发. 1.客户端发起一个访问网站的请求(如: localhost:8080/index). ...

  6. Kafka 客户端实现逻辑分析

    这里主要分析kafka 客户端实现 (代码分析以perl kafka实现为准) kafka客户端分为生产者和消费者,生产者发送消息,消费者获取消息. 在kafka协议里客户端通信中用到的最多的四个协议 ...

  7. 转:Kafka 客户端TimeoutException问题之坑

    原文出自:http://www.jianshu.com/p/2db7abddb9e6 各种TimeoutException问题 会抛出org.apache.kafka.common.errors.Ti ...

  8. Erlang 编写 Kafka 客户端之最简单入门

    Erlang 编写 Kafka 客户端之最简单入门 费劲周折,终于测通了 erlang 向kafka 发送消息,使用了ekaf 库,参考: An advanced but simple to use, ...

  9. kafka客户端发布record(消息)

    kafka客户端发布record(消息)到kafka集群. 新的生产者是线程安全的,在线程之间共享单个生产者实例,通常单例比多个实例要快. 一个简单的例子,使用producer发送一个有序的key/v ...

随机推荐

  1. nodejs+mysql入门实例

    此前我已准备好mysql,使用的是PHP的组合包Appserv 手动添加数据库依赖: 在package.json的dependencies中新增, “mysql” : “latest”, { &quo ...

  2. 18.并发类容器MQ

    package demo7.MQ; public class QueueData { private int id; private String name; private String taskC ...

  3. [转载]Delphi 版 everything、光速搜索代码

    近日没啥事情,研究了一下 everything.光速搜索原理.花了一个礼拜时间,终于搞定. 废话不多说,直接上代码: unit uMFTSearchFile; { dbyoung@sina.com 2 ...

  4. px、em、rem的区别

    一.PX: px像素(Pixel):相对长度单位.像素px是相对于显示器屏幕分辨率而言的. PX特点 1. IE无法调整那些使用px作为单位的字体大小: 2. 国外的大部分网站能够调整的原因在于其使用 ...

  5. [Python爬虫] 之二十八:Selenium +phantomjs 利用 pyquery抓取网站排名信息

    一.介绍 本例子用Selenium +phantomjs爬取中文网站总排名(http://top.chinaz.com/all/index.html,http://top.chinaz.com/han ...

  6. 实现自动文本摘要(python,java)

    参考资料:http://www.ruanyifeng.com/blog/2013/03/automatic_summarization.html http://joshbohde.com/blog/d ...

  7. Hadoop 伪分布式上安装 Hive

    下载地址:点此链接(P.S.下载带bin的安装包) 下载hive后放到虚拟机文件夹内,打开: -bin.tar.gz -C /home/software/ 修改并保存环境配置: gedit /etc/ ...

  8. C#/Sqlite-单机Window 程序 sqlite 数据库实现

    数据库分析和选择 Excel 文件 做数据源 限制性比较强,且不适合查询,分析 等操作 Access 数据库 Access 管理数据界面和功能不强 mysql 和sql server 功能满足,但需要 ...

  9. Silverlight 安装失败 提示 消息 ID 1603 的解决方法

    消息 ID: 1603 安装过程中出现错误.请执行以下步骤 原因是在以前安装过silverlight,没有安装成功或者没有彻底卸载干净,遗留了一些文件,尤其是安装时突然中断的时候会出现这个问题. 解决 ...

  10. java中Xml、json之间的相互转换

    旁白: 最近关于xml与json之间的转换都搞蒙了,这里写一个demo,以后备用. 正题: project格式是: jar包是一个一个检出来的,还算干净了. 代码: 工具类: package exer ...