【云原生】一文搞懂Kafka中的listeners和advertised.listeners以及其他通信配置 | 您所在的位置:网站首页 › kafka监听配置 › 【云原生】一文搞懂Kafka中的listeners和advertised.listeners以及其他通信配置 |
🔥《Kafka运维管控平台LogiKM》🔥 ✏️更强大的管控能力✏️ 🎾更高效的问题定位能力🎾 🌅更便捷的集群运维能力🌅 🎼更专业的资源治理🎼 🌞更友好的运维生态🌞 文章目录参数详解listenersadvertised.listenerslistener.security.protocol.mapinter.broker.listener.namesecurity.inter.broker.protocolcontrol.plane.listener.name示例说明1 . 绑定一个IP, 客户端使用另外的IP访问2. listeners 和 advertised.listeners 配置的IP不一样3 . listeners监听任意可用IP, advertised.listeners发布指定IP4 . listeners配置多个监听器,内外网分流几种场景的配置方式1. 一台机器部署一套集群2. 内网环境多机器部署集群3. 内网和外网分流4. 内网和外网和Controller分流参数详解listeners侦听器列表,这里配置的监听器底层调用的是 ServerSocketAdaptor.bind(SocketAddress local)那么这个说明什么意思呢?说明你配置的监听器将被用于监听网络请求。 简单理解就是你建立监听一个通道,别人能够通过这个通道跟你沟通。 所以我们需要设置 IP:Port. 这个属性的格式为: listeners = listener_name://host_name:port,listener_name2://host_nam2e:port2可以同时配置多个, 并且用逗号隔开 监听器的名称和端口必须是唯一的,端口相同,就冲突了 host_name如果为空,例如(),则会绑定到默认的接口(网卡),一般情况下是,底层调用的是 将host_name设置为 则会绑定所有的网卡, 也就是说不管从哪个网卡进入的请求都会被接受处理。但是请注意,假如你设置的是,那么 必须要设置,因为默认请看下使用的是的配置发布到zk中,发布到zk中是给其他Brokers/Clients 来跟你通信的,你设置,谁知道要请求哪个IP呢, 所以它必须要指定并明确 IP:PORT。具体详情请看下面 listener_name 是监听名,唯一值, 他并不是安全协议(大部分人都会搞错),因为默认的4个安全协议已经做好了映射, 例如 :PLAINTEXT ==> PLAINTEXT . 所以你经常看到的配置 可动态配置该属性 advertised.listeners发布公开的监听器, 啥叫发布公开的监听器? 就是,让Brokers和Clients们都能够知道的监听器,你想想看,listeners是Broker用来监听网络请求的 那么,其他Broker或者客户端想要与它通信,则需要知道具体的IP:PORT吧? 所以,为了让别人知道自己的监听器,那么就需要公开出去,当然这个公开的形式,是通过zk来共享数据。 看看broker到zk节点/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就是我们发布出去的监听器。 这个属性的格式为: advertised.listeners = listener_name://host_name:port,listener_name2://host_nam2e:port2默认情况下,advertised.listeners不设置会自动使用listeners属性advertised.listeners不支持0.0.0.0这种形式, 所以如果listeners属性设置成0.0.0.0,则必须设置advertised.listeners属性。具体请看 示例3 因为0.0.0.0是表示的是监听Broker上任意的网卡的, 你将这个发布出去,那么别的Broker和客户端怎么知道你具体的ip和端口呢?可以同时配置多个, 并且用逗号隔开可动态配置该属性listener.security.protocol.map监听器名称和安全协议之间的映射关系集合。 listeners=PLAINTEXT://localhost:9092看看上面的配置, PLANINTEXT是监听器名称,那么它对应的安全协议是什么呢? 它对应的安全协议是 PLANINTEXT, 为什么呢? 那是因为默认情况下,已经有了他们的映射关系。 默认集合: PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL 属性格式: 监听名称1:安全协议1,监听名称2:安全协议2现有的安全协议,有4种, 分别如下, 下为默认监听器名称映射对应的安全协议情况。 PLAINTEXT => PLAINTEXT 不需要授权,非加密通道SSL => SSL 使用SSL加密通道SASL_PLAINTEXT => SASL_PLAINTEXT 使用SASL认证非加密通道SASL_SSL => SASL_SSL 使用SASL认证并且SSL加密通道当然你也可以自己重新映射监听器名称和安全协议, 比如: 示例4 inter.broker.listener.name用于Broker之间通信的listener的名称。如果未设置,则listener名称由 security.inter.broker.protocol定义(security.inter.broker.protocol默认值是PLAINTEXT)。 同时设置 这个和 security.inter.broker.protocol 属性是错误的。 默认值:空 不可动态配置。 特别注意: 这个属性表示是Broker之间的网络通信使用的监听器, 比如 Broker2Broker 但是还有一种就是Controller2Broker、如果没有配置control.plane.listener.name ,那么走的也是inter.broker.listener.name 这个监听器。 根据本地配置的监听器名称, 去查找其他Broker的监听器的EndPoint。所以一般所有Broker的监听器名称都必须一致,否则的话就找不到具体的EndPoint,无法正确的发起请求。 security.inter.broker.protocol用于在代理之间进行通信的安全协议。 有效值为:PLAINTEXT、SSL、SASL_PLAINTEXT、SASL_SSL。 同时设置 该属性和 inter.broker.listener.name 属性是错误的。 默认值:PLAINTEXT (纯文本) 注意这个跟inter.broker.listener.name是有区别的, 这个配置只有四个选项,是安全协议 而inter.broker.listener.name是监听名称, 是需要通过这个监听名称去找到它映射的 安全协议 还有 IP:PORT 如果inter.broker.listener.name没有配置,则默认使用security.inter.broker.protocol的配置. 对inter.broker.listener.name而言,最终还是要去找到对应的 IP:PORT。 一般自定义了监听器名称, inter.broker.listener.name就是必须要设置的, 不能使用security.inter.broker.protocol 来代替。 control.plane.listener.name用于Controller和Broker之间通信的监听器名称, Broker将会使用control.plane.listener.name 来定位监听器列表中的EndPoint 如果未设置,则默认使用inter.broker.listener.name来通信,没有专门的链接。 详情请看:Kafka的客户端NetworkClient如何发起的请求 示例说明1 . 绑定一个IP, 客户端使用另外的IP访问让broker 监听localhost:9092. 然后客户端访问broker的具体IP. listeners=PLAINTEXT://localhost:9092启动之后查看一下监听情况 Linux命令: netstat -anp |grep 9092 Mac环境命令:netstat -AaLlnW ![]() 当然,如果你这台机器刚好还是Controller的话,除了了LISTEN, 还能看到ESTABLISHED状态的连接,因为Controller也会给这台Broker建立连接发起请求的,比如通知Broker更新元信息之类的。 ![]() 我们使用生产者客户端来生产几条消息 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![]() ![]() 可以发现正常发送消息。 那么接下来,使用使用具体IP发起请求 sh bin/kafka-console-producer.sh --bootstrap-server 10.xxx.xx.128:9092 --topic Topic4![]() 可以看到,客户端提示说不能跟这个ip:port建立连接。 2. listeners 和 advertised.listeners 配置的IP不一样listeners=PLAINTEXT://xx.xx.xxx.01:9092 advertised.listeners=PLAINTEXT:/xx.xx.xxx.02:9092假设你本地监听和发布的监听不一样, 那么就会造成其他broker和客户端跟这台broker不能正确的建立链接。 如果你这台Broker刚好还是Controller,那么他也会对自己建立连接, 都是根据advertised.listeners的配置来建立的,同样会失败。其他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监听任意可用IP, advertised.listeners发布指定IP在示例2中,我们指定 listeners 监听器和advertised.listeners发布的监听器不一致会导致异常。 那么,我们只需要将监听器的和发布的监听器一致就行了 当然,我们还可直接设置监听器监听任意可用IP(该Broker上的可用IP) listeners=PLAINTEXT://0.0.0.0:9092当然,如果只是将host设置为 0.0.0.0. 那么会报错 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)因为默认情况下,advertised.listeners不设置的话,则默认使用listeners的属性,然而advertised.listeners是不支持0.0.0.0的,所以需要指定暴露的监听器,如下 listeners=PLAINTEXT://0.0.0.0:9092 advertised.listeners=PLAINTEXT://xx.xx.xx.128:9092这样子配置就不会报错了,其他Broker和客户端会通过advertised.listeners发布的监听器来跟该Broker建立链接。 注意: 这个时候你还可以在这台Broker的机器上使用 localhost 来进行访问。比如: sh bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic Topic4![]() 可以看到也是可以正常发送消息的。 4 . listeners配置多个监听器,内外网分流listeners = INSIDE://内网IP:9091,OUTSIDE://外网IP:9092 #把OUTSIDE 的安全协议映射成PLAINTEXT INSIDE也映射成PLAINTEXT listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT # Broker之间的连接用 INSIDE 监听器 inter.broker.listener.name=INSIDE设置了2个监听器 ①. INSIDE 监听内网IP ②. OUTSIDE 监听外网IP 因为这个是我们自己定义的监听名称,listener.security.protocol.map默认映射中并没有对应的映射关系 所以我们就需要主动设置这个映射关系 listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:SSL 不然会抛异常 Caused by: java.lang.IllegalArgumentException: No security protocol defined for listener INSIDE at kafka.cluster.EndPoint$.$anonfun$createEndPoint$2(EndPoint.scala:48)注意:自定义了监听器,则必须要配置inter.broker.listener.name 确定好内部的broker之间通信的监听器. 并确保能够正常访问。 这样Broker直接就会通过内网互相连接, 客户端除了可以通过内网连接(如果在内网环境的话),也可以通过外网连接。 几种场景的配置方式1. 一台机器部署一套集群这种场景一般是自己开发测试的时候, 比如自己搭建一个集群,学习学习,但是又没有那么多机器,那么就可以在一台电脑上部署多个Broker。 只配置listeners属性 listeners = 监听名称://your.host.name:port关于监听名称,默认的映射关系有4种。 PLAINTEXT => PLAINTEXT 不需要授权,非加密通道SSL => SSL 使用SSL加密通道SASL_PLAINTEXT => SASL_PLAINTEXT 使用SASL认证非加密通道SASL_SSL => SASL_SSL 使用SASL认证并且SSL加密通道简单一点,用PLAINTEXT就够了, 这里我们可以把host给去掉, 或者使用localhost listeners = PLAINTEXT://:port 或者 listeners = PLAINTEXT://localhost:port如果没有配置host,会调用java.net.InetAddress.getCanonicalHostName()获取本机host. 默认情况下就是localhost. 这里之所以建议你不填写具体的host,是因为一般自己搭建玩玩的时候可能网络IP会经常变动(例如家里的和公司), 如果绑定了具体的IP的话,每次重启都要更换配置就很麻烦。 可以看看Broker启动后注册到zk中的配置如下 { "features": {}, "listener_security_protocol_map": { "PLAINTEXT": "PLAINTEXT" }, "endpoints": ["PLAINTEXT://localhost:9092"], "jmx_port": -1, "port": 9092, "host": "localhost", "version": 5, "timestamp": "1647337490945" }这个endpoints 就是broker注册到zk的访问地址, 如果其他Broker或者客户端要跟这台Broker发生网络请求话, 就是拿的这里面的值。 所以,你想想看,如果是不同机器上,你配置的host是 localhost, 是不是就访问不了? 当然,listeners属性的host,我们也可以自己去hosts文件里面配置别的域名。配置域名指向的具体IP, 这样的话那还能奏效。就是每个Broker和客户端都要配置host,这就比较麻烦,所以还不如直接配置IP呢。 2. 内网环境多机器部署集群这种是绝大部分的场景, 一般公司部署集群都是在公司内网环境下, Broker之间和Broker与客户端之间都在同一个网络环境。并且安全协议都是直接PLAINTEXT(明文)或者其他 listeners=PLAINTEXT://ip:port3. 内网和外网分流listeners=INTERNAL://内网ip:port1,EXTERNAL://外网ip:port2 #把OUTSIDE 的安全协议映射成PLAINTEXT INSIDE也映射成PLAINTEXT listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT # Broker之间的连接用 INSIDE 监听器 inter.broker.listener.name=INTERNAL配置了两个监听器,每个Brokerinter.broker.listener.name=INTERNAL 使用内网交流。 其他的客户端例如Producer和Consumer 请求的时候直接访问外网IP. 4. 内网和外网和Controller分流listeners=INTERNAL://内网ip:port1,EXTERNAL://外网ip:port2,CONTROLLER://内网ip:port3, #把OUTSIDE 的安全协议映射成PLAINTEXT INSIDE也映射成PLAINTEXT listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT # Broker之间的连接用 INSIDE 监听器 inter.broker.listener.name=INTERNAL control.plane.listener.name=CONTROLLER这样配置 Controller2Broker或者Broker2ControllerBroker2BrokerClients2Broker他们都会会有独立的网络通信线程 你好,我是彦祖,滴滴Kafka技术专家,LogiKM PMC, CSDN 年度博客之星Topc5、华为云MVP。 现在在深度参与开源社区的建设。 |
CopyRight 2018-2019 实验室设备网 版权所有 |