在當今的軟體開發領域,容器化技術成為了越來越流行的部署方式。而Docker作為最受歡迎的容器化解決方案之一,為開發者提供了便捷的環境隔離和部署方式。對於使用Kafka作為訊息佇列系統的開發者來說,將Kafka與Docker結合起來,可以更靈活和有效率地進行開發和部署。在這篇文章中,php小編西瓜將為大家介紹如何在Docker中運行Kafka,讓您輕鬆享受容器化帶來的便利。
我在本機電腦上設定了一個單節點 kafka docker 容器,如 confluence 文件所述(步驟 2-3)。
此外,我還公開了 zookeeper 的連接埠 2181 和 kafka 的連接埠 9092,以便我能夠從本機電腦上執行的用戶端連接到它們:
$ docker run -d \ -p 2181:2181 \ --net=confluent \ --name=zookeeper \ -e zookeeper_client_port=2181 \ confluentinc/cp-zookeeper:4.1.0 $ docker run -d \ --net=confluent \ --name=kafka \ -p 9092:9092 \ -e kafka_zookeeper_connect=zookeeper:2181 \ -e kafka_advertised_listeners=plaintext://kafka:9092 \ -e kafka_offsets_topic_replication_factor=1 \ confluentinc/cp-kafka:4.1.0
問題:當我嘗試從主機連線到 kafka 時,連線失敗,因為 無法解析位址:kafka:9092
。
這是我的 java 程式碼:
properties props = new properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("client.id", "kafkaexampleproducer"); props.put("key.serializer", longserializer.class.getname()); props.put("value.serializer", stringserializer.class.getname()); kafkaproducer<long, string> producer = new kafkaproducer<>(props); producerrecord<long, string> record = new producerrecord<>("foo", 1l, "test 1"); producer.send(record).get(); producer.flush();
例外:
java.io.IOException: Can't resolve address: kafka:9092 at org.apache.kafka.common.network.Selector.doConnect(Selector.java:235) ~[kafka-clients-2.0.0.jar:na] at org.apache.kafka.common.network.Selector.connect(Selector.java:214) ~[kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:864) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:265) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.sendProducerData(Sender.java:266) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:238) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:176) [kafka-clients-2.0.0.jar:na] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144] Caused by: java.nio.channels.UnresolvedAddressException: null at sun.nio.ch.Net.checkAddress(Net.java:101) ~[na:1.8.0_144] at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622) ~[na:1.8.0_144] at org.apache.kafka.common.network.Selector.doConnect(Selector.java:233) ~[kafka-clients-2.0.0.jar:na] ... 7 common frames omitted
問題:如何連接到在 docker 中執行的 kafka?我的程式碼是從主機運行的,而不是 docker。
注意:我知道理論上我可以嘗試 dns 設定和 /etc/hosts
但這是一種解決方法 - 不應該是這樣的。
這裡也有類似的問題,但它是基於 ches/kafka
圖片。我使用基於 confluenceinc
的圖像,這是不一樣的。
tl;dr - 從容器到主機的簡單連接埠轉送將不起作用...主機檔案(例如* NIX 系統上的 /etc/hosts
)不應修改以解決Kafka 網路問題,因為此解決方案無法移植。
1) 您想要連接到哪個確切的 IP/主機名稱 連接埠?確保該值在代理程式上設定為 advertished.listeners
(不是 advertished.host.name
和 advertished.port
,因為這些已被棄用)。如果您看到諸如 Connection to node -1 (localhost/127.0.0.1:9092)
之類的錯誤,則表示您的應用程式容器嘗試連接到自身。您的應用程式容器是否也在執行 Kafka 代理程式?可能不是。
2) 確保作為 bootstrap.servers
一部分列出的伺服器實際上是可解析的。例如ping
IP/主機名,使用netcat
檢查連接埠...如果您的用戶端位於容器中,則需要從容器執行此操作,而不是(僅)從主機執行此操作。如果容器沒有立即崩潰以存取其 shell,請使用 docker exec
。
3) 如果從主機而不是另一個容器運行進程,要驗證連接埠是否在主機上正確映射,請確保docker ps
顯示kafka 容器是從0.0.0.0 對應的: 50c5a3c9bd6141bda139d1e2f6e9d778 -> cd3356af2f6e059e7bd54cd1ababa980 /tcp
.如果嘗試從Docker 網路外部執行用戶端,則連接埠必須符合。兩個容器之間不需要連接埠轉送;使用連結/docker網路
下面的答案使用 confluenceinc
docker 映像來解決所提出的問題,不是 wurstmeister/kafka
。如果您設定了 KAFKA_ADVERTISED_HOST_NAME
變量,請將其刪除(這是已棄用的屬性)
以下部分嘗試匯總使用其他圖像所需的所有詳細資訊。對於其他常用的 Kafka 映像,都是在容器中執行的 Apache Kafka。
您只依賴它的配置方式。以及哪些變數導致了這種情況。
wurstmeister/kafka
自 2023 年 10 月起,DockerHub 中不再存在此內容。無論如何,2022 年後就不再維護了。
請參閱有關監聽器設定的自述文件部分 a>,另外閱讀他們的 Connectivity wiki。
bitnami/kafka
如果您想要一個小容器,請嘗試這些。這些映像比 Confluence 小得多,並且比 wurstmeister
維護得更好。 參考他們的監聽器配置的自述文件。
debezium/kafka
此處提到了相關文件此處。
注意:已棄用已公佈的主機和連接埠設定。廣告聽眾涵蓋了兩者。與 Confluence 容器類似,Debezium 可以使用 KAFKA_
前綴的代理設定來更新其屬性。
ubuntu/kafka
要求您透過Docker 映像參數新增--overrideadvertising.listeners=kafka:9092
...我發現它不如環境變數可移植,因此不推薦spotify/kafka
已棄用且過時。 fast-data-dev
或lensesio/box
非常適合一體化解決方案,具有架構註冊表、Kafka Connect 等,但如果您僅想要Kafka,則顯得臃腫。另外,這是一種在一個容器中執行多個服務的 Docker 反模式Dockerfile
- 為什麼?這些其他的東西是否不完整?從拉取請求開始,而不是從頭開始。 有關補充閱讀、功能齊全 docker-compose
和網絡圖,請參閱 此部落格作者:@rmoff
Confluence 快速入門 (Docker) 文件 假設所有生產和消費要求將在 Docker 網路內進行。
您可以透過在自己的容器中執行Kafka 用戶端程式碼(使用Docker 橋接器)來解決連接到kafka:9092
的問題,但否則您需要新增更多環境變數以將容器公開到外部,同時仍然讓它在Docker 網路中運作。
首先新增 PLAINTEXT_HOST:PLAINTEXT
的協定映射,它將偵聽器協定映射到 Kafka 協定
金鑰:KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
#
值: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
#然後在不同的連接埠上設定兩個通告的偵聽器。 (這裡的 kafka
指的是 docker 容器名稱;它也可能被命名為 broker
,因此請仔細檢查您的服務 主機名稱)。
鍵:KAFKA_ADVERTISED_LISTENERS
值:PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
#請注意,此處的協定與上面協定對映設定的左側值相符
執行容器時,新增 -p 29092:29092
進行主機連接埠映射,並通告 PLAINTEXT_HOST
監聽器。
所以...(使用上述設定)
如果仍然不起作用,可以將KAFKA_LISTENERS
設定為包含9625b882931466931ca10eb1a60367b3://0.0.0.0:a3b0c87895079be75e30be94102cc20b
,其中兩個選項都與廣告設定和Docker 轉送的連接埠相符
廣告本機主機和關聯的連接埠將允許您在容器外部進行連接,正如您所期望的那樣。
換句話說,當在Docker 網路之外執行任何Kafka 用戶端(包括您可能在本機安裝的CLI 工具)時,請使用localhost:29092
作為引導伺服器,使用 localhost:2181
作為Zookeeper(需要Docker)連接埠轉送)
如果嘗試從外部伺服器連接,您需要公佈主機的外部主機名稱/IP(例如 192.168.x.y
)以及/取代 localhost #。
簡單地透過連接埠轉送來通告 localhost 是行不通的,因為 Kafka 協定仍將繼續通告您設定的偵聽器。
如果不在同一個本機網路中,此設定需要Docker 連接埠轉送和路由器連接埠轉送(以及防火牆/安全性群組變更),例如,您的容器在雲端中運行,並且您想要從本機與其互動。
這是最不容易出錯的設定;您可以直接使用 DNS 服務名稱。
在Docker 網路中執行應用程式時,使用kafka:9092
(請參閱上面廣告的PLAINTEXT
偵聽器設定)作為引導伺服器,使用zookeeper:2181
作為Zookeeper,就像任何其他Docker 服務通訊一樣(不不需要任何連接埠轉送)
如果您使用單獨的docker run
命令或Compose 文件,則需要使用compose networks
部分或docker network --create
手動定義共享network
請參閱完整 Confluence 堆疊的範例 Compose 檔案 或 針對單一經紀商的更簡單的。
如果使用多個代理,那麼它們需要使用唯一的主機名稱 廣告偵聽器。 查看範例一个>
從 Docker (ksqlDB) 連線到主機上的 Kafka
對於任何對 Kubernetes 部署感興趣的人:
以上是連接到在 Docker 中運行的 Kafka的詳細內容。更多資訊請關注PHP中文網其他相關文章!