首先kafka的消费者组机制一直很受诟病,就是很受诟病的。
过度设计,也不实用,永远在做没必要的重平衡。很多情况架构上和客户端上都可以自己做。
其次,如果用了咋办
什么时候会发生rebalance?
前面我们已经说到,rebalance 其实就是对 partition 进行重新分配。那么什么时候会发生 rebalance 呢?其实在以下三种情况下,会触发 rebalance:
- 订阅 Topic 的分区数发生变化。
- 订阅的 Topic 个数发生变化。
- 消费组内成员个数发生变化。例如有新的 consumer 实例加入该消费组或者离开组。
-
「消费组内成员个数发生变化」的几种情况:
- 新成员加入
- 组成员主动离开
- 组成员崩溃
--------------------------------------------------------------------
20220421,
一次重平衡复现实验,重启了一台机器上的各个consumer group成员。用了4分钟最终完成重平衡。
第一次报警:
{"Level":"error","Time":"2022-04-21T20:38:02.9884226+08:00","LoggerName":"","Message":"Cleanup session MemberID :[vwin04_hunter-69c09b1d-a46b-40f8-8e55-e7c07580b46b] , GenerationID :[3980] , Claims :[map[vsdir:[12 13 14 15 16 17]]]","Caller":{"Defined":true,"PC":23615323,"File":"/groupconsumer.go","Line":67,"Function":"cloudscan/pubsub.(*GroupConsumer).Cleanup"},"Stack":"","Subject":"csscand告警 engine: [hunter] , version:[1.7.0]","IP":"","HostName":"vwin04"}
最后一次报警:
{"Level":"error","Time":"2022-04-21T20:42:08.2430919+08:00","LoggerName":"","Message":"Cleanup session MemberID :[vwin04_comodo-724c94cf-551f-4cd4-abb5-389c47f63a07] , GenerationID :[11674] , Claims :[map[vsdir:[16 17 18 19 20 21 22 23]]]","Caller":{"Defined":true,"PC":23615323,"File":"/groupconsumer.go","Line":67,"Function":"cloudscan/pubsub.(*GroupConsumer).Cleanup"},"Stack":"","Subject":"csscand告警 engine: [comodo] , version:[1.7.0]","IP":"","HostName":"vwin04"}
------------------------------------------------------------------------------
20220419
调了
config.Consumer.Group.Session.Timeout = time.Second * 120
加了这一行config.Consumer.Group.Rebalance.Timeout = config.Consumer.Group.Session.Timeout
config.Consumer.Group.Rebalance.Timeout rebalance的timeout 设置为了2分钟,并且和Session.Timeout相等
20220421
Group vsarcabit remove dynamic members who haven't joined: Set(10-52-6-136_arcabit-590f2304-7918-44f7-9c79-753d548bd41e) (kafka.coordinator.group.GroupCoordinator)
参考https://zhuanlan.zhihu.com/p/109574627
RPC
与 Rebalance 相关有 JoinGroup 和 SyncGroup 两个接口,再加上 Heartbeat 接口。
JoinGroup 接口演进到了第六版:
JoinGroup Request (Version: 6) => group_id session_timeout_ms rebalance_timeout_ms member_id group_instance_id protocol_type [protocols] TAG_BUFFER
group_id => COMPACT_STRING
session_timeout_ms => INT32
rebalance_timeout_ms => INT32
member_id => COMPACT_STRING
group_instance_id => COMPACT_NULLABLE_STRING
protocol_type => COMPACT_STRING
protocols => name metadata TAG_BUFFER
name => COMPACT_STRING
metadata => COMPACT_BYTES
JoinGroup Response (Version: 6) => throttle_time_ms error_code generation_id protocol_name leader member_id [members] TAG_BUFFER
throttle_time_ms => INT32
error_code => INT16
generation_id => INT32
protocol_name => COMPACT_STRING
leader => COMPACT_STRING
member_id => COMPACT_STRING
members => member_id group_instance_id metadata TAG_BUFFER
member_id => COMPACT_STRING
group_instance_id => COMPACT_NULLABLE_STRING
metadata => COMPACT_BYTES
当有任何新的 Consumer 发起 JoinGroup 后,Coordinator 会进入 PreparingBalance 状态,递增 generationID,随后等待活跃的所有 Consumer 重新加入 Group,等待的期限为 rebalance_timeout_ms(默认值为 60s)。
里面有两个 timeout 值得注意:
- session_timeout_ms:表示 Coordinator 如果超过该超时值没有收到心跳,则认为 session 过期;
- rebalance_timeout_ms:表示 Coordinator 等待所有 Consumer 重新申请加入的最大时限;
假如我扩容 100 个 Consumer,要等多久生效?显然不能是 60s。那么 Coordinator 怎么知道要等到什么时候呢?等待所有活跃 session 的 Consumer 都发送过 JoinGroup 便可以了。每个 Consumer 每 3s 与 Coordinator 发一次心跳,这也意味着一次 rebalance 大约需要 3s 左右的等待。如果减少心跳的时间间隔,Rebalance 的生效时间应能够相应减少。
也就是说,所有客户端的 JoinGroup 会阻塞直到所有活跃 Session 的 Consumer 皆执行了 JoinGroup 为止。随后 ConsumerGroup 将进入 CompletingBalance 状态。
haven't joined