1. 發生場景
版本:confluent 2.0.0
如果因爲some reason觸發了task的rebalance,herder work可能發生異常,導致connect進程退出
2. 異常棧
[2016-06-28 17:22:59,934] ERROR Uncaught exception in herder work thread, exiting: (org.apache.kafka.connect.runtime.distributed.DistributedHerder:166)
java.util.ConcurrentModificationException: KafkaConsumer is not safe for multi-threaded access
at org.apache.kafka.clients.consumer.KafkaConsumer.acquire(KafkaConsumer.java:1294)
at org.apache.kafka.clients.consumer.KafkaConsumer.close(KafkaConsumer.java:1225)
at org.apache.kafka.connect.runtime.WorkerSinkTask.close(WorkerSinkTask.java:128)
at org.apache.kafka.connect.runtime.Worker.stopTask(Worker.java:313)
at org.apache.kafka.connect.runtime.distributed.DistributedHerder$14.onRevoked(DistributedHerder.java:898)
at org.apache.kafka.connect.runtime.distributed.WorkerCoordinator.onJoinPrepare(WorkerCoordinator.java:236)
at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureActiveGroup(AbstractCoordinator.java:207)
at org.apache.kafka.connect.runtime.distributed.WorkerGroupMember.poll(WorkerGroupMember.java:142)
at org.apache.kafka.connect.runtime.distributed.DistributedHerder.tick(DistributedHerder.java:266)
at org.apache.kafka.connect.runtime.distributed.DistributedHerder.run(DistributedHerder.java:159)
at java.lang.Thread.run(Thread.java:745)
[2016-06-28 17:22:59,936] INFO Kafka Connect stopping (org.apache.kafka.connect.runtime.Connect:68)
3. 異常分析
1. 線程模型
confluent存在兩種worker:
(1)控制數據讀寫 的source/sink worker;
(2)負責協調source/sink worker的herder worker;
當rebalance發生時,herder會去主動close worker線程。
2. 關鍵方法
從棧中可以看出,在KafkaConsumer.acquire方法中拋出的異常,分析下該方法:
(1)本意:阻止多個線程對同一分區數據進行讀寫操作。
(2)實現手段:非阻塞鎖的思路,用變量記錄了當前的操作線程。一個線程來操作時,如果發現其他線程也在操作就退出。
這個控制手段很粗暴,它應該做的是“不許多個sink worker同時操作“。而不是一棒子全打死,不許所有線程操作。
3. 問題
herder 主動去殺sink worker,會操作Consumer。如果sink worker正在操作就會發生異常。
4. 解決辦法
- herder close sink worker時,不要走acquire流程;
- herder close sink worker時,先等待一定時長(sleep或者加鎖)
- 在V3.0.0 版本,框架上做了改動,herder 只是置位close標記,不錯其他的操作。