Kafka的監聽地址配置實例詳解

有時我們會碰到網絡是通暢的,但卻連不上Kafka,特別是在多網卡環境或者雲環境上很容易出現,這個其實和Kafka的監聽配置有關系。本文介紹監聽相關的配置,目前監聽相關的參數主要有下面幾個:

  • listeners
  • advertised.listeners
  • listener.security.protocol.map
  • inter.broker.listener.name
  • security.inter.broker.protocol
  • advertised.host.name(歷史遺留,已廢棄,勿使用)
  • advertised.port(歷史遺留,已廢棄,勿使用)
  • host.name(歷史遺留,已廢棄,勿使用)

其中最重要的就是listeners和advertised.listeners:集群啟動時監聽listeners配置的地址,並將advertised.listeners配置的地址寫到Zookeeper裡面,作為集群元數據的一部分。我們可以將客戶端(生產者/消費者)連接Kafka集群進行操作的過程分成2步:

  • 通過listeners配置的連接信息(ip/host)連接到某個Broker(broker會定期獲取並緩存zk中的元數據信息),獲取元數據中advertised.listeners配置的地址信息。
  • 通過第1步獲取的advertised.listeners連接信息和Kafka集群通信(讀/寫)。

所以在存在內外網隔離的虛擬化環境中(比如Docker、公有雲),外部客戶端經常會出現可以連接到Kafka(第1步),但發送/消費數據時報連接超時(第2步),就是因為listeners配置的是外網地址,而advertised.listeners配置的卻是內網地址。那這幾個參數該如何配置呢?

先看連接信息的配置格式:{listener名字}://{HOST/IP}:{PORT}。HOST/IP、PORT很清楚,主要是這個“listener名字”字段。要理解這個得瞭解listener.security.protocol.map這個配置項:它的用途是配置listener名字和協議的映射(所以它是一個key-value的map),key是“listener名字”,value是“協議名稱”,其默認值是“listener名字”和“協議名稱”一樣。有點繞,舉個例子,比如:PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,冒號前面是key,即協議名字;後面是value,即協議名稱。listener名字我們可以隨便起,而協議名稱則是固定可枚舉的一個范圍。所以如果我們自定義瞭listener名字,那就需要顯式的設置其對應的協議名。

inter.broker.listener.name和security.inter.broker.protocol都是用於配置Broker之間通信的,前者配置名稱(即listener.security.protocol.map中的key),後者配置協議(即listener.security.protocol.map中的value),默認值是PLAINTEXT。這兩個配置項同時隻能配置一個。

為什麼一個連接要搞這麼復雜呢?主要是為瞭各種不同的場景需求。下面舉一個復雜一點的應用場景進行說明。比如我們在一個公有雲上面部署瞭一個Kafka集群,該環境有一個外網地址external_hostname和一個內網地址internal_hostname;且在內部中是無法獲取外網地址的(公有雲大多都是這樣的)。然後想實現內部客戶端訪問集群時走內部地址,且不需要加密;而外部客戶端訪問時則走外部地址,且需要加密。要實現這個需求,可以對集群進行如下配置:

listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:SSL
listeners=INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
advertised.listeners=INTERNAL://{internal_hostname}:19092,EXTERNAL://{external_hostname}:9092
inter.broker.listener.name=INTERNALlistener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:SSL

其實更進一步,我們還可以通過可選的control.plane.listener.name參數單獨定制集群Controller節點與其他Broker節點的連接,那配置信息就變為:

listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:SSL,CONTROL:SSL
listeners=INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
advertised.listeners=INTERNAL://{internal_hostname}:19092,EXTERNAL://{external_hostname}:9092,CONTROL://{control_ip}:9094
inter.broker.listener.name=INTERNAL
control.plane.listener.name=CONTROL

最後給出這些配置項的默認值和一些註意事項:

  • listeners如果不顯式的配置,那會監聽所有網卡,相當於配置瞭0.0.0.0。該配置項裡面listeners名字和端口都必須是唯一的,不能重復。
  • advertised.listeners如果不配置,默認使用listeners配置的值。如果listeners也沒有顯式配置,則使用java.net.InetAddress.getCanonicalHostName()獲取的IP地址。如果listeners配置的是0.0.0.0,則必須顯式的配置advertised.listeners,因為這個配置項必須是一個具體的地址,不允許是0.0.0.0(因為客戶端無法根據這個地址連接到Broker)。另外,advertised.listeners中的端口允許重復。
  • 對於listeners和advertised.listeners,有多個地址的時候,每一個地址都必須按照{listener名字}://{HOST/IP}:{PORT}格式進行配置,多個地址用英文逗號分隔。
  • 如果集群所有節點的hostname在客戶端和服務端各節點之間可以正確解析,優先使用hostname,而不是IP。因為代碼裡面使用瞭java.net.InetAddress.getCanonicalHostName(),有時使用IP會出現訪問不通的情況。

總結:

listeners地址是用於首次連接的;advertised.listeners的地址是會寫到zk裡面,客戶端通過listeners地址建立連接獲取該地址信息,然後通過該地址和集群交互。所以對於客戶端,這2個地址必須都是可以訪問的才可以。

到此這篇關於Kafka監聽地址配置的文章就介紹到這瞭,更多相關Kafka監聽地址配置內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: