1. 程式人生 > >kafka問題排查之 Java程式碼不進行消費

kafka問題排查之 Java程式碼不進行消費

發現問題

使用 kafka 在linux系統,通過命令測試消費正常, 但在Java 程式碼無法正常接收佇列訊息

控制檯提示資訊:

15:21:33.804 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8886"]
15:21:33.836 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8886"]
15:21:33.841 [main] INFO  org.apache.tomcat.util.net.NioSelectorPool - Using a shared selector for servlet write/read
15:21:33.859 [concurrentMessageListenerContainer-0-kafka-consumer-1] INFO  org.apache.kafka.clients.consumer.internals.AbstractCoordinator - Discovered coordinator platform-010-030-050-167:16792 (id: 2147483647 rack: null) for group test-mengqa.
15:21:33.878 [main] INFO  org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer - Tomcat started on port(s): 8886 (http)
15:21:33.884 [main] INFO  com.navinfo.opentsp.qingqi.webpush.core.Application - Started Application in 49.808 seconds (JVM running for 53.243)
15:21:34.864 [concurrentMessageListenerContainer-0-kafka-consumer-1] INFO  org.apache.kafka.clients.consumer.internals.AbstractCoordinator - Marking the coordinator platform-010-030-050-167:16792 (id: 2147483647 rack: null) dead for group test-mengqa

最後一行 Marking the coordinator platform-010-030-050-167:16792 (id: 2147483647 rack: null) dead for group test-mengqa
被標記為死亡, 不能接收訊息的原因可能就是消費者死亡導致的

分析過程

從 log 可以分析這句是 AbstractCoordinator 類列印的, 我們找到列印這行資訊的程式碼

protected void coordinatorDead() {
    if (this.coordinator != null) {
         log.info("Marking the coordinator {} dead.", this.coordinator.id());
         this.coordinator = null;
     }
 }

顯然coordinator 為null了
打斷點追蹤

在這裡插入圖片描述

platform-010-030-050-167 是 Kafka 例項所在伺服器的主機名,
16792 是 kafka 的埠,這玩意好像是 Kafka 的連線地址
乍一看, 覺得沒什麼問題

從堆疊追蹤到上一呼叫方法處看看:
在這裡插入圖片描述

既然 coordinator 不為空, 那進入程式碼塊一定是因為 client.connectionFailed(coordinator) 這個方法的返回結果為true了。
從語義分析是因為客戶端連線 coordinator 失敗

進入該方法看看:
在這裡插入圖片描述

看到形參名是 node, 這個物件應該就是 kafka 的節點資訊,
點開檢視一下物件的具體屬性,知道問題原因在此。

問題定位

注意看上圖的 host 屬性, host 的意思一般是主機.
區域網內, 通過主機名是無法訪問的。
一般是通過 IP 、域名、或者修改 hosts 檔案把主機名和 IP 對應起來
定位後,我們嘗試用最簡單的方法解決問題.

解決

最簡單的就是修改本機 hosts 檔案

windows 系統 hosts 檔案位於 C:\Windows\System32\drivers\etc\hosts
使用管理員許可權開啟, 追加 IP 和 主機名對應關係

10.30.50.167 platform-010-030-050-167

重啟解決之。

方案總結

可能因為沒有給 Kafka 設定監聽地址導致的預設監聽主機名

在配置中果然搜尋到類似選項, 按照註釋的意思就是會廣播給消費者和生產者的地址.
我們按照要求改成 advertised.listeners=PLAINTEXT://10.30.50.167:16792
恢復本機 hosts 檔案經測試同樣解決了問題

最後

我們在 application.properties 中已經指定 spring.kafka.bootstrap-servers 為 IP, 為什麼還會使用主機名連結呢?

推測客戶端是先連線到 Kafka 例項後會從 zk 中獲取配置
然後客戶端 watch zk 節點得到配置地址後才開始監聽佇列。