- 參數(shù)詳解listenersadvertised.listenerslistener.security.protocol.mapinter.broker.listener.namesecurity.inter.broker.protocolcontrol.plane.listener.name示例說(shuō)明
- 幾種場(chǎng)景的配置方式1. 一臺(tái)機(jī)器部署一套集群2. 內(nèi)網(wǎng)環(huán)境多機(jī)器部署集群3. 內(nèi)網(wǎng)和外網(wǎng)分流3. 內(nèi)網(wǎng)和外網(wǎng)和Controller分流
《Kafka運(yùn)維管控平臺(tái)LogiKM》 ??更強(qiáng)大的管控能力?? 更高效的問(wèn)題定位能力 更便捷的集群運(yùn)維能力 更專業(yè)的資源治理 更友好的運(yùn)維生態(tài)
1參數(shù)詳解
listeners
偵聽器列表,這里配置的監(jiān)聽器底層調(diào)用的是
ServerSocketAdaptor.bind(SocketAddress local)
那么這個(gè)說(shuō)明什么意思呢?說(shuō)明你配置的監(jiān)聽器將被用于監(jiān)聽網(wǎng)絡(luò)請(qǐng)求。 簡(jiǎn)單理解就是你建立監(jiān)聽一個(gè)通道,別人能夠通過(guò)這個(gè)通道跟你溝通。 所以我們需要設(shè)置 IP:Port.
這個(gè)屬性的格式為:
listeners = listener_name://host_name:port,listener_name2://host_nam2e:port2
- 可以同時(shí)配置多個(gè), 并且用逗號(hào)隔開
- 監(jiān)聽器的名稱和端口必須是唯一的,端口相同,就沖突了
- host_name如果為空,例如(listeners = ://host_name:port),則會(huì)綁定到默認(rèn)的接口(網(wǎng)卡),一般情況下是localhost,底層調(diào)用的是JAVA.net.InetAddress.getCanonicalHostName()
- 將host_name設(shè)置為0.0.0.0 則會(huì)綁定所有的網(wǎng)卡, 也就是說(shuō)不管從哪個(gè)網(wǎng)卡進(jìn)入的請(qǐng)求都會(huì)被接受處理。但是請(qǐng)注意,假如你設(shè)置的是0.0.0.0,那么advertised.listeners 必須要設(shè)置,因?yàn)閍dvertised.listeners默認(rèn)請(qǐng)看下使用的是listeners的配置發(fā)布到zk中,發(fā)布到zk中是給其他Brokers/Clients 來(lái)跟你通信的,你設(shè)置0.0.0.0,誰(shuí)知道要請(qǐng)求哪個(gè)IP呢, 所以它必須要指定并明確 IP:PORT。具體詳情請(qǐng)看下面 示例3
- listener_name 是監(jiān)聽名,唯一值, 他并不是安全協(xié)議(大部分人都會(huì)搞錯(cuò)),因?yàn)槟J(rèn)的4個(gè)安全協(xié)議已經(jīng)做好了映射, 例如 :PLAINTEXT ==> PLAINTEXT . 所以你經(jīng)常看到的配置## 這個(gè)PLAINTEXT是監(jiān)聽名稱,剛好他對(duì)應(yīng)的安全協(xié)議就是 PLAINTEXT
## 當(dāng)然這個(gè)是可以自定義的, 詳細(xì)情況 后面的配置listener.security.protocol.map
listeners = PLAINTEXT://your.host.name:9092 - 可動(dòng)態(tài)配置該屬性
advertised.listeners
發(fā)布公開的監(jiān)聽器, 啥叫發(fā)布公開的監(jiān)聽器? 就是,讓Brokers和Clients們都能夠知道的監(jiān)聽器,你想想看,listeners是Broker用來(lái)監(jiān)聽網(wǎng)絡(luò)請(qǐng)求的
那么,其他Broker或者客戶端想要與它通信,則需要知道具體的IP:PORT吧? 所以,為了讓別人知道自己的監(jiān)聽器,那么就需要公開出去,當(dāng)然這個(gè)公開的形式,是通過(guò)zk來(lái)共享數(shù)據(jù)。
看看broker到zk節(jié)點(diǎn)/brokers/{brokerid}/ 下面的信息示例
{
"features": {},
"listener_security_protocol_map": {
"PLAINTEXT": "PLAINTEXT"
},
"endpoints": ["PLAINTEXT://localhost:9092"],
"jmx_port": -1,
"port": 9092,
"host": "localhost",
"version": 5,
"timestamp": "1647337490945"
}
其中endpoints就是我們發(fā)布出去的監(jiān)聽器。 這個(gè)屬性的格式為:
advertised.listeners = listener_name://host_name:port,listener_name2://host_nam2e:port2
- 默認(rèn)情況下,advertised.listeners不設(shè)置會(huì)自動(dòng)使用listeners屬性
- advertised.listeners不支持0.0.0.0這種形式, 所以如果listeners屬性設(shè)置成0.0.0.0,則必須設(shè)置advertised.listeners屬性。具體請(qǐng)看 示例3 因?yàn)?.0.0.0是表示的是監(jiān)聽Broker上任意的網(wǎng)卡的, 你將這個(gè)發(fā)布出去,那么別的Broker和客戶端怎么知道你具體的ip和端口呢?
- 可以同時(shí)配置多個(gè), 并且用逗號(hào)隔開
- 可動(dòng)態(tài)配置該屬性
listener.security.protocol.map
監(jiān)聽器名稱和安全協(xié)議之間的映射關(guān)系集合。
listeners=PLAINTEXT://localhost:9092
看看上面的配置, PLANINTEXT是監(jiān)聽器名稱,那么它對(duì)應(yīng)的安全協(xié)議是什么呢? 它對(duì)應(yīng)的安全協(xié)議是 PLANINTEXT, 為什么呢? 那是因?yàn)槟J(rèn)情況下,已經(jīng)有了他們的映射關(guān)系。
默認(rèn)集合:
PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
屬性格式:
監(jiān)聽名稱1:安全協(xié)議1,監(jiān)聽名稱2:安全協(xié)議2
現(xiàn)有的安全協(xié)議,有4種, 分別如下, 下為默認(rèn)監(jiān)聽器名稱映射對(duì)應(yīng)的安全協(xié)議情況。
- PLAINTEXT => PLAINTEXT 不需要授權(quán),非加密通道
- SSL => SSL 使用SSL加密通道
- SASL_PLAINTEXT => SASL_PLAINTEXT 使用SASL認(rèn)證非加密通道
- SASL_SSL => SASL_SSL 使用SASL認(rèn)證并且SSL加密通道
當(dāng)然你也可以自己重新映射監(jiān)聽器名稱和安全協(xié)議, 比如: 示例4
inter.broker.listener.name
用于Broker之間通信的listener的名稱。如果未設(shè)置,則listener名稱由 security.inter.broker.protocol定義(security.inter.broker.protocol默認(rèn)值是PLAINTEXT)。
同時(shí)設(shè)置 這個(gè)和 security.inter.broker.protocol 屬性是錯(cuò)誤的。
默認(rèn)值:空
不可動(dòng)態(tài)配置。
特別注意:這個(gè)屬性表示是Broker之間的網(wǎng)絡(luò)通信使用的監(jiān)聽器, 比如 Broker2Broker 但是還有一種就是Controller2Broker、如果沒(méi)有配置control.plane.listener.name ,那么走的也是inter.broker.listener.name 這個(gè)監(jiān)聽器。
根據(jù)本地配置的監(jiān)聽器名稱, 去查找其他Broker的監(jiān)聽器的EndPoint。所以一般所有Broker的監(jiān)聽器名稱都必須一致,否則的話就找不到具體的EndPoint,無(wú)法正確的發(fā)起請(qǐng)求。
security.inter.broker.protocol
用于在代理之間進(jìn)行通信的安全協(xié)議。
有效值為:PLAINTEXT、SSL、SASL_PLAINTEXT、SASL_SSL。
同時(shí)設(shè)置 該屬性和 inter.broker.listener.name 屬性是錯(cuò)誤的。
默認(rèn)值:PLAINTEXT (純文本)
注意這個(gè)跟inter.broker.listener.name是有區(qū)別的, 這個(gè)配置只有四個(gè)選項(xiàng),是安全協(xié)議 而inter.broker.listener.name是監(jiān)聽名稱, 是需要通過(guò)這個(gè)監(jiān)聽名稱去找到它映射的 安全協(xié)議 還有 IP:PORT
如果inter.broker.listener.name沒(méi)有配置,則默認(rèn)使用security.inter.broker.protocol的配置. 對(duì)inter.broker.listener.name而言,最終還是要去找到對(duì)應(yīng)的 IP:PORT。
一般自定義了監(jiān)聽器名稱, inter.broker.listener.name就是必須要設(shè)置的, 不能使用security.inter.broker.protocol 來(lái)代替。
control.plane.listener.name
用于Controller和Broker之間通信的監(jiān)聽器名稱, Broker將會(huì)使用control.plane.listener.name 來(lái)定位監(jiān)聽器列表中的EndPoint
如果未設(shè)置,則默認(rèn)使用inter.broker.listener.name來(lái)通信,沒(méi)有專門的鏈接。
詳情請(qǐng)看:Kafka的客戶端NetworkClient如何發(fā)起的請(qǐng)求
示例說(shuō)明
1 . 綁定一個(gè)IP, 客戶端使用另外的IP訪問(wèn)
讓broker 監(jiān)聽localhost:9092. 然后客戶端訪問(wèn)broker的具體IP.
listeners=PLAINTEXT://localhost:9092
啟動(dòng)之后查看一下監(jiān)聽情況
linux命令: netstat -anp |grep 9092 mac環(huán)境命令:netstat -AaLlnW
在這里插入圖片描述
當(dāng)然,如果你這臺(tái)機(jī)器剛好還是Controller的話,除了了LISTEN, 還能看到ESTABLISHED狀態(tài)的連接,因?yàn)镃ontroller也會(huì)給這臺(tái)Broker建立連接發(fā)起請(qǐng)求的,比如通知Broker更新元信息之類的。
在這里插入圖片描述
我們使用生產(chǎn)者客戶端來(lái)生產(chǎn)幾條消息
sh bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic Topic4
## 或者
sh bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic Topic4
可以發(fā)現(xiàn)正常發(fā)送消息。
那么接下來(lái),使用使用具體IP發(fā)起請(qǐng)求
sh bin/kafka-console-producer.sh --bootstrap-server 10.xxx.xx.128:9092 --topic Topic4
在這里插入圖片描述
[2022-03-16 12:59:07,024] WARN [Controller id=1000, targetBrokerId=1000] Connection to node 1000
(/10.xxx.xxx.xx:9092) could not be established. Broker may not be available. (org.Apache.kafka.clients.NetworkClient)
可以看到,客戶端提示說(shuō)不能跟這個(gè)ip:port建立連接。
2. listeners 和 advertised.listeners 配置的IP不一樣
listeners=PLAINTEXT://xx.xx.xxx.01:9092
advertised.listeners=PLAINTEXT:/xx.xx.xxx.02:9092
假設(shè)你本地監(jiān)聽和發(fā)布的監(jiān)聽不一樣, 那么就會(huì)造成其他broker和客戶端跟這臺(tái)broker不能正確的建立鏈接。
如果你這臺(tái)Broker剛好還是Controller,那么他也會(huì)對(duì)自己建立連接, 都是根據(jù)advertised.listeners的配置來(lái)建立的,同樣會(huì)失敗。其他broker也一樣。
[2022-03-16 12:59:07,024] WARN [Controller id=1000, targetBrokerId=1000] Connection to node 1000
(/10.xxx.xxx.xx:9092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
3 . listeners監(jiān)聽任意可用IP, advertised.listeners發(fā)布指定IP
在示例2中,我們指定 listeners 監(jiān)聽器和advertised.listeners發(fā)布的監(jiān)聽器不一致會(huì)導(dǎo)致異常。 那么,我們只需要將監(jiān)聽器的和發(fā)布的監(jiān)聽器一致就行了
當(dāng)然,我們還可直接設(shè)置監(jiān)聽器監(jiān)聽任意可用IP(該Broker上的可用IP)
listeners=PLAINTEXT://0.0.0.0:9092
當(dāng)然,如果只是將host設(shè)置為 0.0.0.0. 那么會(huì)報(bào)錯(cuò)
java.lang.IllegalArgumentException: requirement failed: advertised.listeners cannot use the nonroutable meta-address 0.0.0.0. Use a routable IP address.
at kafka.server.KafkaConfig.validateValues(KafkaConfig.scala:1789)
因?yàn)槟J(rèn)情況下,advertised.listeners不設(shè)置的話,則默認(rèn)使用listeners的屬性,然而advertised.listeners是不支持0.0.0.0的,所以需要指定暴露的監(jiān)聽器,如下
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://xx.xx.xx.128:9092
這樣子配置就不會(huì)報(bào)錯(cuò)了,其他Broker和客戶端會(huì)通過(guò)advertised.listeners發(fā)布的監(jiān)聽器來(lái)跟該Broker建立鏈接。
注意: 這個(gè)時(shí)候你還可以在這臺(tái)Broker的機(jī)器上使用 localhost 來(lái)進(jìn)行訪問(wèn)。比如:
sh bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic Topic4
在這里插入圖片描述
可以看到也是可以正常發(fā)送消息的。
4 . listeners配置多個(gè)監(jiān)聽器,內(nèi)外網(wǎng)分流
listeners = INSIDE://內(nèi)網(wǎng)IP:9091,OUTSIDE://外網(wǎng)IP:9092
#把OUTSIDE 的安全協(xié)議映射成PLAINTEXT INSIDE也映射成PLAINTEXT
listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
# Broker之間的連接用 INSIDE 監(jiān)聽器
inter.broker.listener.name=INSIDE
設(shè)置了2個(gè)監(jiān)聽器 ①. INSIDE 監(jiān)聽內(nèi)網(wǎng)IP ②. OUTSIDE 監(jiān)聽外網(wǎng)IP
因?yàn)檫@個(gè)是我們自己定義的監(jiān)聽名稱,listener.security.protocol.map默認(rèn)映射中并沒(méi)有對(duì)應(yīng)的映射關(guān)系 所以我們就需要主動(dòng)設(shè)置這個(gè)映射關(guān)系 listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:SSL
不然會(huì)拋異常
Caused by: java.lang.IllegalArgumentException: No security protocol defined for listener INSIDE
at kafka.cluster.EndPoint$.$anonfun$createEndPoint$2(EndPoint.scala:48)
注意:自定義了監(jiān)聽器,則必須要配置inter.broker.listener.name
確定好內(nèi)部的broker之間通信的監(jiān)聽器. 并確保能夠正常訪問(wèn)。
這樣Broker直接就會(huì)通過(guò)內(nèi)網(wǎng)互相連接, 客戶端除了可以通過(guò)內(nèi)網(wǎng)連接(如果在內(nèi)網(wǎng)環(huán)境的話),也可以通過(guò)外網(wǎng)連接。
2幾種場(chǎng)景的配置方式
1. 一臺(tái)機(jī)器部署一套集群
這種場(chǎng)景一般是自己開發(fā)測(cè)試的時(shí)候, 比如自己搭建一個(gè)集群,學(xué)習(xí)學(xué)習(xí),但是又沒(méi)有那么多機(jī)器,那么就可以在一臺(tái)電腦上部署多個(gè)Broker。
只配置listeners屬性
listeners = 監(jiān)聽名稱://your.host.name:port
關(guān)于監(jiān)聽名稱,默認(rèn)的映射關(guān)系有4種。
- PLAINTEXT => PLAINTEXT 不需要授權(quán),非加密通道
- SSL => SSL 使用SSL加密通道
- SASL_PLAINTEXT => SASL_PLAINTEXT 使用SASL認(rèn)證非加密通道
- SASL_SSL => SASL_SSL 使用SASL認(rèn)證并且SSL加密通道
簡(jiǎn)單一點(diǎn),用PLAINTEXT就夠了, 這里我們可以把host給去掉, 或者使用localhost
listeners = PLAINTEXT://:port
或者
listeners = PLAINTEXT://localhost:port
如果沒(méi)有配置host,會(huì)調(diào)用java.net.InetAddress.getCanonicalHostName()獲取本機(jī)host. 默認(rèn)情況下就是localhost.
這里之所以建議你不填寫具體的host,是因?yàn)橐话阕约捍罱ㄍ嫱娴臅r(shí)候可能網(wǎng)絡(luò)IP會(huì)經(jīng)常變動(dòng)(例如家里的和公司), 如果綁定了具體的IP的話,每次重啟都要更換配置就很麻煩。
可以看看Broker啟動(dòng)后注冊(cè)到zk中的配置如下
{
"features": {},
"listener_security_protocol_map": {
"PLAINTEXT": "PLAINTEXT"
},
"endpoints": ["PLAINTEXT://localhost:9092"],
"jmx_port": -1,
"port": 9092,
"host": "localhost",
"version": 5,
"timestamp": "1647337490945"
}
這個(gè)endpoints 就是broker注冊(cè)到zk的訪問(wèn)地址, 如果其他Broker或者客戶端要跟這臺(tái)Broker發(fā)生網(wǎng)絡(luò)請(qǐng)求話, 就是拿的這里面的值。
所以,你想想看,如果是不同機(jī)器上,你配置的host是 localhost, 是不是就訪問(wèn)不了?
當(dāng)然,listeners屬性的host,我們也可以自己去hosts文件里面配置別的域名。配置域名指向的具體IP, 這樣的話那還能奏效。就是每個(gè)Broker和客戶端都要配置host,這就比較麻煩,所以還不如直接配置IP呢。
2. 內(nèi)網(wǎng)環(huán)境多機(jī)器部署集群
這種是絕大部分的場(chǎng)景, 一般公司部署集群都是在公司內(nèi)網(wǎng)環(huán)境下, Broker之間和Broker與客戶端之間都在同一個(gè)網(wǎng)絡(luò)環(huán)境。并且安全協(xié)議都是直接PLAINTEXT(明文)或者其他
listeners=PLAINTEXT://ip:port
3. 內(nèi)網(wǎng)和外網(wǎng)分流
listeners=INTERNAL://內(nèi)網(wǎng)ip:port1,EXTERNAL://外網(wǎng)ip:port2
#把OUTSIDE 的安全協(xié)議映射成PLAINTEXT INSIDE也映射成PLAINTEXT
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# Broker之間的連接用 INSIDE 監(jiān)聽器
inter.broker.listener.name=INTERNAL
配置了兩個(gè)監(jiān)聽器,每個(gè)Brokerinter.broker.listener.name=INTERNAL 使用內(nèi)網(wǎng)交流。
其他的客戶端例如Producer和Consumer 請(qǐng)求的時(shí)候直接訪問(wèn)外網(wǎng)IP.
3. 內(nèi)網(wǎng)和外網(wǎng)和Controller分流
listeners=INTERNAL://內(nèi)網(wǎng)ip:port1,EXTERNAL://外網(wǎng)ip:port2,CONTROLLER://內(nèi)網(wǎng)ip:port3,
#把OUTSIDE 的安全協(xié)議映射成PLAINTEXT INSIDE也映射成PLAINTEXT
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
# Broker之間的連接用 INSIDE 監(jiān)聽器
inter.broker.listener.name=INTERNAL
control.plane.listener.name=CONTROLLER
這樣配置
- Controller2Broker或者Broker2Controller
- Broker2Broker
- Clients2Broker
他們都會(huì)會(huì)有獨(dú)立的網(wǎng)絡(luò)通信線程