关于kafka:Kafka-监听器详解

55次阅读

共计 6987 个字符,预计需要花费 18 分钟才能阅读完成。

Kafka 监听器详解

Kafka Assistant 是一款 Kafka GUI 管理工具——治理 Broker,Topic,Group、查看生产详情、监控服务器状态、反对多种音讯格局。

[TOC]

你须要将 advertised.listeners(如果你应用 Docker 镜像,则为 KAFKA_ADVERTISED_LISTENERS)设置为内部地址(host/IP),以便客户端能够正确地连贯到它。否则,他们会尝试连贯到外部主机地址 – 如果无奈达到,问题就会接踵而来。

换一种说法,由 Spencer Ruport 提供。

listeners 是 Kafka 所绑定的接口。advertised.listeners 是客户端的连贯形式。

在这篇文章中,我将议论为什么这是有必要的配置 listenersadvertised.listeners,而后展现如何基于几个场景 –Docker 和 AWS 来做。

是谁在监听

Apache Kafka 是一个分布式系统。数据是从一个给定的分区的领导者那里读取和写入的,这个领导者能够是集群中的任何一个 Broker。当一个客户端(生产者 / 消费者)启动时,它将申请对于哪个 broker 是一个分区的领导者的元数据 – 它能够从任何 broker 那里做到这一点。返回的元数据将包含该分区的领导者 broker 的可用端点,而后客户端将应用这些端点连贯到 broker,依据须要读 / 写数据。

正是这些端点给人们带来了麻烦。在单机上,运行裸机(没有虚拟机,没有 Docker),可能只须要应用主机名(或只是 localhost),这很容易。然而,一旦你进入更简单的网络设置和多节点,你就必须更加留神。

让咱们假如你有一个以上的网络。比方:

  • Docker 外部网络()加上主机
  • 云中的 Broker(如 AWS EC2)和本地的企业外部机器(甚至在另一个云中)。

你须要通知 Kafka Broker 如何互相分割,但也要确保内部客户端(生产者 / 消费者)能够分割到他们须要分割的 Broker。

最要害的是,当你运行一个客户端时,你传递给它的 Broker 只是它要去的中央,并从那里取得集群中 Broker 的元数据。它为读 / 写数据而连贯的理论主机和 IP 是基于 Broker 在初始连贯中传递回来的数据 – 即便它只是一个繁多的节点,而且返回的 Broker 与它所连贯的 Broker 雷同。

为了正确配置,你须要理解 Kafka Broker 能够有多个监听器。一个监听器是一个组合:

  • Host/IP
  • Port
  • Protocol

让咱们来看看一些配置。通常状况下,协定也被用于监听器的名称,但在这里,让咱们通过应用监听器的形象名称来使它变得丑陋和清晰。

KAFKA_LISTENERS: LISTENER_BOB://kafka0:29092,LISTENER_FRED://localhost:9092
KAFKA_ADVERTISED_LISTENERS: LISTENER_BOB://kafka0:29092,LISTENER_FRED://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_BOB:PLAINTEXT,LISTENER_FRED:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_BOB

我应用的是 Docker 配置名称 – 如果你间接配置 server.properties(例如,在 AWS 等),其对应名称在以下列表中缩进显示。

  • KAFKA_LISTENERS 是一个以逗号分隔的监听器列表,以及 Kafka 绑定监听的主机 /IP 和端口。对于更简单的网络,这可能是一个与机器上的特定网络接口相干的 IP 地址。默认是 0.0.0.0,这意味着在所有接口上进行监听。

    • listeners
  • KAFKA_ADVERTISED_LISTENERS 是一个以逗号分隔的监听器列表,包含它们的主机 /IP 和端口。这是传回给客户端的元数据。

    • advertised.listeners
  • KAFKA_LISTENER_SECURITY_PROTOCOL_MAP 定义了每个监听器名称要应用的平安协定的键 / 值对。

    • listener.security.protocol.map

Kafka Broker 之间的通信,通常是在外部网络(如 Docker 网络,AWS VPC 等)。要定义应用哪个监听器,请指定 KAFKA_INTER_BROKER_LISTENER_NAMEinter.broker.listener.name)。应用的主机 /IP 必须是其他人能够从 Broker 机器上拜访的。

Kafka 客户端很可能不在 Broker 的网络中,这就是额定监听器的作用。

每个监听器在被连贯到时,都会报告它能够被接连到的地址。你达到 Broker 的地址取决于所应用的网络。如果你从外部网络连接到经纪人,它将是一个不同于内部连贯的主机 /IP。

当连贯到 Broker 时,返回给客户端的监听器将是你连贯到的监听器(基于端口)。

kafkacat 是一个摸索这个问题的有用工具。应用 -L,你能够看到你所连贯的监听器的元数据。基于上述雷同的监听器配置(LISTENER_BOB/LISTENER_FRED),留神察看返回的后果:

  • 在 9092 端口(咱们映射为 LISTENER_FRED)进行连贯,Broker 的地址被反馈为 localhost

    $ kafkacat -b kafka0:9092 \
           -L
    Metadata for all topics (from broker -1: kafka0:9092/bootstrap):
    1 brokers:
    broker 0 at localhost:9092
  • 在 29092 端口(咱们将其映射为 LISTENER_BOB)进行连贯,Broker 的地址被反馈为 kafka0。

    $ kafkacat -b kafka0:29092 \
               -L
    Metadata for all topics (from broker 0: kafka0:29092/0):
    1 brokers:
      broker 0 at kafka0:29092

你也能够用 tcpdump 来查看连贯到 Broker 服务器的客户端的流量,并发现从代理服务器返回的主机名。

为什么我能够连贯到 Broker,但客户端依然失败?

即便你能与 Broker 建设初始连贯,在元数据中返回的地址依然可能是一个你的客户端无法访问的主机名。

让咱们一步一步来剖析。

  1. 咱们在 AWS 上有一个 Broker。咱们想从咱们的笔记本电脑向它发送一个音讯。咱们晓得 EC2 实例的内部主机名(ec2-54-191-84-122.us-west-2.compute.amazonaws.com)。咱们曾经在平安组中创立了必要的条目,为咱们的入站流量关上 Broker 的端口。保险起见,还要查看咱们的本地机器是否能够连贯到 AWS 实例上的端口。

    $ nc -vz ec2-54-191-84-122.us-west-2.compute.amazonaws.com 9092
    found 0 associations
    found 1 connections:
        1:  flags=82<CONNECTED,PREFERRED>
      outif utun5
      src 172.27.230.23 port 53352
      dst 54.191.84.122 port 9092
      rank info not available
      TCP aux info available

    咱们连上了 9092 端口,持续

    echo "test"|kafka-console-producer --broker-list ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 --topic test
    

    这一步产生了什么:

    • 咱们的笔记本电脑胜利地解析了 ec2-54-191-84-122.us-west-2.compute.amazonaws.com(到 IP 地址 54.191.84.122),并在 9092 端口连贯到 AWS 的机器。
    • Broker 在端口 9092 上接支出站连贯。它把元数据返回给客户端,主机名是ip-172-31-18-160.us-west-2.compute.internal,因为这是 Broker 的主机名和监听器的默认值。
    • 而后,客户端试图应用它被赋予的元数据向代理发送数据。因为 ip-172-31-18-160.us-west-2.compute.internal 不能从互联网上解析,所以它失败了。

      $ echo "test"|kafka-console-producer --broker-list ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 --topic test
      >>[2022-07-30 15:08:41,932] ERROR Error when sending message to topic test with key: null, value: 4 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
      org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for test-0: 1547 ms has passed since batch creation plus linger time
    • 然而,如果咱们从 Broker 所在的机器上尝试同样的事件。

      $ echo "foo"|kafka-console-producer --broker-list ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 --topic test
      >>
      $ kafka-console-consumer --bootstrap-server ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 --topic test --from-beginning
      foo

      它工作得很好! 这是因为咱们正在连接到 9092 端口,它被配置为外部监听器,因而报告其主机名为 ip-172-31-18-160.us-west-2.compute.internal,这能够从 Broker 机器上解析(因为这是它本人的主机名!)。

    • 咱们能够通过应用 kafkacat -L 标记,看到 Broker 返回的元数据。

      $ kafkacat -b ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 -L
      Metadata for all topics (from broker -1: ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092/bootstrap):
      1 brokers:
        broker 0 at ip-172-31-18-160.us-west-2.compute.internal:9092

      很显著,外部主机名被返回。这也使得这个看似凌乱的谬误变得更有意义 – 连贯到一个主机名,在另一个主机上失去一个查问谬误。

      $ kafkacat -b ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092 -C -t test
      % ERROR: Local: Host resolution failure: ip-172-31-18-160.us-west-2.compute.internal:9092/0: Failed to resolve 'ip-172-31-18-160.us-west-2.compute.internal:9092': nodename nor servname provided, or not known

      这里,咱们在本地机器上应用消费者模式(-C)的 kafkacat 来尝试从主题中读取。和以前一样,因为咱们从元数据中的 Broker 那里失去了外部监听器的主机名,所以客户端无奈解析这个主机名来进行读 / 写。

批改我的 hosts 文件

我看到一个 Stack Overflow 的答案,倡议间接更新我的 hosts 文件 …… 这不是更简略吗?
这能够解决问题,而不是真正修复它。

如果 Broker 服务器报告了一个客户端无奈连贯的主机名,那么在本地 /etc/hosts 中硬编码主机名 /IP 组合可能看起来是一个很好的修复。但这是一个十分软弱的、手动的解决方案。当 IP 发生变化时,当你挪动主机而遗记带配置 hosts 时,以及当其他人想做同样的事件时,会产生什么?

理解并理论修复你的网络的 advertised.listeners 设置要好得多。

如何连贯在 Docker 上的 Kafka

为了在 Docker 中运行,你须要为 Kafka 配置两个监听器。

  • Docker 网络内的通信。这可能是 Broker 之间的通信以及在 Docker 中运行的其余组件之间的通信,如 Kafka Connect 或第三方客户端或生产者。对于这些通信,咱们须要应用 Docker 容器的主机名。同一 Docker 网络上的每个 Docker 容器将应用 Kafka Broker 容器的主机名来达到它。
  • 非 Docker 网络流量。这可能是在 Docker 主机上本地运行的客户端,例如。假如他们将在 localhost 上连贯到从 Docker 容器裸露进去的端口。这是 Docker Compose 的片段。

    • Docker 网络中的客户端应用监听器 BOB 进行连贯,端口为 29092,主机名为 kafka0。这样做,他们会失去要连贯的主机名 kafka0。每个 Docker 容器将应用 Docker 的外部网络来解析 kafka0,并可能达到 Broker。
    • Docker 网络内部(但都在同一个 Host Machine 里)的客户端应用监听器 FRED 连贯,端口为 9092,主机名为 localhost。9092 端口是由 Docker 容器裸露的,因而能够连贯到。当客户端连贯时,他们被赋予 Broker 元数据的主机名 localhost,因而在读 / 写数据时连贯到此。
    • 上述配置无奈解决 Docker 内部和主机内部的客户端想要连贯的状况。这是因为无论是 kafka0(Docker 外部的主机名)还是 localhost(Docker 主机的环回地址)都是无奈解析的。

如何连贯到 AWS/IaaS 上的 Kafka

我命名 AWS 是因为它是大多数人应用的,但这实用于任何 IaaS/ 云解决方案。

这里实用的概念与 Docker 完全相同。次要的区别是,在 Docker 中,内部连贯很可能只是在 localhost 上(如上),而在云托管的 Kafka 中(如 AWS 上),内部连贯将来自非本地的机器。

另一个简单的问题是,尽管 Docker 网络与主机的网络重大隔离,但在 IaaS 上,内部主机名往往是能够在外部解析的,这使得你可能真正遇到这些问题时,一发不可收拾。

有两种办法,取决于你要连贯到 Broker 服务器的内部地址是否也能够在网络(如 VPC)上的所有 Broker 服务器上进行本地解析。

选项 1:内部地址是能够在本地解析的

在这里,你能够用一个监听器搞定。现有的监听器叫 PLAINTEXT,只须要设置 advertised.listeners(即传递给入站客户的那个)。

advertised.listeners=PLAINTEXT://ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092

当初外部和内部的连贯都将应用 ec2-54-191-84-122.us-west-2.compute.amazonaws.com 进行连贯。因为 ec2-54-191-84-122.us-west-2.com compute.amazonaws.com 既能够在本地也能够在内部解决,所以事件停顿顺利。

选项 2:内部地址在本地无奈解析

你将须要为 Kafka 配置两个监听器。

  • AWS 网络(VPC)内的通信。这可能是 Broker 之间的通信和在 VPC 中运行的其余组件之间的通信,如 Kafka Connect 或第三方客户端或生产商。对于这些通信,咱们须要应用 EC2 机器的外部 IP(或主机名,如果配置了 DNS)。
  • 内部 AWS 流量。这可能是测试来自笔记本电脑的连贯,或者只是来自不在亚马逊托管的机器。在这两种状况下,须要应用实例的内部 IP(或主机名,如果配置了 DNS)。

上面是一个例子:

listeners=INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
advertised.listeners=INTERNAL://ip-172-31-18-160.us-west-2.compute.internal:19092,EXTERNAL://ec2-54-191-84-122.us-west-2.compute.amazonaws.com:9092
inter.broker.listener.name=INTERNAL

原文地址:

  • Kafka Listeners – Explained

正文完
 0