搜索

在 RHEL 中使用 AMQ Streams

download PDF
Red Hat AMQ 2021.Q3

用于 Red Hat Enterprise Linux 上的 AMQ Streams 1.8

摘要

本指南描述了如何安装、配置和管理 Red Hat AMQ Streams 来构建大规模消息传递网络。

使开源包含更多

红帽承诺替换我们的代码、文档和网页属性中存在问题的语言。我们从这四个术语开始: master、slave、blacklist 和 whitelist。这些更改将在即将发行的几个发行本中逐渐实施。如需了解更多详细信息,请参阅 CTO Chris Wright 信息

第 1 章 AMQ 流概述

Red Hat AMQ Streams 是一个可大规模扩展、分布式且高性能的数据流平台,基于 Apache ZooKeeper 和 Apache Kafka 项目。

主要组成部分包括:

Kafka Broker

负责将记录从生成客户端传送到使用客户端的消息传递代理.

Apache ZooKeeper 是 Kafka 的核心依赖项,为高度可靠的分布式协调提供集群协调服务。

Kafka Streams API
用于编写 流处理器 应用程序的 API。
生产者和消费者 API
基于 Java 的 API,用于生成和消费与 Kafka 代理来回的消息。
Kafka Bridge
AMQ Streams Kafka Bridge 提供了一个 RESTful 接口,允许基于 HTTP 的客户端与 Kafka 集群交互。
Kafka Connect
使用 Connector 插件在 Kafka 代理和其他系统间流传输数据的工具包。
Kafka MirrorMaker
在数据中心内或数据中心内两个 Kafka 集群之间复制数据。
Kafka Exporter
在提取用于监控的 Kafka 指标数据时使用的导出器。

Kafka 代理集群是连接所有这些组件的 hub。代理使用 Apache ZooKeeper 来存储配置数据和集群协调。在运行 Apache Kafka 之前,Apache ZooKeeper 集群必须就绪。

图 1.1. AMQ 流架构

AMQ Streams architecture

1.1. Kafka 功能

Kafka 的底层数据流处理功能和组件架构可以提供:

  • 微服务和其他应用以极高的吞吐量和低延迟共享数据
  • 消息排序保证
  • 从数据存储中重获/重播消息以重建应用程序状态
  • 使用键值日志时删除旧记录的消息紧凑
  • 集群配置中的水平可扩展性
  • 数据复制来控制容错
  • 保留大量数据以便立即访问

1.2. Kafka 用例

Kafka 的功能使其适合:

  • 事件驱动的架构
  • 事件源,以捕获对应用状态的更改作为事件日志
  • 消息代理
  • 网站活动跟踪
  • 通过指标进行操作监控
  • 日志收集和聚合
  • 为分布式系统提交日志
  • 流处理,以便应用程序能够实时响应数据

1.3. 支持的配置

要在受支持的配置中运行,AMQ Streams 必须在以下 JVM 版本或受支持的操作系统之一中运行。

表 1.1. 支持的 Java 虚拟机列表
Java 虚拟机版本

OpenJDK

1.8, 11

OracleJDK

1.8, 11

IBM JDK

1.8

表 1.2. 支持的操作系统列表
操作系统构架版本

Red Hat Enterprise Linux

x86_64

7.x, 8.x

1.4. 文档惯例

Replaceables

在这个文档中,可替换的文本风格在 monospace 中,使用斜体、大写和连字符。

例如,在以下代码中,您要将 BOOTSTRAP-ADDRESSTOPIC-NAME 替换为您自己的地址和主题名称:

bin/kafka-console-consumer.sh --bootstrap-server BOOTSTRAP-ADDRESS --topic TOPIC-NAME --from-beginning

第 2 章 入门

2.1. AMQ 流分布

AMQ Streams 以单个 ZIP 文件进行分发。这个 ZIP 文件包含 AMQ Streams 组件:

2.2. 下载 AMQ Streams 归档

可以从红帽网站下载 AMQ Streams 的存档发行版。您可以按照以下步骤下载发行本。

流程

2.3. 安装 AMQ Streams

按照以下步骤在 Red Hat Enterprise Linux 上安装 AMQ Streams 的最新版本。

有关将现有集群升级到 AMQ Streams 1.8 的说明,请参阅 AMQ Streams 和 Kafka 升级

先决条件

流程

  1. 添加新 kafka 用户和组。

    sudo groupadd kafka
    sudo useradd -g kafka kafka
    sudo passwd kafka
  2. 创建目录 /opt/kafka

    sudo mkdir /opt/kafka
  3. 创建一个临时目录,并提取 AMQ Streams ZIP 文件的内容。

    mkdir /tmp/kafka
    unzip amq-streams_y.y-x.x.x.zip -d /tmp/kafka
  4. 将提取的内容移到 /opt/kafka 目录中,并删除临时目录。

    sudo mv /tmp/kafka/kafka_y.y-x.x.x/* /opt/kafka/
    rm -r /tmp/kafka
  5. /opt/kafka 目录的所有权更改为 kafka 用户。

    sudo chown -R kafka:kafka /opt/kafka
  6. 创建用于存储 ZooKeeper 数据的目录 /var/lib/zookeeper,并将其所有权设置为 kafka 用户。

    sudo mkdir /var/lib/zookeeper
    sudo chown -R kafka:kafka /var/lib/zookeeper
  7. 创建用于存储 Kafka 数据的目录 /var/lib/kafka,并将其所有权设置为 kafka 用户。

    sudo mkdir /var/lib/kafka
    sudo chown -R kafka:kafka /var/lib/kafka

2.4. 数据存储注意事项

高效的数据存储基础架构对于 AMQ 流的最佳性能至关重要。

AMQ 流需要块存储,并且非常适合基于云的块存储解决方案,如 Amazon Elastic Block Store(EBS)。不建议使用文件存储。

尽可能选择本地存储。如果本地存储不可用,您可以使用由协议(如光纤通道或 iSCSI)访问的存储区域网络(SAN)。

2.4.1. Apache Kafka 和 ZooKeeper 存储支持

Apache Kafka 和 ZooKeeper 使用单独的磁盘。

Kafka 支持 JBOD(只是磁盘绑定)存储,支持多个磁盘或卷的数据存储配置。JBOD 为 Kafka 代理提供更多数据存储。它还能提高性能。

在异步发送和从多个主题接收数据的大型集群中,固态驱动器(SSD)(虽然不必要)可以提高 Kafka 的性能。SSD 在 ZooKeeper 中特别有效,它需要快速、低延迟的数据访问。

注意

您不需要置备复制存储,因为 Kafka 和 ZooKeeper 都内置了数据复制。

2.4.2. 文件系统

建议您将存储系统配置为使用 XFS 文件系统。AMQ Streams 还与 ext4 文件系统兼容,但为了获得最佳结果,可能需要额外的配置。

其它资源

2.5. 运行单个节点 AMQ Streams 集群

此流程演示了如何运行由单个 Apache ZooKeeper 节点和单个 Apache Kafka 节点组成的基本 AMQ Streams 集群,它们在同一主机上运行。默认配置文件用于 ZooKeeper 和 Kafka。

警告

单一节点 AMQ Streams 集群不提供可靠性和高可用性,仅适用于开发目的。

先决条件

  • 在主机上安装 AMQ Streams

运行集群

  1. 编辑 ZooKeeper 配置文件 /opt/kafka/config/zookeeper.properties。将 dataDir 选项设置为 /var/lib/zookeeper/:

    dataDir=/var/lib/zookeeper/
  2. 编辑 Kafka 配置文件 /opt/kafka/config/server.properties。将 log.dirs 选项设置为 /var/lib/kafka/:

    log.dirs=/var/lib/kafka/
  3. 切换到 kafka 用户:

    su - kafka
  4. 启动 ZooKeeper:

    /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties
  5. 检查 ZooKeeper 是否正在运行:

    jcmd | grep zookeeper

    返回:

    number org.apache.zookeeper.server.quorum.QuorumPeerMain /opt/kafka/config/zookeeper.properties
  6. 启动 Kafka:

    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  7. 检查 Kafka 是否正在运行:

    jcmd | grep kafka

    返回:

    number kafka.Kafka /opt/kafka/config/server.properties

其它资源

2.6. 使用集群

这个步骤描述了如何启动 Kafka 控制台制作者和消费者客户端,并使用它们发送和接收多个信息。

在第 1 步中自动创建一个新主题。主题自动创建使用 auto.create.topics.enable 配置属性(默认设置为 true )进行控制。或者,您可以在使用集群前配置和创建主题。如需更多信息,请参阅 主题

流程

  1. 启动 Kafka 控制台制作者并将其配置为发送消息到新主题:

    /opt/kafka/bin/kafka-console-producer.sh --broker-list <bootstrap-address> --topic <topic-name>

    例如:

    /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-topic
  2. 在控制台中输入多个消息。按 Enter 将每个单独消息发送到您的新主题:

    >message 1
    >message 2
    >message 3
    >message 4

    当 Kafka 自动创建一个新主题时,您可能会收到一个表明该主题不存在的警告:

    WARN Error while fetching metadata with correlation id 39 :
    {4-3-16-topic1=LEADER_NOT_AVAILABLE} (org.apache.kafka.clients.NetworkClient)

    发送进一步消息后,不应重新显示警告。

  3. 在新的终端窗口中,启动 Kafka 控制台使用者并将其配置为从新主题开始时读取消息。

    /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server <bootstrap-address> --topic <topic-name> --from-beginning

    例如:

    /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-topic --from-beginning

    传入的消息显示在使用者控制台中。

  4. 切换到制作者控制台并发送其他消息。检查它们是否显示在使用者控制台中。
  5. Ctrl+C 停止 Kafka 控制台制作者,再停止使用者

2.7. 停止 AMQ Streams 服务

您可以通过运行脚本来停止 Kafka 和 ZooKeeper 服务。与 Kafka 和 ZooKeeper 服务的所有连接都将被终止。

先决条件

  • 在主机上安装 AMQ Streams
  • zookeeper 和 Kafka 已启动并运行

流程

  1. 停止 Kafka 代理。

    su - kafka
    /opt/kafka/bin/kafka-server-stop.sh
  2. 确认 Kafka 代理已被停止。

    jcmd | grep kafka
  3. 停止 ZooKeeper。

    su - kafka
    /opt/kafka/bin/zookeeper-server-stop.sh

2.8. 配置 AMQ 流

先决条件

  • 主机上下载并安装 AMQ Streams

流程

  1. 在文本编辑器中打开 ZooKeeper 和 Kafka 代理配置文件。配置文件位于:

    ZooKeeper
    /opt/kafka/config/zookeeper.properties
    kafka
    /opt/kafka/config/server.properties
  2. 编辑配置选项。配置文件采用 Java 属性格式。每个配置选项都应以以下格式位于单独的行中:

    <option> = <value>

    #! 开头的行将被视为注释,AMQ Streams 组件将忽略这些行。

    # This is a comment

    在换行 / 回车前,可以直接使用 \ 将值分成多行。

    sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
        username="bob" \
        password="bobs-password";
  3. 保存更改
  4. 重启 ZooKeeper 或 Kafka 代理
  5. 在集群的所有节点上重复此步骤。

第 3 章 配置 ZooKeeper

Kafka 使用 ZooKeeper 来存储配置数据和集群协调。强烈建议运行复制的 ZooKeeper 实例群集。

3.1. 基本配置

最重要的 ZooKeeper 配置选项有:

tickTime
zookeeper 的基本时间单元(以毫秒为单位)。它用于心跳和会话超时。例如,最小会话超时将为两个 ticks。
dataDir
ZooKeeper 存储其事务日志和内存中数据库快照的目录。这应该设置为安装期间创建的 /var/lib/zookeeper/ 目录。
clientPort
客户端可以连接的端口号。默认值为 2181

名为 config/zookeeper.properties 的 ZooKeeper 配置文件示例位于 AMQ Streams 安装目录中。建议将 dataDir 目录放在单独的磁盘设备中,以便最大程度缩短 ZooKeeper 中的延迟。

zookeeper 配置文件应位于 /opt/kafka/config/zookeeper.properties 中。配置文件的基本示例如下所示:配置文件必须可由 kafka 用户读取。

tickTime=2000
dataDir=/var/lib/zookeeper/
clientPort=2181

3.2. zookeeper 集群配置

在大多数生产环境中,我们建议您部署复制的 ZooKeeper 实例集群。对于运行可靠的 ZooKeeper 服务而言,稳定且高度可用的 ZooKeeper 集群非常重要。zookeeper 集群也称为 ensemble s

zookeeper 集群通常由奇数节点组成。zookeeper 需要集群中的大多数节点都已启动并运行。例如:

  • 在具有三个节点的群集中,至少有两个节点必须已启动并在运行。这意味着它可以容忍一个节点停机。
  • 在由五个节点组成的群集中,必须至少有三个节点可用。这意味着它可以容忍两个节点停机。
  • 在一个由 7 个节点组成的集群中,必须至少有四个节点可用。这意味着它可以容忍三个节点停机。

在 ZooKeeper 集群中拥有更多节点可提高整个集群的弹性和可靠性。

zookeeper 可以在具有偶数节点的集群中运行。但是,额外的节点不会增加集群的弹性。具有四个节点的群集要求至少三个节点可用,并且只能容忍一个节点停机。因此,它与只有三个节点的集群具有完全相同的弹性。

理想情况下,不同的 ZooKeeper 节点应位于不同的数据中心或网络段内。增加 ZooKeeper 节点的数量会增加群集同步所花费的工作负载。在大多数 Kafka 用例中,带有 3、5 或 7 节点的 ZooKeeper 集群应该足够了。

警告

具有 3 个节点的 ZooKeeper 集群只能容忍 1 个不可用的节点。这意味着,如果在另一个节点上维护时集群节点崩溃,ZooKeeper 集群将无法使用。

复制 ZooKeeper 配置支持独立配置支持的所有配置选项。为集群配置添加了附加选项:

initLimit
允许跟随者连接并同步集群领导器的时间。时间被指定为多个勾号(更多详情请参阅 timeTick 选项 )。
syncLimit
追随者在领导后面的时间。时间被指定为多个勾号(更多详情请参阅 timeTick 选项 )。
reconfigEnabled
启用或禁用 动态重新配置。必须启用才能向 ZooKeeper 集群添加或删除服务器。
standaloneEnabled
启用或禁用独立模式,即 ZooKeeper 仅在一台服务器中运行。

除上述选项外,每个配置文件还应包含属于 ZooKeeper 群集成员的服务器列表。服务器记录应该以 server.id=hostname:port1:port2 格式指定,其中:

id
ZooKeeper 集群节点的 ID。
hostname
节点侦听连接的主机名或 IP 地址。
port1
用于集群内部通信的端口号。
port2
用于领导选举的端口号。

以下是具有三个节点的 ZooKeeper 集群配置文件示例:

timeTick=2000
dataDir=/var/lib/zookeeper/
initLimit=5
syncLimit=2
reconfigEnabled=true
standaloneEnabled=false

server.1=172.17.0.1:2888:3888:participant;172.17.0.1:2181
server.2=172.17.0.2:2888:3888:participant;172.17.0.2:2181
server.3=172.17.0.3:2888:3888:participant;172.17.0.3:2181
注意

在 ZooKeeper 3.5.7 中,必须先将 四个字母 命令添加到 allow 列表中,然后才能使用它们。如需更多信息,请参阅 ZooKeeper 文档

myid 文件

ZooKeeper 集群中每个节点都必须被分配一个唯一的 ID。每个节点的 ID 必须配置在 myid 文件中,并存储在 dataDir 文件夹中,如 /var/lib/zookeeper/myid 文件应只包含一个行,其中的 ID 写为文本。ID 可以是 1 到 255 的任何整数。您必须在每个集群节点上手动创建此文件。使用这个文件,每个 ZooKeeper 实例将使用配置文件 server. 行中的相应配置来配置其监听程序。它还将使用所有其他 server. 行识别其他群集成员。

在上例中,有三个节点,因此每个节点都有不同的 myid,其值分别为 123

3.3. 运行多节点 ZooKeeper 集群

此流程将为您显示如何将 ZooKeeper 配置为多节点集群。

注意

在 ZooKeeper 3.5.7 中,必须先将 四个字母 命令添加到 allow 列表中,然后才能使用它们。如需更多信息,请参阅 ZooKeeper 文档

先决条件

  • AMQ Streams 安装在所有用作 ZooKeeper 群集节点的主机上。

运行集群

  1. /var/lib/zookeeper/ 中创建 myid 文件。为第一个 ZooKeeper 节点输入 ID 1,为第二个 ZooKeeper 节点输入 2,以此类推。

    su - kafka
    echo "<NodeID>" > /var/lib/zookeeper/myid

    例如:

    su - kafka
    echo "1" > /var/lib/zookeeper/myid
  2. 编辑 ZooKeeper /opt/kafka/config/zookeeper.properties 配置文件:

    • 将选项 dataDir 设置为 /var/lib/zookeeper/
    • 配置 initLimitsyncLimit 选项。
    • 配置 reconfigEnabledstandaloneEnabled 选项。
    • 添加所有 ZooKeeper 节点的列表。该列表还应包含当前节点。

      具有五个成员的 ZooKeeper 集群配置示例

      timeTick=2000
      dataDir=/var/lib/zookeeper/
      initLimit=5
      syncLimit=2
      reconfigEnabled=true
      standaloneEnabled=false
      
      server.1=172.17.0.1:2888:3888:participant;172.17.0.1:2181
      server.2=172.17.0.2:2888:3888:participant;172.17.0.2:2181
      server.3=172.17.0.3:2888:3888:participant;172.17.0.3:2181
      server.4=172.17.0.4:2888:3888:participant;172.17.0.4:2181
      server.5=172.17.0.5:2888:3888:participant;172.17.0.5:2181

  3. 使用默认配置文件启动 ZooKeeper。

    su - kafka
    /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties
  4. 验证 ZooKeeper 是否正在运行。

    jcmd | grep zookeeper
  5. 在集群的所有节点上重复此步骤。
  6. 当集群的所有节点都启动并运行后,使用 ncat 工具向每个节点发送 stat 命令来验证所有节点是否为集群成员。

    使用 ncat stat 检查节点状态

    echo stat | ncat localhost 2181

    在输出中,您应该看到该节点是 leaderfollower 的信息。

    ncat 命令的输出示例

    ZooKeeper version: 3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 00:39 GMT
    Clients:
     /0:0:0:0:0:0:0:1:59726[0](queued=0,recved=1,sent=0)
    
    Latency min/avg/max: 0/0/0
    Received: 2
    Sent: 1
    Connections: 1
    Outstanding: 0
    Zxid: 0x200000000
    Mode: follower
    Node count: 4

其它资源

3.4. Authentication

默认情况下,ZooKeeper 不使用任何形式的身份验证并允许匿名连接。但是,它支持 Java 身份验证与授权服务(JAAS),可用于使用简单身份验证和安全层(SASL)设置身份验证。zookeeper 支持使用带有本地存储的凭证的 DIGEST-MD5 SASL 机制进行身份验证。

3.4.1. 使用 SASL 进行身份验证

JAAS 使用单独的配置文件进行配置。建议将 JAAS 配置文件放在与 ZooKeeper 配置相同的目录中(/opt/kafka/config/)。推荐的文件名是 zookeeper-jaas.conf。将 ZooKeeper 群集与多个节点搭配使用时,必须在所有群集节点上创建 JAAS 配置文件。

JAAS 使用上下文进行配置。服务器和客户端等独立部分始终配置有单独的 上下文。该上下文是一个 配置选项,具有以下格式:

ContextName {
       param1
       param2;
};

SASL 身份验证是单独配置的,用于服务器对服务器通信( ZooKeeper 实例之间的通信)和客户端对服务器通信( Kafka 和 ZooKeeper 之间的通信)。服务器对服务器身份验证仅与具有多个节点的 ZooKeeper 集群相关。

服务器到服务器的身份验证

对于服务器到服务器身份验证,JAAS 配置文件包含两个部分:

  • 服务器配置
  • 客户端配置

使用 DIGEST-MD5 SASL 机制时,QuorumServer 上下文用于配置身份验证服务器。它必须包含允许所有用户名,以便其以未加密的形式与其密码连接。第二个上下文 QuorumLearner 必须为内置在 ZooKeeper 中的客户端配置。它还包含未加密格式的密码。以下是 DIGEST-MD5 机制的 JAAS 配置文件示例:

QuorumServer {
       org.apache.zookeeper.server.auth.DigestLoginModule required
       user_zookeeper="123456";
};

QuorumLearner {
       org.apache.zookeeper.server.auth.DigestLoginModule required
       username="zookeeper"
       password="123456";
};

除了 JAAS 配置文件外,还必须通过指定以下选项在常规 ZooKeeper 配置文件中启用服务器到服务器身份验证:

quorum.auth.enableSasl=true
quorum.auth.learnerRequireSasl=true
quorum.auth.serverRequireSasl=true
quorum.auth.learner.loginContext=QuorumLearner
quorum.auth.server.loginContext=QuorumServer
quorum.cnxn.threads.size=20

使用 KAFKA_OPTS 环境变量将 JAAS 配置文件作为 Java 属性传递给 ZooKeeper 服务器:

su - kafka
export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/zookeeper-jaas.conf"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

有关服务器到服务器身份验证的更多信息,请参阅 ZooKeeper wiki

客户端到服务器身份验证

客户端到服务器身份验证在与服务器到服务器身份验证相同的 JAAS 文件中配置。但是,与服务器对服务器身份验证不同,它仅包含服务器配置。配置的客户端部分必须在客户端中完成。有关如何将 Kafka 代理配置为使用身份验证连接到 ZooKeeper 的详情,请参考 Kafka 安装 部分。

将服务器上下文添加到 JAAS 配置文件,以配置客户端到服务器的身份验证。对于 DIGEST-MD5 机制,它会配置所有用户名和密码:

Server {
    org.apache.zookeeper.server.auth.DigestLoginModule required
    user_super="123456"
    user_kafka="123456"
    user_someoneelse="123456";
};

配置 JAAS 上下文后,通过添加以下行,在 ZooKeeper 配置文件中启用客户端到服务器身份验证:

requireClientAuthScheme=sasl
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
authProvider.2=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
authProvider.3=org.apache.zookeeper.server.auth.SASLAuthenticationProvider

您必须为作为 ZooKeeper 集群一部分的每个服务器添加 authProvider.<ID> 属性。

使用 KAFKA_OPTS 环境变量将 JAAS 配置文件作为 Java 属性传递给 ZooKeeper 服务器:

su - kafka
export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/zookeeper-jaas.conf"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

有关在 Kafka 代理中配置 ZooKeeper 身份验证的详情请参考 第 4.6 节 “zookeeper 身份验证”

3.4.2. 使用 DIGEST-MD5 启用服务器到服务器的身份验证

这个步骤描述了如何在 ZooKeeper 集群的节点之间使用 SASL DIGEST-MD5 机制启用身份验证。

先决条件

  • 在主机上安装 AMQ Streams
  • zookeeper 集群配置 了多个节点。

启用 SASL DIGEST-MD5 身份验证

  1. 在所有 ZooKeeper 节点上,创建或编辑 /opt/kafka/config/zookeeper-jaas.conf JAAS 配置文件并添加以下上下文:

    QuorumServer {
           org.apache.zookeeper.server.auth.DigestLoginModule required
           user_<Username>="<Password>";
    };
    
    QuorumLearner {
           org.apache.zookeeper.server.auth.DigestLoginModule required
           username="<Username>"
           password="<Password>";
    };

    在 JAAS 上下文中,用户名和密码必须相同。例如:

    QuorumServer {
           org.apache.zookeeper.server.auth.DigestLoginModule required
           user_zookeeper="123456";
    };
    
    QuorumLearner {
           org.apache.zookeeper.server.auth.DigestLoginModule required
           username="zookeeper"
           password="123456";
    };
  2. 在所有 ZooKeeper 节点上,编辑 /opt/kafka/config/zookeeper.properties ZooKeeper 配置文件并设置以下选项:

    quorum.auth.enableSasl=true
    quorum.auth.learnerRequireSasl=true
    quorum.auth.serverRequireSasl=true
    quorum.auth.learner.loginContext=QuorumLearner
    quorum.auth.server.loginContext=QuorumServer
    quorum.cnxn.threads.size=20
  3. 逐个重启所有 ZooKeeper 节点。要将 JAAS 配置传递给 ZooKeeper,请使用 KAFKA_OPTS 环境变量。

    su - kafka
    export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/zookeeper-jaas.conf"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

其它资源

3.4.3. 使用 DIGEST-MD5 启用客户端到服务器身份验证

这个步骤描述了如何使用 ZooKeeper 客户端和 ZooKeeper 之间的 SASL DIGEST-MD5 机制启用验证。

先决条件

启用 SASL DIGEST-MD5 身份验证

  1. 在所有 ZooKeeper 节点上,创建或编辑 /opt/kafka/config/zookeeper-jaas.conf JAAS 配置文件并添加以下上下文:

    Server {
        org.apache.zookeeper.server.auth.DigestLoginModule required
        user_super="<SuperUserPassword>"
        user<Username1>_="<Password1>"用户"<USername2>_="<Password2>";
    };

    super 自动具有管理员特权。该文件可以包含多个用户,但 Kafka 代理只需要一个用户。Kafka 用户的建议名称是 kafka

    以下示例显示了客户端到服务器身份验证的 Server 上下文:

    Server {
        org.apache.zookeeper.server.auth.DigestLoginModule required
        user_super="123456"
        user_kafka="123456";
    };
  2. 在所有 ZooKeeper 节点上,编辑 /opt/kafka/config/zookeeper.properties ZooKeeper 配置文件并设置以下选项:

    requireClientAuthScheme=sasl
    authProvider.<IdOfBroker1>=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
    authProvider.<IdOfBroker2>=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
    authProvider.<IdOfBroker3>=org.apache.zookeeper.server.auth.SASLAuthenticationProvider

    必须为每个节点添加 authProvider.<ID> 属性,这是 ZooKeeper 集群的一部分。三节点 ZooKeeper 集群配置示例必须类似如下:

    requireClientAuthScheme=sasl
    authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
    authProvider.2=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
    authProvider.3=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
  3. 逐个重启所有 ZooKeeper 节点。要将 JAAS 配置传递给 ZooKeeper,请使用 KAFKA_OPTS 环境变量。

    su - kafka
    export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/zookeeper-jaas.conf"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

其它资源

3.5. 授权

zookeeper 支持访问控制列表(ACL),以保护其中存储的数据。Kafka 代理可以自动为所创建的所有 ZooKeeper 记录配置 ACL 权限,以便其他 ZooKeeper 用户无法修改它们。

有关在 Kafka 代理中启用 ZooKeeper ACL 的详情请参考 第 4.8 节 “zookeeper 授权”

3.6. TLS

zookeeper 支持 TLS 加密或身份验证。

3.7. 其他配置选项

您可以根据您的用例设置以下额外的 ZooKeeper 配置选项:

maxClientCnxns
与 ZooKeeper 集群单个成员的最大并发客户端连接数。
autopurge.snapRetainCount
ZooKeeper 内存中数据库的快照数量,将被保留。默认值为 3
autopurge.purgeInterval
清除快照的时间间隔(以小时为单位)。默认值为 0,这个选项被禁用。

可在 ZooKeeper 文档中 找到所有可用的配置选项。

3.8. 日志

zookeeper 将 log4j 用作 其日志记录基础架构。默认情况下,日志记录配置是从 log4j.properties 配置文件读取的,该文件应放在 /opt/kafka/config/ 目录中或类路径中。配置文件的位置和名称可使用 Java 属性 log4j.configuration 更改,该属性可使用 KAFKA_LOG4J_OPTS 环境变量传递给 ZooKeeper:

su - kafka
export KAFKA_LOG4J_OPTS="-Dlog4j.configuration=file:/my/path/to/log4j.properties"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

有关 Log4j 配置的更多信息,请参阅 Log4j 文档

第 4 章 配置 Kafka

Kafka 使用属性文件来存储静态配置。配置文件的建议位置是 /opt/kafka/config/server.properties。配置文件必须可由 kafka 用户读取。

AMQ Streams 附带了一个示例配置文件,其中重点介绍了该产品的各种基本和高级功能。它可以在 AMQ Streams 安装目录中的 config/server.properties 下找到。

本章解释了最重要的配置选项。有关支持 Kafka 代理配置选项的完整列表,请参阅 附录 A, 代理配置参数

4.1. ZooKeeper

Kafka 代理需要 ZooKeeper 存储其配置的某些部分并协调集群(例如,决定哪个节点是哪个分区的领导机)。ZooKeeper 集群的连接详情保存在配置文件中。zookeeper.connect 字段包含以逗号分隔的 zookeeper 集群成员的主机名和端口列表。

例如:

zookeeper.connect=zoo1.my-domain.com:2181,zoo2.my-domain.com:2181,zoo3.my-domain.com:2181

Kafka 将使用这些地址连接到 ZooKeeper 集群。使用这个配置,所有 Kafka znodes 都将直接在 ZooKeeper 数据库的根目录中创建。因此,此类 ZooKeeper 集群只能用于单个 Kafka 集群。要将多个 Kafka 集群配置为使用单个 ZooKeeper 集群,请在 Kafka 配置文件中的 ZooKeeper 连接字符串的末尾指定一个基本(前缀)路径:

zookeeper.connect=zoo1.my-domain.com:2181,zoo2.my-domain.com:2181,zoo3.my-domain.com:2181/my-cluster-1

4.2. 监听程序

侦听器用于连接到 Kafka 代理。每个 Kafka 代理都可以配置为使用多个监听程序。每个侦听器都需要不同的配置,以便能够侦听不同的端口或网络接口。

要配置监听程序,请编辑 配置文件(/opt/kafka/config/server.properties)中的 listeners 属性。以逗号分隔列表的形式在 listeners 属性中添加监听程序。按如下方式配置每个属性:

<listenerName>://<hostname>:<port>

如果 <hostname> 为空,Kafka 使用 java.net.InetAddress.getCanonicalHostName() 类作为主机名。

多个监听器的配置示例

listeners=internal-1://:9092,internal-2://:9093,replication://:9094

当 Kafka 客户端想要连接到 Kafka 集群时,它首先连接到 bootstrap 服务器,这是集群节点之一。bootstrap 服务器为客户端提供集群中所有代理的列表,客户端分别连接到每个代理。代理列表基于配置的 listeners

公告的监听程序

另外,您可以使用 advertised.listeners 属性为客户端提供与 listeners 属性中给出的监听器地址不同的监听程序地址集合。这在客户端和代理之间的额外网络基础架构(如代理)或使用外部 DNS 名称而不是 IP 地址时很有用。

advertised.listeners 属性的格式与 listeners 属性相同。

公告的监听器的配置示例

listeners=internal-1://:9092,internal-2://:9093
advertised.listeners=internal-1://my-broker-1.my-domain.com:1234,internal-2://my-broker-1.my-domain.com:1235

注意

公告的监听程序的名称必须与 listeners 属性中列出的名称匹配。

内联监听程序

broker 侦听程序 用于 Kafka 代理之间的通信。以下对象需要代理间通信:

  • 协调不同代理之间的工作负载
  • 在存储在不同代理中的分区间复制消息
  • 处理控制器的管理任务,如分区领导更改

可以将代理间监听程序分配到您选择的端口。当配置了多个监听程序时,您可以在 inter.broker.listener.name 属性中定义 Inter-broker 侦听程序的名称。

在这里,broker 侦听程序命名为 REPLICATION

listeners=REPLICATION://0.0.0.0:9091
inter.broker.listener.name=REPLICATION

control plane 侦听程序

默认情况下,控制器和其他代理之间的通信使用 Inter -broker 侦听程序。控制器负责协调管理任务,如分区领导更改。

您可以为控制器连接启用专用的 control plane 侦听程序。control plane 侦听程序可分配给您选择的端口。

要启用 control plane 侦听程序,使用监听程序名称配置 control.plane.listener.name 属性:

listeners=CONTROLLER://0.0.0.0:9090,REPLICATION://0.0.0.0:9091
...
control.plane.listener.name=CONTROLLER

启用 control plane 侦听器可能会提高集群性能,因为控制器通信不会因为代理间的数据复制而延迟。数据复制继续通过代理间侦听器进行。

如果没有配置 control.plane.listener,控制器连接将使用 代理间侦听程序

如需更多信息,请参阅 附录 A, 代理配置参数

4.3. 提交日志

Apache Kafka 在提交日志中存储从生产者接收的所有记录。提交日志包含 Kafka 需要提供的实际数据,格式为 记录。这些不是记录代理正在执行的操作的应用程序日志文件。

日志目录

您可以使用 log.dirs 属性文件配置日志目录,将提交日志存储在一个或多个日志目录中。它应该设置为在安装过程中创建的 /var/lib/kafka 目录:

log.dirs=/var/lib/kafka

出于性能考虑,您可以将 log.dirs 配置为多个目录,并将每个目录放在不同的物理设备上,以提高磁盘 I/O 性能。例如:

log.dirs=/var/lib/kafka1,/var/lib/kafka2,/var/lib/kafka3

4.4. 代理 ID

代理 ID 是集群中每个代理的唯一标识符。您可以将大于或等于 0 的整数指定为代理 ID。代理 ID 用于在重启或崩溃后识别代理,因此 ID 稳定且不随时间变化非常重要。代理 ID 在代理属性文件中配置:

broker.id=1

4.5. 运行多节点 Kafka 集群

这个步骤描述了如何将 Kafka 配置为多节点集群。

先决条件

运行集群

对于 AMQ Streams 集群中的每个 Kafka 代理:

  1. 按如下方式编辑 /opt/kafka/config/server.properties Kafka 配置文件:

    • 将第一个代理的 broker.id 字段设置为 0,第二个代理为 1,以此类推。
    • zookeeper.connect 选项中配置连接到 ZooKeeper 的详情。
    • 配置 Kafka 侦听程序。
    • 设置提交日志应存储在 logs.dir 目录中的目录。

      在这里,我们会看到 Kafka 代理的配置示例:

      broker.id=0
      zookeeper.connect=zoo1.my-domain.com:2181,zoo2.my-domain.com:2181,zoo3.my-domain.com:2181
      listeners=REPLICATION://:9091,PLAINTEXT://:9092
      inter.broker.listener.name=REPLICATION
      log.dirs=/var/lib/kafka

      在典型的安装中,每个 Kafka 代理都在相同的硬件中运行,只有 broker.id 配置属性会因代理配置而异。

  2. 使用默认配置文件启动 Kafka 代理。

    su - kafka
    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  3. 验证 Kafka 代理正在运行。

    jcmd | grep Kafka

验证代理

当集群的所有节点都启动并运行后,使用 ncat 工具向其中一个 ZooKeeper 节点发送 dump 命令来验证所有节点是否都是 Kafka 集群的成员。命令打印 ZooKeeper 注册的所有 Kafka 代理。

  1. 使用 ncat stat 检查节点状态。

    echo dump | ncat zoo1.my-domain.com 2181

    输出应包含您刚才配置和启动的所有 Kafka 代理。

    带有 3 个节点的 Kafka 集群的 ncat 命令输出示例:

    SessionTracker dump:
    org.apache.zookeeper.server.quorum.LearnerSessionTracker@28848ab9
    ephemeral nodes dump:
    Sessions with Ephemerals (3):
    0x20000015dd00000:
            /brokers/ids/1
    0x10000015dc70000:
            /controller
            /brokers/ids/0
    0x10000015dc70001:
            /brokers/ids/2

其它资源

4.6. zookeeper 身份验证

默认情况下,ZooKeeper 和 Kafka 之间的连接不会被身份验证。但是 Kafka 和 ZooKeeper 支持 Java 身份验证与授权服务(JAAS),可用于使用简单身份验证和安全层(SASL)设置身份验证。zookeeper 支持使用带有本地存储的凭证的 DIGEST-MD5 SASL 机制进行身份验证。

4.6.1. JAAS Configuration

必须在 JAAS 配置文件中配置 ZooKeeper 连接的 SASL 身份验证。默认情况下,Kafka 将使用名为 Client 的 JAAS 上下文连接到 ZooKeeper。Client 上下文应在 /opt/kafka/config/jass.conf 文件中配置。该上下文必须启用 PLAIN SASL 身份验证,如下例所示:

Client {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="kafka"
    password="123456";
};

4.6.2. 启用 ZooKeeper 身份验证

这个步骤描述了如何在连接到 ZooKeeper 时使用 SASL DIGEST-MD5 机制启用验证。

先决条件

  • ZooKeeper 中启用了 客户端到服务器的身份验证

启用 SASL DIGEST-MD5 身份验证

  1. 在所有 Kafka 代理节点上,创建或编辑 /opt/kafka/config/jaas.conf JAAS 配置文件并添加以下上下文:

    Client {
        org.apache.kafka.common.security.plain.PlainLoginModule required
        username="<Username>"
        password="<Password>";
    };

    用户名和密码应与 ZooKeeper 中配置的相同。

    以下示例显示了 Client 上下文:

    Client {
        org.apache.kafka.common.security.plain.PlainLoginModule required
        username="kafka"
        password="123456";
    };
  2. 逐个重启所有 Kafka 代理节点。要将 JAAS 配置传递给 Kafka 代理,请使用 KAFKA_OPTS 环境变量。

    su - kafka
    export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/jaas.conf"; /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

其它资源

4.7. 授权

Kafka 代理中的授权是使用授权器插件实现的。

在本节中,我们将介绍如何使用 Kafka 提供的 AclAuthorizer 插件。

或者,您可以使用自己的授权插件。例如,如果您 使用基于 OAuth 2.0 令牌的身份验证,您可以使用 OAuth 2.0 授权

4.7.1. 简单 ACL 授权器

授权程序插件(包括 AclAuthorizer )通过 authorizer.class.name 属性启用:

authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer

所选授权人需填写完全限定名称。对于 AclAuthorizer,完全限定名称为 kafka.security.auth.SimpleAclAuthorizer

4.7.1.1. ACL 规则

AclAuthorizer 使用 ACL 规则管理对 Kafka 代理的访问。

ACL 规则以以下格式定义:

允许来自主机 H的 Kafka 资源 R 上的主 P /拒绝操作 O

例如,可以设置规则以便用户:

John 可以查看 主机 127.0.0.1中的主题 注释

主机是 John 连接的机器的 IP 地址。

在大多数情况下,用户是一个制作者或消费者应用程序:

Consumer01 可以从主机 127.0.0.1 写入 消费者组 帐户

如果 ACL 规则不存在

如果给定资源没有 ACL 规则,则拒绝所有操作。通过将 Kafka 配置文件 /opt/kafka/config/server.properties 中的属性 allow.everyone.if.no.acl.found 设置为 true,可更改此行为。

4.7.1.2. 主体

主体 表示用户的身份。ID 的格式取决于客户端用来连接到 Kafka 的身份验证机制:

  • User:ANONYMOUS 无身份验证连接时.
  • User:<username> 使用简单验证机制(如 PLAIN 或 SCRAM)进行连接时.

    例如 User:adminUser:user1

  • User:<DistinguishedName> 使用 TLS 客户端身份验证进行连接时.

    例如 User:CN=user1,O=MyCompany,L=Prague,C=CZ

  • User:<Kerberos username> 使用 Kerberos 进行连接时.

DistinguishedName 是与客户端证书的可分辨名称。

Kerberos 用户名 是 Kerberos 主体的主要部分,在使用 Kerberos 连接时默认使用它。您可以使用 sasl.kerberos.principal.to.local.rules 属性配置从 Kerberos 主体构建 Kafka 主体的方式。

4.7.1.3. 用户验证

要使用授权,您需要启用身份验证并供您的客户端使用。否则,所有连接都有主体 User:ANONYMOUS

有关身份验证方法的更多信息,请参阅 加密和身份验证

4.7.1.4. 超级用户

无论 ACL 规则如何,超级用户都可执行所有操作。

超级用户在 Kafka 配置文件中使用属性 super.users 定义。

例如:

super.users=User:admin,User:operator
4.7.1.5. 副本代理验证

启用授权后,它将应用到所有监听器和所有连接。这包括用于在代理之间复制数据的代理间连接。因此,如果启用授权,请确保您对代理使用身份验证进行间隔,并授予代理使用的用户足够的权限。例如,如果代理之间的身份验证使用 kafka-broker 用户,那么超级用户配置必须包含用户名 super.users=User:kafka-broker

4.7.1.6. 支持的资源

您可以将 Kafka ACL 应用到这些资源类型:

  • 主题
  • 消费者组
  • 集群
  • transactionID
  • DelegationToken
4.7.1.7. 支持的操作

AclAuthorizer 授权对资源的操作.

下表中带有 X 的字段标记每个资源支持的操作。

表 4.1. 资源的操作
 主题消费者组Cluster

X

X

 

X

  

create

  

X

删除

X

  

更改

X

  

describe

X

X

X

ClusterAction

  

X

all

X

X

X

4.7.1.8. ACL 管理选项

ACL 规则通过 bin/kafka-acls.sh 工具来管理,该工具作为 Kafka 分发软件包的一部分提供。

使用 kafka-acls.sh 参数选项添加、列出和删除 ACL 规则并执行其他功能。

参数需要双连规则,如 --add

选项类型描述Default(默认)

add

操作

添加 ACL 规则.

 

remove

操作

删除 ACL 规则.

 

list

操作

列出 ACL 规则.

 

authorizer

操作

授权人的完全限定类名称。

kafka.security.auth.SimpleAclAuthorizer

authorizer-properties

Configuration

传递给授权者的键/值对进行初始化.

对于 AclAuthorizer,示例值为: zookeeper.connect=zoo1.my-domain.com:2181

 

bootstrap-server

资源

用于连接到 Kafka 集群的主机/端口对。

使用这个选项或 authorizer 选项,而不是两者。

command-config

资源

要传递给 Admin 客户端的配置属性文件,与 bootstrap-server 参数结合使用。

 

cluster

资源

将集群指定为 ACL 资源。

 

topic

资源

将主题名称指定为 ACL 资源。

星号(*)用作通配符转换为 所有主题

单个命令可以指定多个 --topic 选项。

 

group

资源

指定使用者组名称作为 ACL 资源。

单个命令可以指定多个 --group 选项。

 

transactional-id

资源

将事务 ID 指定为 ACL 资源。

事务发送意味着生产者向多个分区发送的所有消息都必须成功发送或全部发送。

星号(*)用作通配符转换为 所有 ID

 

delegation-token

资源

将委派令牌指定为 ACL 资源。

星号(*)用作通配符转换为 所有令牌

 

resource-pattern-type

Configuration

add 参数指定资源模式,或者为 listremove 参数指定资源模式过滤器值。

使用 literalprefixed 作为资源名称的资源类型。

使用 anymatch 作为资源模式过滤器值,或者使用特定模式类型过滤器。

literal

allow-principal

主体

添加到允许 ACL 规则中的主体.

单个命令可以指定多个 --allow-principal 选项。

 

deny-principal

主体

添加至拒绝 ACL 规则中的主体.

单个命令可以指定多个 --deny-principal 选项。

 

principal

主体

list 参数一起使用的主体名称,为主体返回 ACL 列表。

单个命令可以指定多个 --principal 选项。

 

allow-host

主机

允许访问 --allow-principal 中列出的主体的 IP 地址。

不支持主机名或 CIDR 范围。

如果指定了 --allow-principal,则默认为 * 表示"所有主机"。

deny-host

主机

拒绝访问 --deny-principal 中列出的主体的 IP 地址。

不支持主机名或 CIDR 范围。

如果指定了 --deny-principal,则默认为 * 表示"所有主机"。

operation

操作

允许或拒绝操作.

单个命令可以在单个命令中指定多个Multiple --operation 选项。

all

producer

快捷键

允许或拒绝消息制作者需要的所有操作的快捷方式(群集上的 WRITE 和 DESCRIBE,即 CREATE)。

 

consumer

快捷键

允许或拒绝消息使用者需要的所有操作的快捷方式(READ 和 DESCRIBE 针对主题,READ 在使用者组中)。

 

idempotent

快捷键

--producer 参数一起使用时启用幂等的快捷方式,以便信息只传送一次到分区。

如果生产者有权根据特定的事务 ID 发送消息,Idepmotence 会自动启用。

 

force

快捷键

接受所有查询且不提示的快捷方式。

 

4.7.2. 启用授权

这个步骤描述了如何在 Kafka 代理中为授权启用 AclAuthorizer 插件。

先决条件

流程

  1. 编辑 /opt/kafka/config/server.properties Kafka 配置文件以使用 AclAuthorizer

    authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
  2. (重新)启动 Kafka 代理。

其它资源

4.7.3. 添加 ACL 规则

AclAuthorizer 使用访问控制列表(ACL),定义一组规则,说明用户可以和无法执行的操作。

这个步骤描述了如何在 Kafka 代理中使用 AclAuthorizer 插件时添加 ACL 规则。

使用 kafka-acls.sh 工具添加规则并存储在 ZooKeeper 中。

先决条件

流程

  1. 使用 --add 选项运行 kafka-acls.sh

    示例:

    • 允许 user1user2 使用 MyConsumerGroup 消费者组从 myTopic 读取。

      bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --add --operation Read --topic myTopic --allow-principal User:user1 --allow-principal User:user2
      
      bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --add --operation Describe --topic myTopic --allow-principal User:user1 --allow-principal User:user2
      
      bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --add --operation Read --operation Describe --group MyConsumerGroup --allow-principal User:user1 --allow-principal User:user2
    • 拒绝从 IP 地址主机 127.0.0.1 读取 myTopicuser1 访问。

      bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --add --operation Describe --operation Read --topic myTopic --group MyConsumerGroup --deny-principal User:user1 --deny-host 127.0.0.1
    • 使用 MyConsumerGroup 添加 user1 作为 myTopic 的使用者。

      bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --add --consumer --topic myTopic --group MyConsumerGroup --allow-principal User:user1

其它资源

4.7.4. 列出 ACL 规则

这个步骤描述了如何在 Kafka 代理中使用 AclAuthorizer 插件时列出现有的 ACL 规则。

规则使用 kafka-acls.sh 工具列出。

先决条件

流程

  • 使用 --list 选项运行 kafka-acls.sh

    例如:

    $ bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --list --topic myTopic
    
    Current ACLs for resource `Topic:myTopic`:
    
    User:user1 has Allow permission for operations: Read from hosts: *
    User:user2 has Allow permission for operations: Read from hosts: *
    User:user2 has Deny permission for operations: Read from hosts: 127.0.0.1
    User:user1 has Allow permission for operations: Describe from hosts: *
    User:user2 has Allow permission for operations: Describe from hosts: *
    User:user2 has Deny permission for operations: Describe from hosts: 127.0.0.1

其它资源

4.7.5. 删除 ACL 规则

这个步骤描述了如何在 Kafka 代理中使用 AclAuthorizer 插件时删除 ACL 规则。

使用 kafka-acls.sh 工具删除规则。

先决条件

流程

  • 使用 --remove 选项运行 kafka-acls.sh

    示例:

  • 删除 ACL,允许使用 MyConsumerGroup consumer 组从 myTopic 中读取 user1user2 访问权限。

    bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --remove --operation Read --topic myTopic --allow-principal User:user1 --allow-principal User:user2
    
    bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --remove --operation Describe --topic myTopic --allow-principal User:user1 --allow-principal User:user2
    
    bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --remove --operation Read --operation Describe --group MyConsumerGroup --allow-principal User:user1 --allow-principal User:user2
  • 使用 MyConsumerGroup 删除将 user1 添加为 myTopic 的使用者的 ACL。

    bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --remove --consumer --topic myTopic --group MyConsumerGroup --allow-principal User:user1
  • 删除 ACL 拒绝从 IP 地址主机 127.0.0.1 读取 myTopicuser1 访问权限。

    bin/kafka-acls.sh --authorizer-properties zookeeper.connect=zoo1.my-domain.com:2181 --remove --operation Describe --operation Read --topic myTopic --group MyConsumerGroup --deny-principal User:user1 --deny-host 127.0.0.1

其它资源

4.8. zookeeper 授权

当 Kafka 和 ZooKeeper 间启用身份验证时,您可以使用 ZooKeeper Access Control List(ACL)规则自动控制对存储在 ZooKeeper 中的 Kafka 元数据的访问。

4.8.1. ACL 配置

ZooKeeper ACL 规则的强制由 config/server.properties Kafka 配置文件中的 zookeeper.set.acl 属性控制。

该属性默认是禁用的,并通过设置为 true 来启用。

zookeeper.set.acl=true

如果启用了 ACL 规则,在 ZooKeeper 中创建 znode 时,创建它的 Kafka 用户可以修改或删除它。所有其他用户具有只读访问权限。

Kafka 只为新创建的 ZooKeeper znodes 设置 ACL 规则。如果在集群第一次启动后启用 ACL,则 zookeeper-security-migration.sh 工具可以为所有现有 znodes 设置 ACL。

ZooKeeper 中数据的机密性

ZooKeeper 中存储的数据包括:

  • 主题名称及其配置
  • 使用 SASL SCRAM 身份验证时,alted 和 hashed 用户凭据.

但是 ZooKeeper 不会存储使用 Kafka 发送和接收的任何记录。在 ZooKeeper 中存储的数据假定为非机密性。

如果要将数据视为机密(例如,主题名称包含客户 ID),唯一的保护选项是隔离网络级别的 ZooKeeper,仅允许访问 Kafka 代理。

4.8.2. 为新 Kafka 集群启用 ZooKeeper ACL

这个步骤描述了如何在 Kafka 配置中为新 Kafka 集群启用 ZooKeeper ACL。只有在 Kafka 集群第一次启动前使用此流程。有关在已在运行的集群中启用 ZooKeeper ACL 的详情,请参考 第 4.8.3 节 “在现有 Kafka 集群中启用 ZooKeeper ACL”

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。
  • zookeeper 集群 已配置并运行
  • ZooKeeper 中启用了 客户端到服务器的身份验证。
  • Kafka 代理中 启用了 zoo keeper 身份验证。
  • Kafka 代理尚未启动。

流程

  1. 编辑 /opt/kafka/config/server.properties Kafka 配置文件,将所有集群节点上的 zookeeper.set.acl 字段设置为 true

    zookeeper.set.acl=true
  2. 启动 Kafka 代理。

4.8.3. 在现有 Kafka 集群中启用 ZooKeeper ACL

这个步骤描述了如何在 Kafka 配置中为正在运行的 Kafka 集群启用 ZooKeeper ACL。使用 zookeeper-security-migration.sh 工具为所有现有 znodes 设置 ZooKeeper ACL。zookeeper-security-migration.sh 作为 AMQ Streams 的一部分提供,可以在 bin 目录中找到。

先决条件

启用 ZooKeeper ACL

  1. 编辑 /opt/kafka/config/server.properties Kafka 配置文件,将所有集群节点上的 zookeeper.set.acl 字段设置为 true

    zookeeper.set.acl=true
  2. 逐个重启所有 Kafka 代理。
  3. 使用 zookeeper-security-migration.sh 工具为所有现有 ZooKeeper znodes 设置 ACL。

    su - kafka
    cd /opt/kafka
    KAFKA_OPTS="-Djava.security.auth.login.config=./config/jaas.conf"; ./bin/zookeeper-security-migration.sh --zookeeper.acl=secure --zookeeper.connect=<ZooKeeperURL>
    exit

    例如:

    su - kafka
    cd /opt/kafka
    KAFKA_OPTS="-Djava.security.auth.login.config=./config/jaas.conf"; ./bin/zookeeper-security-migration.sh --zookeeper.acl=secure --zookeeper.connect=zoo1.my-domain.com:2181
    exit

4.9. 加密和身份验证

AMQ Streams 支持加密和身份验证,它们是监听器配置的一部分。

4.9.1. 监听程序配置

每个监听程序都在 Kafka 代理中配置加密和身份验证。有关 Kafka 监听程序配置的详情请参考 第 4.2 节 “监听程序”

Kafka 代理中的每个监听程序都配置了自己的安全协议。配置属性 listener.security.protocol.map 定义哪个侦听器使用哪个安全协议。它将每个侦听器名称映射到其安全协议。支持的安全协议有:

PLAINTEXT
没有任何加密或身份验证的监听程序.
SSL
使用 TLS 加密以及可选地使用 TLS 客户端证书进行身份验证的监听程序。
SASL_PLAINTEXT
无加密侦听器,但具有基于 SASL 的身份验证.
SASL_SSL
侦听基于 TLS 的加密和基于 SASL 的身份验证.

根据以下 listeners 配置:

listeners=INT1://:9092,INT2://:9093,REPLICATION://:9094

listener.security.protocol.map 可能类似如下:

listener.security.protocol.map=INT1:SASL_PLAINTEXT,INT2:SASL_SSL,REPLICATION:SSL

这会将监听器 INT1 配置为使用与 SASL 身份验证的未加密连接,监听器 INT2 使用 SASL 身份验证的加密连接和 REPLICATION 接口使用 TLS 加密(可能与 TLS 客户端身份验证一样)。同一安全协议可以多次使用。以下示例也是有效的配置:

listener.security.protocol.map=INT1:SSL,INT2:SSL,REPLICATION:SSL

此类配置对所有接口使用 TLS 加密和 TLS 身份验证。以下章节将更详细地阐述如何配置 TLS 和 SASL。

4.9.2. TLS 加密

Kafka 支持使用 TLS 加密与 Kafka 客户端的通信。

要使用 TLS 加密和服务器身份验证,必须提供含有私钥和公钥的密钥存储。这通常使用 Java 密钥存储(JKS)格式的文件完成。在 ssl.keystore.location 属性中设置该文件的路径。ssl.keystore.password 属性应该用来设置保护密钥存储的密码。例如:

ssl.keystore.location=/path/to/keystore/server-1.jks
ssl.keystore.password=123456

在某些情况下,使用额外的密码来保护私钥。任何此类密码都可以使用 ssl.key.password 属性设置。

Kafka 可以使用证书颁发机构签名的密钥以及自签名证书。使用证书颁发机构签名的密钥应始终是首选方法。为了允许客户端验证要连接到的 Kafka 代理的身份,证书应始终包含公告的主机名作为其通用名称(CN)或在 Subject alternatives Names(SAN)中。

可以将不同的 SSL 配置用于不同的侦听器。以 ssl. 开始的所有选项都可以带有 listener.name.<NameOfTheListener>. 前缀,其中监听器的名称必须始终为小写。这将覆盖该特定侦听器的默认 SSL 配置。以下示例演示了如何在不同的侦听器中使用不同的 SSL 配置:

listeners=INT1://:9092,INT2://:9093,REPLICATION://:9094
listener.security.protocol.map=INT1:SSL,INT2:SSL,REPLICATION:SSL

# Default configuration - will be used for listeners INT1 and INT2
ssl.keystore.location=/path/to/keystore/server-1.jks
ssl.keystore.password=123456

# Different configuration for listener REPLICATION
listener.name.replication.ssl.keystore.location=/path/to/keystore/server-1.jks
listener.name.replication.ssl.keystore.password=123456

其他 TLS 配置选项

除了上述主要 TLS 配置选项外,Kafka 还支持许多选项来微调 TLS 配置。例如,启用或禁用 TLS / SSL 协议或密码套件:

ssl.cipher.suites
启用的密码套件列表。每个密码套件都是用于 TLS 连接的身份验证、加密、MAC 和密钥交换算法的组合。默认情况下,所有可用的密码套件都是启用的。
ssl.enabled.protocols
启用的 TLS/SSL 协议列表.默认值为 TLSv1.2,TLSv1.1,TLSv1

有关支持 Kafka 代理配置选项的完整列表,请参阅 附录 A, 代理配置参数

4.9.3. 启用 TLS 加密

这个步骤描述了如何在 Kafka 代理中启用加密。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。

流程

  1. 为集群中的所有 Kafka 代理生成 TLS 证书。证书应在其 Common Name 或 Subject Alternative Name 中包括它们公告的 bootstrap 地址。
  2. 编辑所有集群节点中的 /opt/kafka/config/server.properties Kafka 配置文件。

    • 更改 listener.security.protocol.map 字段,为您要使用 TLS 加密的监听程序指定 SSL 协议。
    • ssl.keystore.location 选项设置为使用代理证书的 JKS 密钥存储的路径。
    • ssl.keystore.password 选项设置为用来保护密钥存储的密码。

      例如:

      listeners=UNENCRYPTED://:9092,ENCRYPTED://:9093,REPLICATION://:9094
      listener.security.protocol.map=UNENCRYPTED:PLAINTEXT,ENCRYPTED:SSL,REPLICATION:PLAINTEXT
      ssl.keystore.location=/path/to/keystore/server-1.jks
      ssl.keystore.password=123456
  3. (重新)启动 Kafka 代理

其它资源

4.9.4. Authentication

要进行身份验证,您可以使用:

4.9.4.1. TLS 客户端身份验证

TLS 客户端身份验证只能用于已使用 TLS 加密的连接。要使用 TLS 客户端身份验证,可以向代理提供带有公钥的信任存储。这些密钥可用于验证连接到代理的客户端。信任存储应以 Java 密钥存储(JKS)格式提供,并且应包含证书颁发机构的公钥。所有由信任存储中包含的其中一个认证机构签名的公钥和私钥的客户端都将被验证。truststore 的位置使用字段 ssl.truststore.location 进行设置。如果信任存储受密码保护,应在 ssl.truststore.password 属性中设置密码。例如:

ssl.truststore.location=/path/to/keystore/server-1.jks
ssl.truststore.password=123456

配置信任存储后,必须使用 ssl.client.auth 属性启用 TLS 客户端身份验证。此属性可以设置为以下三个不同值之一:

none
TLS 客户端身份验证已关闭。(默认值)
requested
TLS 客户端身份验证是可选的。将要求客户端使用 TLS 客户端证书进行身份验证,但可以选择不要这样做。
required
客户端需要使用 TLS 客户端证书进行身份验证。

当客户端使用 TLS 客户端身份验证进行身份验证时,经过身份验证的主体名称是与经过身份验证的客户端证书的区分名称。例如:具有可分辨名称 CN=someuser 的证书用户将使用以下主体 CN=someuser,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown 进行身份验证。如果不使用 TLS 客户端身份验证,并且禁用 SASL,则主体名称为 ANONYMOUS

4.9.4.2. SASL 身份验证

SASL 身份验证使用 Java 身份验证和授权服务(JAAS)进行配置。JAAS 也用于验证 Kafka 和 ZooKeeper 之间的连接。JAAS 使用自己的配置文件。此文件的建议位置是 /opt/kafka/config/jaas.conf。该文件必须可由 kafka 用户读取。运行 Kafka 时,使用 Java 系统属性 java.security.auth.login.config 指定此文件的位置。启动代理节点时,必须将此属性传递给 Kafka:

KAFKA_OPTS="-Djava.security.auth.login.config=/path/to/my/jaas.config"; bin/kafka-server-start.sh

SASL 身份验证既通过普通的未加密连接,也受 TLS 连接支持。可以为每个侦听器单独启用 SASL。要启用它,listener.security.protocol.map 中的安全协议必须是 SASL_PLAINTEXTSASL_SSL

Kafka 中的 SASL 身份验证支持多种不同的机制:

PLAIN
基于用户名和密码实施身份验证。用户名和密码存储在 Kafka 配置中。
SCRAM-SHA-256SCRAM-SHA-512
使用交换挑战响应身份验证机制(SCRAM)实施身份验证。SCRAM 凭据集中存储在 ZooKeeper 中。SCRAM 可用于 ZooKeeper 群集节点在专用网络中隔离运行的情况。
GSSAPI
针对 Kerberos 服务器实施身份验证.
警告

PLAIN 机制以未加密格式通过网络发送用户名和密码。因此,它应当仅与 TLS 加密结合使用。

SASL 机制通过 JAAS 配置文件进行配置。Kafka 使用名为 KafkaServer 的 JAAS 上下文。在 JAAS 中配置它们后,必须在 Kafka 配置中启用 SASL 机制。这使用 sasl.enabled.mechanisms 属性完成。此属性包含一个以逗号分隔的启用机制列表:

sasl.enabled.mechanisms=PLAIN,SCRAM-SHA-256,SCRAM-SHA-512

如果用于broker 间通信的监听程序使用 SASL,则必须使用 sasl.mechanism.inter.broker.protocol 属性指定它应使用的 SASL 机制。例如:

sasl.mechanism.inter.broker.protocol=PLAIN

必须在 KafkaServer JAAS 上下文中使用 usernamepassword 字段指定用于内部通信的用户名和密码。

SASL PLAIN

要使用 PLAIN 机制,允许连接的用户名和密码直接在 JAAS 上下文中指定。以下示例显示了为 SASL PLAIN 身份验证配置的上下文。这个示例配置了三个不同的用户:

  • admin
  • user1
  • user2
KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    user_admin="123456"
    user_user1="123456"
    user_user2="123456";
};

包含用户数据库的 JAAS 配置文件应该在所有 Kafka 代理上保持同步。

当 SASL PLAIN 也用于代理间验证时,usernamepassword 属性应包含在 JAAS 上下文中:

KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="admin"
    password="123456"
    user_admin="123456"
    user_user1="123456"
    user_user2="123456";
};

SASL SCRAM

Kafka 中的 SCRAM 身份验证由两个机制组成: SCRAM-SHA-256SCRAM-SHA-512。这些机制仅在所用的哈希算法 - SHA-256 与更强大的 SHA-512 之间有所不同。要启用 SCRAM 身份验证,JAAS 配置文件必须包括以下配置:

KafkaServer {
    org.apache.kafka.common.security.scram.ScramLoginModule required;
};

在 Kafka 配置文件中启用 SASL 身份验证时,可以列出这两个 SCRAM 机制。但是,它们中只能选择其中之一作为代理间通信。例如:

sasl.enabled.mechanisms=SCRAM-SHA-256,SCRAM-SHA-512
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-512

SCRAM 机制的用户凭据存储在 ZooKeeper 中。kafka-configs.sh 工具可用于管理它们。例如,运行以下命令来添加用户 user1,密码为 123456:

bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --add-config 'SCRAM-SHA-256=[password=123456],SCRAM-SHA-512=[password=123456]' --entity-type users --entity-name user1

要删除用户凭证,请使用:

bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name user1

SASL GSSAPI

使用 Kerberos 进行身份验证的 SASL 机制称为 GSSAPI。要配置 Kerberos SASL 身份验证,请在 JAAS 配置文件中添加以下配置:

KafkaServer {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/etc/security/keytabs/kafka_server.keytab"
    principal="kafka/kafka1.hostname.com@EXAMPLE.COM";
};

Kerberos 主体中的域名必须始终以大写形式。

除了 JAAS 配置外,Kerberos 服务名称还需要在 Kafka 配置的 sasl.kerberos.service.name 属性中指定:

sasl.enabled.mechanisms=GSSAPI
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.kerberos.service.name=kafka

多个 SASL 机制

Kafka 可以同时使用多个 SASL 机制。不同的 JAAS 配置都可以添加到同一上下文中:

KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    user_admin="123456"
    user_user1="123456"
    user_user2="123456";

    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/etc/security/keytabs/kafka_server.keytab"
    principal="kafka/kafka1.hostname.com@EXAMPLE.COM";

    org.apache.kafka.common.security.scram.ScramLoginModule required;
};

启用多个机制后,客户端将能够选择要使用的机制。

4.9.5. 启用 TLS 客户端身份验证

这个步骤描述了如何在 Kafka 代理中启用 TLS 客户端身份验证。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。
  • 启用 TLS 加密。

流程

  1. 准备包含用于签署用户证书的证书颁发机构的公钥的 JKS 信任存储。
  2. 编辑所有集群节点中的 /opt/kafka/config/server.properties Kafka 配置文件。

    • 使用用户证书认证机构将 ssl.truststore.location 选项设置为 JKS 信任存储的路径。
    • ssl.truststore.password 选项设置为用来保护信任存储的密码。
    • ssl.client.auth 选项设置为 required

      例如:

      ssl.truststore.location=/path/to/truststore.jks
      ssl.truststore.password=123456
      ssl.client.auth=required
  3. (重新)启动 Kafka 代理

其它资源

4.9.6. 启用 SASL PLAIN 身份验证

这个步骤描述了如何在 Kafka 代理中启用 SASL PLAIN 身份验证。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。

流程

  1. 编辑或创建 /opt/kafka/config/jaas.conf JAAS 配置文件。此文件应包含您的所有用户及其密码。请在所有 Kafka 代理上确保此文件相同。

    例如:

    KafkaServer {
        org.apache.kafka.common.security.plain.PlainLoginModule required
        user_admin="123456"
        user_user1="123456"
        user_user2="123456";
    };
  2. 编辑所有集群节点中的 /opt/kafka/config/server.properties Kafka 配置文件。

    • 更改 listener.security.protocol.map 字段,为您要使用 SASL PLAIN 身份验证的监听程序指定 SASL_PLAINTEXTSASL_SSL 协议。
    • sasl.enabled.mechanisms 选项设置为 PLAIN

      例如:

      listeners=INSECURE://:9092,AUTHENTICATED://:9093,REPLICATION://:9094
      listener.security.protocol.map=INSECURE:PLAINTEXT,AUTHENTICATED:SASL_PLAINTEXT,REPLICATION:PLAINTEXT
      sasl.enabled.mechanisms=PLAIN
  3. (重新)使用 KAFKA_OPTS 环境变量启动 Kafka 代理,将 JAAS 配置传递给 Kafka 代理。

    su - kafka
    export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/jaas.conf"; /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

其它资源

4.9.7. 启用 SASL SCRAM 身份验证

这个步骤描述了如何在 Kafka 代理中启用 SASL SCRAM 身份验证。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。

流程

  1. 编辑或创建 /opt/kafka/config/jaas.conf JAAS 配置文件。为 KafkaServer 上下文启用 ScramLoginModule。请在所有 Kafka 代理上确保此文件相同。

    例如:

    KafkaServer {
        org.apache.kafka.common.security.scram.ScramLoginModule required;
    };
  2. 编辑所有集群节点中的 /opt/kafka/config/server.properties Kafka 配置文件。

    • 更改 listener.security.protocol.map 字段,为您要使用 SASL SCRAM 身份验证的监听程序指定 SASL_PLAINTEXTSASL_SSL 协议。
    • sasl.enabled.mechanisms 选项设置为 SCRAM-SHA-256SCRAM-SHA-512

      例如:

      listeners=INSECURE://:9092,AUTHENTICATED://:9093,REPLICATION://:9094
      listener.security.protocol.map=INSECURE:PLAINTEXT,AUTHENTICATED:SASL_PLAINTEXT,REPLICATION:PLAINTEXT
      sasl.enabled.mechanisms=SCRAM-SHA-512
  3. (重新)使用 KAFKA_OPTS 环境变量启动 Kafka 代理,将 JAAS 配置传递给 Kafka 代理。

    su - kafka
    export KAFKA_OPTS="-Djava.security.auth.login.config=/opt/kafka/config/jaas.conf"; /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

其它资源

4.9.8. 添加 SASL SCRAM 用户

这个步骤描述了如何使用 SASL SCRAM 添加新用户进行身份验证。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。
  • SASL SCRAM 身份验证 已启用

流程

  • 使用 kafka-configs.sh 工具添加新的 SASL SCRAM 用户。

    bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --alter --add-config 'SCRAM-SHA-512=[password=<Password>]' --entity-type users --entity-name <Username>

    例如:

    bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --add-config 'SCRAM-SHA-512=[password=123456]' --entity-type users --entity-name user1

其它资源

4.9.9. 删除 SASL SCRAM 用户

这个步骤描述了在使用 SASL SCRAM 身份验证时如何删除用户。

先决条件

  • AMQ Streams 安装 在所有用作 Kafka 代理的主机上。
  • SASL SCRAM 身份验证 已启用

流程

  • 使用 kafka-configs.sh 工具删除 SASL SCRAM 用户。

    bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name <Username>

    例如:

    bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --delete-config 'SCRAM-SHA-512' --entity-type users --entity-name user1

其它资源

4.10. 使用基于 OAuth 2.0 令牌的身份验证

AMQ Streams 支持使用 OAUTHBEARERPLAIN 机制的 OAuth 2.0 身份验证。

OAuth 2.0 支持应用之间基于令牌的标准化身份验证和授权,使用中央授权服务器发布对资源的有限访问权限的令牌。

Kafka 代理和客户端都需要配置为使用 OAuth 2.0。您可以配置 OAuth 2.0 身份验证,然后配置 OAuth 2.0 授权

注意

通过使用 OAuth 2.0 身份验证,应用程序客户端可以访问应用服务器(称为 资源服务器)上的资源,而无需公开帐户凭据。

应用客户端通过访问令牌来进行身份验证,应用服务器也可以使用该令牌来确定要授予的访问权限级别。授权服务器处理关于访问权限的访问和咨询。

在 AMQ Streams 中:

  • Kafka 代理充当 OAuth 2.0 资源服务器
  • Kafka 客户端充当 OAuth 2.0 应用程序客户端

Kafka 客户端向 Kafka 代理进行身份验证。代理和客户端根据需要与 OAuth 2.0 授权服务器通信,以获取或验证访问令牌。

对于 AMQ Streams 的部署,OAuth 2.0 集成提供:

  • 对 Kafka 代理的服务器端 OAuth 2.0 支持
  • 客户端 OAuth 2.0 支持 Kafka MirrorMaker、Kafka Connect 和 Kafka Bridge

RHEL 上的 AMQ Streams 包括两个 OAuth 2.0 库:

kafka-oauth-client
提供一个名为 io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler 的自定义登录回调处理程序类。要处理 OAUTHBEARER 身份验证机制,请使用由 Apache Kafka 提供的 OAuthBearerLoginModule 登录回调处理程序。
kafka-oauth-common
提供 kafka-oauth-client 库所需的一些功能的帮助程序库。

提供的客户端库还依赖于一些额外的第三方库,如 keycloak-corejackson-databindslf4j-api

我们建议使用 Maven 项目打包您的客户端,以确保包含所有依赖项库。依赖库可能会在以后的版本中有所变化。

为 Kafka 客户端 Java 库提供了一个 OAuth 回调处理程序,因此您不需要为 Java 客户端自行编写回调处理程序。应用客户端可以使用回调处理程序来提供访问令牌。以其他语言编写的客户端(如 Go)必须使用自定义代码连接到授权服务器并获取访问令牌。

其它资源

4.10.1. OAuth 2.0 身份验证机制

AMQ Streams 支持 OAUTHBEARER 和 PLAIN 机制进行 OAuth 2.0 身份验证。这两种机制都允许 Kafka 客户端通过 Kafka 代理建立经过身份验证的会话。客户端、授权服务器和 Kafka 代理之间的身份验证流程因每种机制而异。

建议您将客户端配置为尽可能使用 OAUTHBEARER。OAUTHBEARER 提供比 PLAIN 更高的安全级别,因为客户端凭证 永远不会 与 Kafka 代理共享。只考虑在不支持 OAUTHBEARER 的 Kafka 客户端中使用 PLAIN。

如有必要,可以在相同的 OAuth 身份验证监听器配置中同时启用 OAUTHBEARER 和 PLAIN。

OAUTHBEARER 概述

Kafka 支持 OAUTHBEARER 身份验证机制,但必须明确配置它。许多 Kafka 客户端工具在协议级别使用为 OAUTHBEARER 提供基本支持的库。

使用 OAUTHBEARER 时,客户端会启动与 Kafka 代理的会话进行凭证交换,其中凭证采用回调处理程序提供的 bearer 令牌的形式。通过使用回调,您可以通过以下三种方法之一配置令牌置备:

  • 客户端 ID 和 Secret(使用 OAuth 2.0 客户端凭证机制
  • 长期访问令牌,在配置时手动获得
  • 长期存在的刷新令牌,在配置时手动获取

要使用 OAUTHBEARER,您必须在 Kafka 代理的 OAuth 身份验证监听程序配置中将 sasl.enabled.mechanisms 设置为 OAUTHBEARER。有关详细配置,请参阅 第 4.10.2 节 “OAuth 2.0 Kafka 代理配置”

listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER
注意

OAUTHBEARER 身份验证只能由支持协议级别的 OAUTHBEARER 机制的 Kafka 客户端使用。

PLAIN 概述

PLAIN 是所有 Kafka 客户端工具支持的简单身份验证机制,包括 kafkacat 等开发人员工具。为了启用 PLAIN 与 OAuth 2.0 身份验证一起使用,RHEL 上的 AMQ Streams 包括服务器端回调。PLAIN 的 AMQ 流实现被称为 OAuth 2.0 over PLAIN

对于 OAuth 2.0 over PLAIN,客户端凭证不会存储在 ZooKeeper 中。相反,它们在兼容授权服务器后面被集中处理,这与使用 OAUTHBEARER 身份验证时类似。

当与 OAuth 2.0 over PLAIN 回调搭配使用时,Kafka 客户端使用以下方法之一向 Kafka 代理进行身份验证:

  • 客户端 ID 和 secret(使用 OAuth 2.0 客户端凭证机制
  • 长期访问令牌,在配置时手动获得

客户端必须启用才能使用 PLAIN 身份验证,并提供 usernamepassword。如果密码前缀为 $accessToken:,后跟访问令牌的值,Kafka 代理会将密码解释为访问令牌。否则,Kafka 代理会将 username 解释为客户端 ID,password 解释为客户端 secret。

如果将 password 设置为访问令牌,username 必须设置为 Kafka 代理从访问令牌获取的相同主体名称。该进程取决于您如何使用 userNameClaimfallbackUserNameClaimfallbackUsernamePrefixuserInfoEndpointUri 配置用户名提取。它还取决于您的授权服务器;特别是,如何将客户端 ID 映射到帐户名称。

您可以在 Kafka 代理的 OAuth 验证监听程序配置中启用 PLAIN。为此,请在 sasl.enabled.mechanisms 的值中添加 PLAIN

listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER,PLAIN

有关详细配置,请参阅 第 4.10.2 节 “OAuth 2.0 Kafka 代理配置”

4.10.1.1. 使用属性或变量配置 OAuth 2.0

您可以使用 Java 身份验证和授权服务(JAAS)属性或环境变量来配置 OAuth 2.0 设置。

  • JAAS 属性在 server.properties 配置文件中配置,并作为 listener.name.LISTENER-NAME.oauthbearer.sasl.jaas.config 属性的键值对传递。
  • 如果使用环境变量,您仍需要在 server.properties 文件中提供 listener.name.LISTENER-NAME.oauthbearer.sasl.jaas.config 属性,但您可以省略其他 JAAS 属性。

    您可以使用大写或大写的环境变量命名约定。

AMQ Streams OAuth 2.0 库使用开头的属性:

4.10.2. OAuth 2.0 Kafka 代理配置

OAuth 2.0 身份验证的 Kafka 代理配置涉及:

  • 在授权服务器中创建 OAuth 2.0 客户端
  • 在 Kafka 集群中配置 OAuth 2.0 身份验证
注意

对于授权服务器,Kafka 代理和 Kafka 客户端都被视为 OAuth 2.0 客户端。

4.10.2.1. 授权服务器上的 OAuth 2.0 客户端配置

要将 Kafka 代理配置为验证在会话启动过程中收到的令牌,推荐的方法是在授权服务器中创建 OAuth 2.0 客户端 定义(配置为 机密 )并启用以下客户端凭证:

  • kafka-broker 的客户端 ID(例如)
  • 客户端 ID 和机密作为身份验证机制
注意

您只需要在使用授权服务器的非公共内省端点时使用客户端 ID 和机密。在使用公共授权服务器端点时,通常不需要凭据,如进行快速本地 JWT 令牌验证一样。

4.10.2.2. Kafka 集群中的 OAuth 2.0 身份验证配置

要在 Kafka 集群中使用 OAuth 2.0 身份验证,您可以在 Kafka server.properties 文件中为 Kafka 集群启用 OAuth 身份验证监听程序配置。最低配置是必需的。您还可以配置 TLS 侦听器,其中 TLS 用于代理间通信。

您可以使用以下方法之一配置授权服务器用于令牌验证的代理:

  • 快速本地令牌验证: JWKS 端点与签名 JWT 格式的访问令牌组合
  • 内省 端点

您可以配置 OAUTHBEARER 或 PLAIN 身份验证,或两者。

以下示例显示了应用 全局 监听器配置的最小配置,这意味着代理间通信与应用客户端通过相同的侦听器。

这个示例还显示了特定监听器的 OAuth 2.0 配置,您可以在其中指定 listener.name.LISTENER-NAME.sasl.enabled.mechanisms 而不是 sasl.enabled.mechanismsLISTENER-NAME 是监听器不区分大小写的名称。在这里,我们为监听程序命名 CLIENT,因此属性名称为 listener.name.client.sasl.enabled.mechanisms

这个示例使用 OAUTHBEARER 身份验证。

示例:使用 JWKS 端点的 OAuth 2.0 身份验证的最小侦听器配置

sasl.enabled.mechanisms=OAUTHBEARER 1
listeners=CLIENT://0.0.0.0:9092 2
listener.security.protocol.map=CLIENT:SASL_PLAINTEXT 3
listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER 4
sasl.mechanism.inter.broker.protocol=OAUTHBEARER 5
inter.broker.listener.name=CLIENT 6
listener.name.client.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler 7
listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \ 8
  oauth.valid.issuer.uri="https://AUTH-SERVER-ADDRESS" \ 9
  oauth.jwks.endpoint.uri="https://AUTH-SERVER-ADDRESS/jwks" \ 10
  oauth.username.claim="preferred_username"  \ 11
  oauth.client.id="kafka-broker" \ 12
  oauth.client.secret="kafka-secret" \ 13
  oauth.token.endpoint.uri="https://AUTH-SERVER-ADDRESS/token" ; 14
listener.name.client.oauthbearer.sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler 15
listener.name.client.oauthbearer.connections.max.reauth.ms=3600000 16

1
启用 OAUTHBEARER 机制,用于通过 SASL 进行凭据交换。
2
为要连接的客户端应用配置侦听器。系统 hostname 用作公告的主机名,客户端必须解析该主机名才能重新连接。在这个示例中,监听程序命名为 CLIENT
3
指定监听器的频道协议。SASL_SSL 用于 TLS。SASL_PLAINTEXT 用于未加密的连接(无 TLS),但存在 TCP 连接层窃听和拦截的风险。
4
指定 CLIENT 侦听器的 OAUTHBEARER 机制。客户端名称(CLIENT)通常使用大写的 listeners 属性指定,listener.name 属性(listener.name.client)小写,而 listener.name.client.* 属性的一部分则为小写。
5
指定用于代理间通信的 OAUTHBEARER 机制。
6
指定用于代理间通信的监听程序。需要指定 才能使配置有效。
7
在客户端监听程序上配置 OAuth 2.0 身份验证。
8
配置客户端和代理间通信的身份验证设置。oauth.client.idoauth.client.secretauth.token.endpoint.uri 属性与代理配置相关。
9
有效的签发者 URI。只有签发者发布的访问令牌才会被接受。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME
10
JWKS 端点 URL。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/certs
11
在令牌中包含实际用户名的令牌声明(或密钥)。用户名 是用于 标识用户的主体。该值取决于身份验证流和使用的授权服务器。
12
Kafka 代理的客户端 ID,适用于所有代理。这是在 授权服务器注册为 kafka-broker的客户端
13
Kafka 代理的 secret,在所有代理中都相同。
14
授权服务器的 OAuth 2.0 令牌端点 URL。对于生产环境,始终使用 HTTPs。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token
15
为代理间的通信启用(仅需要)OAuth 2.0 身份验证。
16
(可选)当令牌过期时强制会话到期,并激活 Kafka 重新身份验证机制。如果指定的值小于访问令牌过期的时间,客户端必须在实际令牌到期之前重新进行身份验证。默认情况下,会话不会在访问令牌过期时过期,客户端也不会尝试重新身份验证。

以下示例显示了 TLS 侦听器的最低配置,其中 TLS 用于代理间通信。

示例:OAuth 2.0 身份验证的 TLS 侦听器配置

listeners=REPLICATION://kafka:9091,CLIENT://kafka:9092 1
listener.security.protocol.map=REPLICATION:SSL,CLIENT:SASL_PLAINTEXT 2
listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER
inter.broker.listener.name=REPLICATION
listener.name.replication.ssl.keystore.password=KEYSTORE-PASSWORD 3
listener.name.replication.ssl.truststore.password=TRUSTSTORE-PASSWORD
listener.name.replication.ssl.keystore.type=JKS
listener.name.replication.ssl.truststore.type=JKS
listener.name.replication.ssl.endpoint.identification.algorithm=HTTPS 4
listener.name.replication.ssl.secure.random.implementation=SHA1PRNG 5
listener.name.replication.ssl.keystore.location=PATH-TO-KEYSTORE 6
listener.name.replication.ssl.truststore.location=PATH-TO-TRUSTSTORE 7
listener.name.replication.ssl.client.auth=required 8
listener.name.client.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler
listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
  oauth.valid.issuer.uri="https://AUTH-SERVER-ADDRESS" \
  oauth.jwks.endpoint.uri="https://AUTH-SERVER-ADDRESS/jwks" \
  oauth.username.claim="preferred_username" ; 9

1
在代理间通信和客户端应用需要单独的配置。
2
REPLICATION 侦听器配置为使用 TLS,并将 CLIENT 侦听器配置为通过未加密频道使用 SASL。客户端可以在生产环境中使用加密的频道(SASL_SSL)。
3
ssl. 属性定义 TLS 配置。
4
随机数字生成器实施.如果没有设置,则使用 Java 平台 SDK 默认。
5
主机名验证.如果设置为空字符串,则主机名验证将关闭。如果没有设置,则默认值为 HTTPS,它会强制对服务器证书进行主机名验证。
6
监听器的密钥存储路径。
7
监听器信任存储的路径。
8
指定在建立 TLS 连接时,REPLICATION 侦听器的客户端必须通过客户端证书进行身份验证(用于代理间的连接)。
9
为 OAuth 2.0 配置 CLIENT 侦听器。与授权服务器的连接应使用安全 HTTPS 连接。

以下示例显示了使用 PLAIN 身份验证机制通过 SASL 进行凭证交换的 OAuth 2.0 身份验证的最小配置。使用快速本地令牌验证。

示例:PLAIN 身份验证的最小监听器配置

listeners=CLIENT://0.0.0.0:9092 1
listener.security.protocol.map=CLIENT:SASL_PLAINTEXT 2
listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER,PLAIN 3
sasl.mechanism.inter.broker.protocol=OAUTHBEARER 4
inter.broker.listener.name=CLIENT 5
listener.name.client.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler 6
listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \ 7
  oauth.valid.issuer.uri="http://AUTH_SERVER/auth/realms/REALM" \ 8
  oauth.jwks.endpoint.uri="https://AUTH_SERVER/auth/realms/REALM/protocol/openid-connect/certs" \ 9
  oauth.username.claim="preferred_username"  \ 10
  oauth.client.id="kafka-broker" \ 11
  oauth.client.secret="kafka-secret" \ 12
  oauth.token.endpoint.uri="https://AUTH-SERVER-ADDRESS/token" ; 13
listener.name.client.oauthbearer.sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler 14
listener.name.client.plain.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.plain.JaasServerOauthOverPlainValidatorCallbackHandler 15
listener.name.client.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \ 16
  oauth.valid.issuer.uri="https://AUTH-SERVER-ADDRESS" \ 17
  oauth.jwks.endpoint.uri="https://AUTH-SERVER-ADDRESS/jwks" \ 18
  oauth.username.claim="preferred_username"  \ 19
  oauth.token.endpoint.uri="http://AUTH_SERVER/auth/realms/REALM/protocol/openid-connect/token" ; 20
connections.max.reauth.ms=3600000 21

1
为客户端应用程序配置要连接的监听程序(本例中名为 CLIENT )。系统 hostname 用作公告的主机名,客户端必须解析该主机名才能重新连接。由于这是唯一配置的侦听器,因此它也用于代理间通信。
2
将示例 CLIENT 侦听器配置为通过未加密频道使用 SASL。在生产环境中,客户端应使用加密通道(SASL_SSL)来防止 TCP 连接层被窃听和拦截。
3
启用用于 SASL 和 OAUTHBEARER 的凭据交换的 PLAIN 身份验证机制。OAUTHBEARER 也被指定,因为它是代理间通信所必需的。Kafka 客户端可以选择使用哪一种机制进行连接。

PLAIN 身份验证由所有平台上的所有客户端支持。Kafka 客户端必须启用 PLAIN 机制并设置 usernamepassword。PLAIN 可用于使用 OAuth 访问令牌或 OAuth clientIdsecret (客户端凭证)进行身份验证。该行为还由是否指定 oauth.token.endpoint.uri 进行控制。

如果指定了 oauth.token.endpoint.uri,客户端设置 password 以字符串 $accessToken: 开头,服务器会将密码解析为访问令牌,并将 username 解释为帐户用户名。否则,username 会被解释为 clientIdpassword 作为客户端 secret,代理用于在客户端名称中获取访问令牌。

如果没有指定 oauth.token.endpoint.uripassword 总是被解释为一个访问令牌,username 总是被解释为帐户用户名,它必须与从令牌中提取的主要 id 匹配。这称为 'no-client-credentials' 模式,因为客户端必须始终自行获取访问令牌,且无法使用 clientIdsecret

4
指定 OAUTHBEARER 身份验证机制,用于代理间通信。
5
为 Inter-broker 通讯指定监听程序(本例中名为 CLIENT )。需要此项,以使配置有效。
6
为 OAUTHBEARER 机制配置服务器回调处理程序。
7
使用 OAUTHBEARER 机制配置客户端和代理间通信的身份验证设置。oauth.client.idoauth.client.secretoauth.token.endpoint.uri 属性与代理配置相关。
8
有效的签发者 URI。仅接受来自这个签发者的访问令牌。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME
9
JWKS 端点 URL。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/certs
10
在令牌中包含实际用户名的令牌声明(或密钥)。用户名 标识用户的主体。该值取决于身份验证流和使用的授权服务器。
11
Kafka 代理的客户端 ID,适用于所有代理。这是在 授权服务器注册为 kafka-broker的客户端
12
Kafka 代理的 secret(所有代理相同)。
13
授权服务器的 OAuth 2.0 令牌端点 URL。对于生产环境,始终使用 HTTPS。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token
14
为代理间通信启用 OAuth 2.0 身份验证。
15
配置用于 PLAIN 身份验证的服务器回调处理程序。
16
使用 PLAIN 身份验证配置客户端通信的身份验证设置。

oauth.token.endpoint.uri 是一个可选属性,使用 OAuth 2.0 客户端凭证机制在 PLAIN 上启用 OAuth 2.0

17
有效的签发者 URI。仅接受来自这个签发者的访问令牌。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME
18
JWKS 端点 URL。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/certs
19
在令牌中包含实际用户名的令牌声明(或密钥)。用户名 标识用户的主体。该值取决于身份验证流和使用的授权服务器。
20
授权服务器的 OAuth 2.0 令牌端点 URL。对于生产环境,始终使用 HTTPs。例如 :https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token

PLAIN 机制的其他配置,允许客户端进行身份验证,方法是将 clientIdsecret 传递为 usernamepassword,如第 3 点所述。如果没有指定,客户端只能通过将访问令牌作为 password 参数传递来通过 PLAIN 验证。

21
(可选)当令牌过期时强制会话到期,并激活 Kafka 重新身份验证机制。如果指定的值小于访问令牌过期的时间,客户端必须在实际令牌到期之前重新进行身份验证。默认情况下,会话不会在访问令牌过期时过期,客户端也不会尝试重新身份验证。
4.10.2.3. 快速本地 JWT 令牌验证配置

快速本地 JWT 令牌验证在本地检查 JWT 令牌签名。

本地检查可确保令牌:

  • 通过包含访问令牌的 Bearer 声明值来符合类型
  • 有效(未过期)
  • 具有与 匹配的签发者 validIssuerURI

在配置监听器时,您可以指定 一个有效的签发者 URI,以便拒绝授权服务器未发布的任何令牌。

在快速本地 JWT 令牌验证期间,不需要联系授权服务器。您可以通过指定 OAuth 2.0 授权服务器公开的 JWKs 端点 URI 来 激活快速本地 JWT 令牌验证。端点包含用于验证签名 JWT 令牌的公钥,这些令牌由 Kafka 客户端作为凭据发送。

注意

与授权服务器的所有通信都应通过 HTTPS 执行。

对于 TLS 侦听器,您可以配置证书 信任存储 并指向信任存储文件。

快速本地 JWT 令牌验证的属性示例

listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
  oauth.valid.issuer.uri="https://AUTH-SERVER-ADDRESS" \ 1
  oauth.jwks.endpoint.uri="https://AUTH-SERVER-ADDRESS/jwks" \ 2
  oauth.jwks.refresh.seconds="300" \ 3
  oauth.jwks.refresh.min.pause.seconds="1" \ 4
  oauth.jwks.expiry.seconds="360" \ 5
  oauth.username.claim="preferred_username" \ 6
  oauth.ssl.truststore.location="PATH-TO-TRUSTSTORE-P12-FILE" \ 7
  oauth.ssl.truststore.password="TRUSTSTORE-PASSWORD" \ 8
  oauth.ssl.truststore.type="PKCS12" ; 9

1
有效的签发者 URI。只有签发者发布的访问令牌才会被接受。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME
2
JWKS 端点 URL。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/certs
3
端点刷新之间的 period(默认值 300)。
4
连续尝试刷新 JWKS 公钥之间的最小暂停(以秒为单位)。当遇到未知签名密钥时,将在常规定期计划外调度 JWKS 密钥刷新,并且自上次刷新尝试后至少使用指定的暂停。刷新键遵循指数回退规则,不成功刷新会一直增加暂停,直到达到 oauth.jwks.refresh.seconds。默认值为 1。
5
JWK 证书在过期前被视为有效的持续时间。默认为 360 秒。如果您指定了更长的时间,请考虑允许访问撤销的证书的风险。
6
在令牌中包含实际用户名的令牌声明(或密钥)。用户名 是用于 标识用户的主体。该值取决于身份验证流和使用的授权服务器。
7
TLS 配置中使用的信任存储的位置。
8
用于访问信任存储的密码。
9
PKCS #12 格式的信任存储类型。
4.10.2.4. OAuth 2.0 内省端点配置

使用 OAuth 2.0 内省端点进行令牌验证,将收到的访问令牌视为不透明。Kafka 代理将访问令牌发送到内省端点,该端点使用验证所需的令牌信息进行响应。更重要的是,如果特定访问令牌有效,它将返回最新信息,以及关于令牌何时到期的信息。

要配置基于 OAuth 2.0 内省的验证,您需要指定一个 内省端点 URI,而不是为快速本地 JWT 令牌验证指定的 JWKs 端点 URI。根据授权服务器,您通常必须指定 客户端 ID 和客户端 机密,因为内省端点通常受到保护。

内省端点的属性示例

listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
  oauth.introspection.endpoint.uri="https://AUTH-SERVER-ADDRESS/introspection" \ 1
  oauth.client.id="kafka-broker" \ 2
  oauth.client.secret="kafka-broker-secret" \ 3
  oauth.ssl.truststore.location="PATH-TO-TRUSTSTORE-P12-FILE" \ 4
  oauth.ssl.truststore.password="TRUSTSTORE-PASSWORD" \ 5
  oauth.ssl.truststore.type="PKCS12" \ 6
  oauth.username.claim="preferred_username" ; 7

1
OAuth 2.0 内省端点 URI。例如: https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token/introspect
2
Kafka 代理的客户端 ID。
3
Kafka 代理的 secret。
4
TLS 配置中使用的信任存储的位置。
5
用于访问信任存储的密码。
6
PKCS #12 格式的信任存储类型。
7
在令牌中包含实际用户名的令牌声明(或密钥)。用户名 是用于 标识用户的主体。oauth.username.claim 的值取决于所使用的授权服务器。

4.10.3. Kafka 代理的会话重新身份验证

您可以配置 OAuth 侦听程序,为 Kafka 客户端和 Kafka 代理之间的 OAuth 2.0 会话使用 Kafka 会话 重新身份验证。这种机制强制客户端与代理之间经过身份验证的会话在指定时间段后到期。会话过期时,客户端将通过重复使用现有连接而不是丢弃它来立即启动新会话。

会话重新身份验证默认为禁用。您可以在 server.properties 文件中启用它。为启用了 OAUTHBEARER 或 PLAIN 机制的 TLS 监听程序设置 connections.max.reauth.ms 属性。

您可以为每个监听程序指定会话重新身份验证。例如:

listener.name.client.oauthbearer.connections.max.reauth.ms=3600000

客户端使用的 Kafka 客户端库必须支持会话重新身份验证。

会话重新身份验证可用于 快速本地 JWT内省端点 令牌验证。

客户端重新身份验证

当代理经过身份验证的会话过期时,客户端必须通过向代理发送新的有效访问令牌来重新验证现有会话,而不丢弃连接。

如果令牌验证成功,则利用现有连接启动新的客户端会话。如果客户端无法重新验证,代理会在进一步尝试发送或接收消息时关闭连接。如果在代理中启用了重新身份验证机制,使用 Kafka 客户端库 2.2 或更高版本的 Java 客户端会自动重新验证。

会话重新身份验证也适用于刷新令牌(若使用)。会话过期时,客户端使用刷新令牌刷新访问令牌。然后,客户端使用新的访问令牌重新通过现有连接进行身份验证。

OAUTHBEARER 和 PLAIN 的会话过期

当配置会话重新身份验证时,会话过期适用于 OAUTHBEARER 和 PLAIN 身份验证的不同。

对于 OAUTHBEARER 和 PLAIN,请使用 客户端 ID 和 secret 方法:

  • 代理通过身份验证的会话将在配置 connections.max.reauth.ms 时过期。
  • 如果访问令牌在配置的时间之前过期,会话将更早过期。

对于 PLAIN 使用 长期访问令牌 方法:

  • 代理通过身份验证的会话将在配置 connections.max.reauth.ms 时过期。
  • 如果访问令牌在配置的时间之前过期,则重新身份验证会失败。虽然尝试重新身份验证会话,但 PLAIN 没有刷新令牌的机制。

如果没有 配置 connections.max.reauth.ms,OAUTHBEARER 和 PLAIN 客户端可以无限期地保持连接到代理,而无需重新验证。经过身份验证的会话不以访问令牌到期结尾。但是,在配置授权时需要考虑这一点,例如使用 keycloak 授权或安装自定义授权器。

4.10.4. OAuth 2.0 Kafka 客户端配置

使用以下方法配置了 Kafka 客户端:

  • 与授权服务器进行身份验证以获取有效访问令牌所需的凭证(客户端 ID 和 Secret)
  • 使用授权服务器提供的工具获取的、有效的长期 访问令牌或 刷新令牌

发送到 Kafka 代理的唯一信息是访问令牌。用于与授权服务器进行身份验证的凭证 永远不会 发送到代理。当客户端获取访问令牌时,不需要进一步与授权服务器通信。

最简单的机制是使用客户端 ID 和机密进行身份验证。使用长期访问令牌或长期提供的刷新令牌增加了复杂性,因为对授权服务器工具存在额外的依赖性。

注意

如果您使用长期访问令牌,您可能需要在授权服务器中配置客户端,以增加令牌的最长生命周期。

如果 Kafka 客户端没有直接配置访问令牌,客户端会联系授权服务器在 Kafka 会话启动时交换访问令牌的凭证。Kafka 客户端交换:

  • 客户端 ID 和机密
  • 客户端 ID、刷新令牌和(可选)Secret

4.10.5. OAuth 2.0 客户端身份验证流

在本节中,我们在 Kafka 会话启动过程中解释和视觉化 Kafka 客户端、Kafka 代理和授权服务器之间的通信流。流程取决于客户端和服务器配置。

当 Kafka 客户端将访问令牌作为凭证发送到 Kafka 代理时,需要验证令牌。

根据所使用的授权服务器以及可用的配置选项,您可能更愿意使用:

  • 基于 JWT 签名检查和本地令牌内省的快速本地令牌验证,而不联系授权服务器
  • 授权服务器提供的 OAuth 2.0 内省端点

使用快速本地令牌验证需要授权服务器提供 JWKS 端点以及用于验证令牌签名的公共证书。

另一种选择是在授权服务器上使用 OAuth 2.0 内省端点。每次建立新的 Kafka 代理连接时,代理会将从客户端收到的访问令牌传递给授权服务器,并检查响应以确认令牌是否有效。

还可以为以下项配置 Kafka 客户端凭证:

  • 使用之前生成的长期访问令牌直接进行本地访问
  • 与授权服务器联系以获取要发布的新访问令牌
注意

授权服务器可能只允许使用不透明访问令牌,这意味着无法进行本地令牌验证。

4.10.5.1. 客户端身份验证流示例

您可以在 Kafka 会话验证过程中看到用于不同配置的 Kafka 客户端和代理的通信流。

使用客户端 ID 和 secret 的客户端,代理将验证委派给授权服务器

Client using client ID and secret with broker delegating validation to authorization server

  1. Kafka 客户端使用客户端 ID 和机密从授权服务器请求访问令牌,以及可选的刷新令牌。
  2. 授权服务器生成新的访问令牌。
  3. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证来传递访问令牌。
  4. Kafka 代理使用自己的客户端 ID 和 secret,在授权服务器上调用令牌内省端点来验证访问令牌。
  5. 如果令牌有效,则创建 Kafka 客户端会话。

使用客户端 ID 和 secret 的客户端,代理执行快速本地令牌验证

Client using client ID and secret with broker performing fast local token validation

  1. Kafka 客户端从令牌端点通过授权服务器进行身份验证,使用客户端 ID 和 secret 以及可选的刷新令牌进行身份验证。
  2. 授权服务器生成新的访问令牌。
  3. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证来传递访问令牌。
  4. Kafka 代理使用 JWT 令牌签名检查和本地令牌内省在本地验证访问令牌。

使用长期访问令牌的客户端,并将代理委派验证到授权服务器

Client using long-lived access token with broker delegating validation to authorization server

  1. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证,以传递长期访问令牌。
  2. Kafka 代理使用自己的客户端 ID 和 secret,在授权服务器上调用令牌内省端点来验证访问令牌。
  3. 如果令牌有效,则创建 Kafka 客户端会话。

使用长期访问令牌的客户端,代理执行快速本地验证

Client using long-lived access token with broker performing fast local validation

  1. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证,以传递长期访问令牌。
  2. Kafka 代理使用 JWT 令牌签名检查和本地令牌内省在本地验证访问令牌。
警告

快速本地 JWT 令牌签名验证仅适用于短期的令牌,因为如果令牌被撤销,则不会与授权服务器检查。令牌到期将写入令牌中,但取消可以在任何时间发生,因此在不联系授权服务器的情况下无法考虑该令牌。任何发布的令牌都将被视为有效,直到该令牌过期为止。

4.10.6. 配置 OAuth 2.0 身份验证

OAuth 2.0 用于 Kafka 客户端和 AMQ Streams 组件之间的交互。

要将 OAuth 2.0 用于 AMQ Streams,您必须:

4.10.6.1. 将红帽单点登录配置为 OAuth 2.0 授权服务器

这个步骤描述了如何将 Red Hat Single Sign-On 部署为授权服务器,并将其配置为与 AMQ Streams 集成。

授权服务器为身份验证和授权以及用户、客户端和权限的管理提供中央点。红帽单点登录有一个域概念,其中 代表一组单独的用户、客户端、权限和其他配置。您可以使用默认的 master 域,或者创建一个新域。每个域公开自己的 OAuth 2.0 端点,这意味着应用客户端和应用服务器都需要使用相同的域。

要将 OAuth 2.0 与 AMQ Streams 搭配使用,您需要部署授权服务器才能创建和管理身份验证域。

注意

如果您已经部署了红帽单点登录,您可以跳过部署步骤并使用当前的部署。

开始前

您需要熟悉使用红帽单点登录。

有关安装和管理说明,请参阅:

先决条件

  • AMQ Streams 和 Kafka 正在运行

对于 Red Hat Single Sign-On 部署:

流程

  1. 安装红帽单点登录.

    您可以从 ZIP 文件或使用 RPM 安装。

  2. 登录红帽单点登录管理控制台,为 AMQ Streams 创建 OAuth 2.0 策略。

    部署 Red Hat Single Sign-On 时会提供登录详情。

  3. 创建和启用域。

    您可以使用现有的 master 域。

  4. 如果需要,调整域的会话和令牌超时。
  5. 创建名为 kafka-broker 的客户端。
  6. Settings 选项卡中设置:

    • 访问类型Confidential
    • 标准流启用OFF,以禁用此客户端的 Web 登录
    • 支持 ON 的服务帐户以允许这个客户端使用自己的名称进行身份验证
  7. 单击 Save,然后再继续。
  8. Credentials 选项卡中,记下 AMQ Streams Kafka 集群配置中使用的 secret。
  9. 为要连接到 Kafka 代理的任何应用程序客户端重复客户端创建步骤。

    为每个新客户端创建定义。

    在配置中,您将使用名称作为客户端 ID。

接下来要做什么

部署和配置授权服务器后,将 Kafka 代理配置为使用 OAuth 2.0

4.10.6.2. 配置 Kafka 代理的 OAuth 2.0 支持

这个步骤描述了如何配置 Kafka 代理,以便代理监听程序被启用为使用授权服务器使用 OAuth 2.0 身份验证。

我们建议通过配置 TLS 侦听器在加密接口上使用 OAuth 2.0。不建议纯监听器。

使用支持所选授权服务器的属性以及您要实施的授权类型来配置 Kafka 代理。

开始前

有关 Kafka 代理监听程序的配置和身份验证的更多信息,请参阅:

有关监听程序配置中使用的属性的描述,请参阅:

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 部署了 OAuth 2.0 授权服务器

流程

  1. server.properties 文件中配置 Kafka 代理监听程序配置。

    例如,使用 OAUTHBEARER 机制:

    sasl.enabled.mechanisms=OAUTHBEARER
    listeners=CLIENT://0.0.0.0:9092
    listener.security.protocol.map=CLIENT:SASL_PLAINTEXT
    listener.name.client.sasl.enabled.mechanisms=OAUTHBEARER
    sasl.mechanism.inter.broker.protocol=OAUTHBEARER
    inter.broker.listener.name=CLIENT
    listener.name.client.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler
    listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required ;
    listener.name.client.oauthbearer.sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
  2. 将代理连接设置配置为 listener.name.client.oauthbearer.sasl.jaas.config 的一部分。

    此处的示例演示了连接配置选项。

    示例 1:使用 JWKS 端点配置进行本地令牌验证

    listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.valid.issuer.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME" \
      oauth.jwks.endpoint.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/certs" \
      oauth.jwks.refresh.seconds="300" \
      oauth.jwks.refresh.min.pause.seconds="1" \
      oauth.jwks.expiry.seconds="360" \
      oauth.username.claim="preferred_username" \
      oauth.ssl.truststore.location="PATH-TO-TRUSTSTORE-P12-FILE" \
      oauth.ssl.truststore.password="TRUSTSTORE-PASSWORD" \
      oauth.ssl.truststore.type="PKCS12" ;
    listener.name.client.oauthbearer.connections.max.reauth.ms=3600000

    示例 2:通过 OAuth 2.0 内省端点将令牌验证委派给授权服务器

    listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.introspection.endpoint.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/introspection" \
      # ...

  3. 如果需要,配置对授权服务器的访问权限。

    生产环境通常需要这一步,除非使用 服务网格 等技术在容器外部配置安全频道。

    1. 提供用于连接到安全授权服务器的自定义信任存储。访问授权服务器时始终需要 SSL。

      设置属性以配置信任存储。

      例如:

      listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        # ...
        oauth.client.id="kafka-broker" \
        oauth.client.secret="kafka-broker-secret" \
        oauth.ssl.truststore.location="PATH-TO-TRUSTSTORE-P12-FILE" \
        oauth.ssl.truststore.password="TRUSTSTORE-PASSWORD" \
        oauth.ssl.truststore.type="PKCS12" ;
    2. 如果证书主机名与访问 URL 主机名不匹配,您可以关闭证书主机名验证:

      oauth.ssl.endpoint.identification.algorithm=""

      检查可确保客户端与授权服务器的连接是身份验证的。您可能需要在非生产环境中关闭验证。

  4. 根据您选择的身份验证流配置其他属性。

    listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      # ...
      oauth.token.endpoint.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token" \ 1
      oauth.custom.claim.check="@.custom == 'custom-value'" \ 2
      oauth.scope="SCOPE" \ 3
      oauth.check.audience="true" \ 4
      oauth.audience="AUDIENCE" \ 5
      oauth.valid.issuer.uri="https://https://AUTH-SERVER-ADDRESS/auth/REALM-NAME" \ 6
      oauth.client.id="kafka-broker" \ 7
      oauth.client.secret="kafka-broker-secret" \ 8
      oauth.refresh.token="REFRESH-TOKEN-FOR-KAFKA-BROKERS" \ 9
      oauth.access.token="ACCESS-TOKEN-FOR-KAFKA-BROKERS" ; 10
    1
    授权服务器的 OAuth 2.0 令牌端点 URL。对于生产环境,始终使用 HTTPs。使用 KeycloakRBACAuthorizer 时需要,或使用 OAuth 2.0 启用的监听程序进行内部通信。
    2
    (可选) 自定义声明检查.在验证期间对 JWT 访问令牌应用其他自定义规则的 JsonPath 过滤器查询。如果访问令牌不包含必要的数据,则会被拒绝。使用 内省 端点方法时,自定义检查将应用到内省端点响应 JSON。
    3
    (可选)传递给令牌端点的 scope 参数。在获取用于代理身份验证的访问令牌时,会使用 范围。它还在 OAuth 2.0 的客户端名称中使用 clientIdsecret 进行 PLAIN 客户端身份验证。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响侦听器的令牌验证规则。
    4
    (可选) 正确检查。如果您的授权服务器提供 aud (严重)声明,并且您希望强制进行使用者检查,请将 ouath.check.audience 设置为 true。使用者检查可识别令牌的预期接收者。因此,Kafka 代理将拒绝在其 aud 声明中没有其 clientId 的令牌。默认值为 false
    5
    (可选)传递给令牌端点的 audience 参数。在获取用于代理身份验证的访问令牌时,会使用 使用者。它还在 OAuth 2.0 的客户端名称中使用 clientIdsecret 进行 PLAIN 客户端身份验证。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响侦听器的令牌验证规则。
    6
    有效的签发者 URI。只有签发者发布的访问令牌才会被接受。(始终需要.)
    7
    Kafka 代理配置的客户端 ID,在所有代理中都相同。这是在 授权服务器注册为 kafka-broker的客户端。使用内省端点进行令牌验证或使用 KeycloakRBACAuthorizer 时需要此项。
    8
    为 Kafka 代理配置 secret,在所有代理中都相同。当代理必须与授权服务器进行身份验证时,必须指定客户端 secret、访问令牌或刷新令牌。
    9
    (可选) Kafka 代理的长期刷新令牌。
    10
    (可选) Kafka 代理的长期访问令牌。
  5. 根据您应用 OAuth 2.0 身份验证的方式,以及所使用的授权服务器类型,添加额外的配置设置:

    listener.name.client.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      # ...
      oauth.check.issuer=false \ 1
      oauth.fallback.username.claim="CLIENT-ID" \ 2
      oauth.fallback.username.prefix="CLIENT-ACCOUNT" \ 3
      oauth.valid.token.type="bearer" \ 4
      oauth.userinfo.endpoint.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/userinfo" ; 5
    1
    如果您的授权服务器不提供 iss 声明,则无法执行签发者检查。在这种情况下,将 oauth.check.issuer 设置为 false,且不要指定 oauth.valid.issuer.uri。默认值为 true
    2
    授权服务器不能提供单个属性来标识常规用户和客户端。当客户端在其自己的名称中进行身份验证时,服务器可能会提供 客户端 ID。当用户使用用户名和密码进行身份验证时,为了获取刷新令牌或访问令牌,服务器可能会提供除客户端 ID 之外 的用户名 属性。使用此回退选项指定用户名声明(attribute),以便在主用户 ID 属性不可用时使用。
    3
    在适用 oauth.fallback.username.claim 的情况下,可能还需要防止名称在用户名声明的值和回退用户名声明的值之间发生冲突。请考虑存在名为 producer 的客户端,但还有一个名为 producer 的普通用户。为了区分这两者,您可以使用此属性向客户端的用户 ID 添加前缀。
    4
    (仅在使用 oauth.introspection.endpoint.uri时)取决于您使用的授权服务器,内省端点可能会也可能不会返回 令牌类型 属性,或者它可能包含不同的值。您可以指定内省端点必须包含的有效令牌类型值。
    5
    (仅在使用 oauth.introspection.endpoint.uri时适用)可以配置或实施授权服务器,以避免在内省端点响应中提供任何可识别的信息。要获取用户 ID,您可以将 userinfo 端点的 URI 配置为回退。oauth.fallback.username.claimoauth.fallback.username.claimoauth.fallback.username.prefix 设置应用于 userinfo 端点的响应。
4.10.6.3. 将 Kafka Java 客户端配置为使用 OAuth 2.0

这个步骤描述了如何配置 Kafka 制作者和使用者 API,以使用 OAuth 2.0 与 Kafka 代理交互。

将客户端回调插件添加到 pom.xml 文件,并配置系统属性。

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 为对 Kafka 代理的 OAuth 访问部署并配置了 OAuth 授权服务器
  • 为 OAuth 2.0 配置 Kafka 代理

流程

  1. 在 Kafka 客户端的 pom.xml 文件中添加带有 OAuth 2.0 支持的客户端库:

    <dependency>
     <groupId>io.strimzi</groupId>
     <artifactId>kafka-oauth-client</artifactId>
     <version>0.8.1.redhat-00004</version>
    </dependency>
  2. 为回调配置系统属性:

    例如:

    System.setProperty(ClientConfig.OAUTH_TOKEN_ENDPOINT_URI, “https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token”); 1
    System.setProperty(ClientConfig.OAUTH_CLIENT_ID, "CLIENT-NAME"); 2
    System.setProperty(ClientConfig.OAUTH_CLIENT_SECRET, "CLIENT_SECRET"); 3
    System.setProperty(ClientConfig.OAUTH_SCOPE, "SCOPE-VALUE") 4
    1
    授权服务器令牌端点的 URI。
    2
    客户端 ID,这是在授权服务器中创建 客户端 时使用的名称。
    3
    在授权服务器中创建 客户端 时创建的客户端机密。
    4
    (可选) scope 用于从令牌端点请求令牌。授权服务器可能需要客户端指定范围。
  3. 在 Kafka 客户端配置中的 TLS 加密连接上启用 OAUTHBEARER OR PLAIN 机制。

    例如:

    为 Kafka 客户端启用 OAUTHBEARER

    props.put("sasl.jaas.config", "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;");
    props.put("security.protocol", "SASL_SSL");
    props.put("sasl.mechanism", "OAUTHBEARER");
    props.put("sasl.login.callback.handler.class", "io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler");

    为 Kafka 客户端启用 PLAIN

    props.put("sasl.jaas.config", "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"$CLIENT_ID_OR_ACCOUNT_NAME\" password=\"$SECRET_OR_ACCESS_TOKEN\" ;");
    props.put("security.protocol", "SASL_SSL"); 1
    props.put("sasl.mechanism", "PLAIN");

    1
    在这里,我们使用 SASL_SSL 通过 TLS 连接使用。在未加密连接中使用 SASL_PLAINTEXT 只用于本地开发。
  4. 验证 Kafka 客户端可以访问 Kafka 代理。

4.11. 使用基于 OAuth 2.0 令牌的授权

如果您在 Red Hat Single Sign-On 中使用 OAuth 2.0 进行基于令牌的身份验证,您还可以使用 Red Hat Single Sign-On 配置授权规则来限制客户端对 Kafka 代理的访问。身份验证建立用户的身份。授权决定该用户的访问级别。

AMQ Streams 支持通过 Red Hat Single Sign-On Authorization Services 使用基于 OAuth 2.0 令牌的授权,它允许您集中管理安全策略和权限。

Red Hat Single Sign-On 中定义的安全策略和权限用于授予对 Kafka 代理上资源的访问权限。用户和客户端与允许对 Kafka 代理执行特定操作的策略进行匹配。

默认情况下,Kafka 允许所有用户对代理进行完全访问,还提供 AclAuthorizer 插件根据访问控制列表(ACL)配置授权。

zookeeper 存储允许或拒绝基于 用户名 访问资源的 ACL 规则。但是,使用红帽单点登录的 OAuth 2.0 基于令牌的授权为您要对 Kafka 代理实施访问控制提供了极大的灵活性。另外,您可以将 Kafka 代理配置为使用 OAuth 2.0 授权和 ACL。

4.11.1. OAuth 2.0 授权机制

AMQ Streams 中的 OAuth 2.0 授权使用 Red Hat Single Sign-On 服务器授权服务 REST 端点通过对特定用户应用定义的安全策略,并为该用户提供不同资源获得的权限列表,从而通过红帽单点登录来扩展基于令牌的身份验证。策略使用角色和组来匹配用户的权限。OAuth 2.0 授权根据红帽单点登录授权服务中用户收到的授权列表,在本地强制实施权限。

4.11.1.1. Kafka 代理自定义授权器

Red Hat Single Sign-On 授权程序( KeycloakRBACAuthorizer)由 AMQ Streams 提供。为了能够将 Red Hat Single Sign-On REST 端点用于 Red Hat Single Sign-On 提供的授权服务,您可以在 Kafka 代理上配置自定义授权程序。

授权者根据需要从授权服务器获取授予权限的列表,并在 Kafka Broker 上强制本地实施授权,从而对每个客户端请求做出快速的授权决策。

4.11.2. 配置 OAuth 2.0 授权支持

这个步骤描述了如何使用 Red Hat Single Sign-On Authorization Services 将 Kafka 代理配置为使用 OAuth 2.0 授权服务。

开始前

考虑您需要或希望限制某些用户的访问权限。您可以使用红帽单点登录 角色客户端 和用户 组合在红帽单点登录中配置访问权限。

通常,组用于根据组织部门或地理位置匹配用户。和 角色用于根据用户的功能匹配用户。

通过红帽单点登录,您可以将用户和组存储在 LDAP 中,而客户端和角色则无法以这种方式存储。存储和用户数据访问可能是您选择配置授权策略的一个因素。

注意

无论 Kafka 代理中实施的授权如何,超级用户 始终都对 Kafka 代理具有未经约束的访问权限。

先决条件

  • AMQ Streams 必须配置为使用 OAuth 2.0 和 Red Hat Single Sign-On 基于 令牌的身份验证。设置授权时,您可以使用相同的 Red Hat Single Sign-On 服务器端点。
  • 您需要了解如何管理红帽单点登录授权服务的策略和权限,如红帽 单点登录文档 中所述。

流程

  1. 访问 Red Hat Single Sign-On Admin 控制台,或使用 Red Hat Single Sign-On Admin CLI 为您在设置 OAuth 2.0 身份验证时创建的 Kafka 代理客户端启用授权服务。
  2. 使用授权服务为客户端定义资源、授权范围、策略和权限。
  3. 通过为用户和组分配角色和组,将权限绑定至用户和组。
  4. 将 Kafka 代理配置为使用 Red Hat Single Sign-On 授权。

    在 Kafka server.properties 配置文件中添加以下内容以在 Kafka 中安装授权器:

    authorizer.class.name=io.strimzi.kafka.oauth.server.authorizer.KeycloakRBACAuthorizer
    principal.builder.class=io.strimzi.kafka.oauth.server.authorizer.JwtKafkaPrincipalBuilder
  5. 添加 Kafka 代理的配置,以访问授权服务器和授权服务。

    在此,我们演示了添加为 server.properties 附加属性的示例配置,但也可以使用大写或大写命名惯例将其定义为环境变量。

    strimzi.authorization.token.endpoint.uri="https://AUTH-SERVER-ADDRESS/auth/realms/REALM-NAME/protocol/openid-connect/token" 1
    strimzi.authorization.client.id="kafka" 2
    1
    红帽单点登录的 OAuth 2.0 令牌端点 URL。对于生产环境,始终使用 HTTPs。
    2
    启用了授权服务的 Red Hat Single Sign-On 中的 OAuth 2.0 客户端定义的客户端 ID。通常,kafka 用作 ID。
  6. (可选)添加特定 Kafka 集群的配置。

    例如:

    strimzi.authorization.kafka.cluster.name="kafka-cluster" 1
    1
    特定 Kafka 集群的名称。名称用于目标权限,从而能够管理同一红帽单点登录域中的多个集群。默认值为 kafka-cluster
  7. (可选)提交到简单授权。

    例如:

    strimzi.authorization.delegate.to.kafka.acl="false" 1
    1
    如果 Red Hat Single Sign-On Authorization Services 策略拒绝访问,请将访问权限委派给 Kafka AclAuthorizer。默认值为 false
  8. (可选)添加 TLS 连接到授权服务器的配置。

    例如:

    strimzi.authorization.ssl.truststore.location=<path-to-truststore> 1
    strimzi.authorization.ssl.truststore.password=<my-truststore-password> 2
    strimzi.authorization.ssl.truststore.type=JKS 3
    strimzi.authorization.ssl.secure.random.implementation=SHA1PRNG 4
    strimzi.authorization.ssl.endpoint.identification.algorithm=HTTPS 5
    1
    包含证书的信任存储的路径。
    2
    信任存储的密码。
    3
    truststore 类型。如果没有设置,则使用默认的 Java 密钥存储类型。
    4
    随机数字生成器实施.如果没有设置,则使用 Java 平台 SDK 默认。
    5
    主机名验证.如果设置为空字符串,则主机名验证将关闭。如果没有设置,则默认值为 HTTPS,它会强制对服务器证书进行主机名验证。
  9. (可选)从授权服务器配置 授权刷新。通过枚举活动令牌并请求每个帐户的最新授权来授予刷新作业。

    例如:

    strimzi.authorization.grants.refresh.period.seconds="120" 1
    strimzi.authorization.grants.refresh.pool.size="10" 2
    1
    指定授权服务器授权列表刷新的频率(默认为每分钟刷新一次)。要为调试目的关闭刷新,请将 设为 "0"
    2
    指定授权刷新作业使用的线程池的大小(并行程度)。默认值为 "5"
  10. 以具有特定角色的客户端或用户访问 Kafka 代理,确保他们具有必要的访问权限,或者没有他们应该拥有的访问权限,来验证配置的权限。

4.12. 使用基于 OPA 策略的授权

开源策略代理(OPA)是一个开源策略引擎。您可以将 OPA 与 AMQ Streams 集成,作为基于策略的授权机制,允许在 Kafka 代理上进行客户端操作。

从客户端发出请求时,OPA 将根据为 Kafka 访问定义的策略评估请求,然后允许或拒绝请求。

注意

红帽不支持 OPA 服务器。

4.12.1. 定义 OPA 策略

在将 OPA 与 AMQ Streams 集成之前,请考虑如何定义策略以提供精细访问控制。

您可以为 Kafka 集群、消费者组和主题定义访问控制。例如,您可以定义一个授权策略,允许从制作者客户端写入到特定代理主题的访问。

因此,策略可能会指定:

  • 与制作者客户端关联的 用户主体 和主机地址
  • 客户端允许 的操作
  • 策略应用到的资源类型 (topic)和资源类型 名称

允许和拒绝决策写入策略中,并根据提供的请求和客户端识别数据提供响应。

在我们的示例中,制作者客户必须满足该策略才能写入该主题。

4.12.2. 连接到 OPA

要启用 Kafka 访问 OPA 策略引擎以查询访问控制策略,您需要在 Kafka server.properties 文件中配置自定义 OPA 授权器插件(kafka-authorizer-opa-VERSION.jar)。

当客户端发出请求时,插件使用指定的 URL 地址和 REST 端点(必须是定义的策略的名称)查询 OPA 策略引擎。

插件以 JSON 格式提供客户端请求(用户主体、操作和资源)的详细信息,以 JSON 格式根据策略检查。详细信息将包括客户端的唯一身份;例如,如果使用 TLS 身份验证,则使用与客户端证书的区分名称。

OPA 使用数据向插件提供响应( truefalse )来允许或拒绝请求。

4.12.3. 配置 OPA 授权支持

这个步骤描述了如何将 Kafka 代理配置为使用 OPA 授权。

开始前

考虑您需要或希望限制某些用户的访问权限。您可以使用 用户和 Kafka 资源 组合来定义 OPA 策略。

可以设置 OPA 以从 LDAP 数据源加载用户信息。

注意

无论 Kafka 代理中实施的授权如何,超级用户 始终都对 Kafka 代理具有未经约束的访问权限。

先决条件

流程

  1. 编写授权客户端请求对 Kafka 代理执行操作所需的 OPA 策略。

    请参阅 定义 OPA 策略

    现在,将 Kafka 代理配置为使用 OPA。

  2. 为 Kafka 安装 OPA 授权器插件

    请参阅 连接到 OPA

    确保 plugin 文件包含在 Kafka 类路径中。

  3. 在 Kafka server.properties 配置文件中添加以下内容以启用 OPA 插件:

    authorizer.class.name: com.bisnode.kafka.authorization.OpaAuthorizer
  4. 为 Kafka 代理 server.properties 添加更多配置,以访问 OPA 策略引擎和策略。

    例如:

    opa.authorizer.url=https://OPA-ADDRESS/allow 1
    opa.authorizer.allow.on.error=false 2
    opa.authorizer.cache.initial.capacity=50000 3
    opa.authorizer.cache.maximum.size=50000 4
    opa.authorizer.cache.expire.after.seconds=600000 5
    super.users=User:alice;User:bob 6
    1
    (必需)授权者将查询的策略的 OAuth 2.0 令牌端点 URL。在本例中,策略名为 allow
    2
    如果授权者插件无法与 OPA 策略引擎连接,则指定是否允许或拒绝客户端访问。
    3
    以本地缓存字节为单位的初始容量。使用缓存,以便插件不必为每个请求查询 OPA 策略引擎。
    4
    本地缓存的最大容量(以字节为单位)。
    5
    从 OPA 策略引擎重新加载,以毫秒为单位刷新本地缓存的时间。
    6
    被视为超级用户的用户主体列表,以便始终允许用户无需查询 Open Policy Agent 策略。

    有关身份验证和授权选项的信息,请参阅 Open Policy Agent 网站

  5. 使用具有且没有正确授权的客户端访问 Kafka 代理来验证配置的权限。

4.13. 日志

Kafka 代理使用 Log4j 作为日志记录基础架构。默认情况下,日志配置是从 log4j.properties 配置文件读取的,该文件应该放在 /opt/kafka/config/ 目录中或类路径中。配置文件的位置和名称可使用 Java 属性 log4j.configuration 更改,该属性可使用 KAFKA_LOG4J_OPTS 环境变量传递给 Kafka:

su - kafka
export KAFKA_LOG4J_OPTS="-Dlog4j.configuration=file:/my/path/to/log4j.config"; /opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties

有关 Log4j 配置的更多信息,请参阅 Log4j 手册

4.13.1. 动态更改 Kafka 代理日志记录器的日志记录级别

Kafka 代理日志记录由每个 代理中的多个代理日志记录器 提供。您可以动态更改代理日志记录器的日志记录级别,而无需重启代理。通过将 INFO 改为 DEBUG 来提高 logs 中返回的详细信息级别,例如 -​ 可用于调查 Kafka 集群中的性能问题。

代理日志记录器也可以动态重置为默认的日志记录级别。

流程

  1. 切换到 kafka 用户:

    su - kafka
  2. 使用 kafka-configs.sh 工具列出代理的所有代理日志记录器:

    /opt/kafka/bin/kafka-configs.sh --bootstrap-server BOOTSTRAP-ADDRESS --describe --entity-type broker-loggers --entity-name BROKER-ID

    例如,对于代理 0

    /opt/kafka/bin/kafka-configs.sh --bootstrap-server localhost:9092 --describe --entity-type broker-loggers --entity-name 0

    这会为每个日志记录器返回日志级别: TRACEDEBUGINFOWARNERRORFATAL。例如:

    #...
    kafka.controller.ControllerChannelManager=INFO sensitive=false synonyms={}
    kafka.log.TimeIndex=INFO sensitive=false synonyms={}
  3. 更改一个或多个代理日志记录器的日志记录级别。使用 --alter--add-config 选项,使用双引号以逗号分隔列表的形式指定每个日志记录器及其级别。

    /opt/kafka/bin/kafka-configs.sh --bootstrap-server BOOTSTRAP-ADDRESS --alter --add-config "LOGGER-ONE=NEW-LEVEL,LOGGER-TWO=NEW-LEVEL" --entity-type broker-loggers --entity-name BROKER-ID

    例如,对于代理 0

    /opt/kafka/bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --add-config "kafka.controller.ControllerChannelManager=WARN,kafka.log.TimeIndex=WARN" --entity-type broker-loggers --entity-name 0

    如果成功,则返回:

    Completed updating config for broker: 0.
重置代理日志记录器

您可以使用 kafka-configs.sh 工具将一个或多个代理日志记录器重置为默认日志记录级别。使用 --alter--delete-config 选项,并使用双引号将每个代理日志记录器指定为用逗号分开的列表:

/opt/kafka/bin/kafka-configs.sh --bootstrap-server localhost:9092 --alter --delete-config "LOGGER-ONE,LOGGER-TWO" --entity-type broker-loggers --entity-name BROKER-ID

第 5 章 主题

Kafka 中的消息始终发送到或从某个主题接收。本章论述了如何配置和管理 Kafka 主题。

5.1. 分区和副本

Kafka 中的消息始终发送到或从某个主题接收。主题始终分为一个或多个分区。分区充当分片。这意味着生产者发送的每一消息始终仅写入单个分区。由于将消息分片到不同的分区中,主题可以轻松横向扩展。

每个分区都可以有一个或多个副本,这些副本将存储在集群中的不同代理中。在创建主题时,您可以使用 复制因素 配置副本数量。复制因素 定义集群中将要保存的副本数。给定分区的一个副本将被选为领导。领导副本供制作者用于发送新消息,使用者则使用消息。其他副本将是后续副本。追随者复制领导者。

如果领导机失败,其中一个追随者将自动成为新的领导。每个服务器充当其部分分区的领导,并充当其他分区的追随者,以便在群集内平衡负载。

注意

复制因素决定了副本数量,包括领导机和追随者。例如,如果您将复制因素设置为 3,则会有一个领导机和两个后续副本。

5.2. 消息保留

消息保留策略定义消息存储在 Kafka 代理中的时长。它可根据时间、分区大小或两者定义。

例如,您可以定义应保留信息:

  • 7 天
  • 直到 parition 有 1GB 的消息。达到限制后,将删除最旧的消息。
  • 持续 7 天,或者直到达到 1GB 限制为止。将首先使用任何限制。
警告

Kafka 代理将信息存储在日志片段中。只有在创建新日志分段时,才会删除超过其保留策略的消息。当上一个日志片段超过配置的日志片段大小时,会创建新的日志片段。此外,用户可以要求定期创建新的片段。

另外,Kafka 代理支持紧凑策略。

对于包含紧凑策略的主题,代理始终只保留每个密钥的最后一条消息。使用相同密钥的旧消息将从分区中删除。由于压缩是一种定期执行的操作,因此当具有相同密钥的新消息被发送到分区时,它不会立即发生。相反,可能需要稍等片刻后,旧消息才会被删除。

有关消息保留配置选项的详情请参考 第 5.5 节 “主题配置”

5.3. 主题自动创建

当制作者或消费者尝试向不存在的主题发送或接收消息时,Kafka 默认会自动创建该主题。这个行为由 auto.create.topics.enable 配置属性控制,该属性默认设置为 true

要禁用它,在 Kafka 代理配置文件中将 auto.create.topics.enable 设置为 false

auto.create.topics.enable=false

5.4. 主题删除

Kafka 可以禁用主题删除。这通过 delete.topic.enable 属性进行配置,该属性默认设置为 true (也就是说,可以删除主题)。当此属性设置为 false 时,将无法删除主题,所有删除主题的尝试都会返回成功,但不会删除该主题。

delete.topic.enable=false

5.5. 主题配置

自动创建的主题将使用默认的主题配置,可以在代理属性文件中指定。但是,在手动创建主题时,可以在创建时指定它们的配置。也可以在主题创建后更改其配置。手动创建主题的主要配置选项为:

cleanup.policy
将保留策略配置为 deletecompactdelete 策略将删除旧记录。compact 策略将启用日志紧凑。默认值为 delete。有关日志紧凑的更多信息,请参阅 Kafka 网站
compression.type
指定用于存储信息的压缩。有效值为 gzipsnappylz4uncompressed (无压缩)和 producer (恢复由制作者使用的压缩解码器)。默认值为 producer
max.message.bytes
Kafka 代理允许的批量消息的最大大小,以字节为单位。默认值为 1000012
min.insync.replicas
若要将写入视为成功,必须同步最少的副本数。默认值为 1
retention.ms
保存日志片段的最大毫秒数。大于此值的日志片段将被删除。默认值为 604800000 (7 天)。
retention.bytes
分区将保留的最大字节数。当分区大小超过这个限制时,将删除最旧的日志片段。-1 的值表示没有限制。默认值为 -1
segment.bytes
单个提交日志文件段文件的最大文件大小(以字节为单位)。当网段达到其大小时,将启动一个新网段。默认值为 1073741824 字节(1 千兆字节)。

有关所有支持的主题配置选项列表,请参考 附录 B, 主题配置参数

可以使用类似的选项在 Kafka 代理配置中指定自动创建的主题的默认值:

log.cleanup.policy
请参阅上面的 cleanup.policy
compression.type
请参阅上面的 compression.type
message.max.bytes
请参阅上面的 max.message.bytes
min.insync.replicas
请参阅上面的 min.insync.replicas
log.retention.ms
请参阅上面的 retention.ms
log.retention.bytes
请参阅上面的 retention.bytes
log.segment.bytes
请参阅上面的 segment.bytes
default.replication.factor
自动创建主题的默认复制因素。默认值为 1
num.partitions
自动创建主题的默认分区数。默认值为 1

有关所有支持的 Kafka 代理配置选项列表,请参阅 附录 A, 代理配置参数

5.6. 内部主题

内部主题由 Kafka 代理和客户端在内部创建和使用。Kafka 有几个内部主题。它们用于存储消费者偏移(__consumer_offsets)或交易状态(__transaction_state)。可以使用专用的 Kafka 代理配置选项配置这些主题,选项以前缀 offsets.topic.transaction.state.log. 开头。最重要的配置选项是:

offsets.topic.replication.factor
__consumer_offsets 主题的副本数。默认值为 3
offsets.topic.num.partitions
__consumer_offsets 主题的分区数量。默认值为 50
transaction.state.log.replication.factor
__transaction_state 主题的副本数。默认值为 3
transaction.state.log.num.partitions
__transaction_state 主题的分区数量。默认值为 50
transaction.state.log.min.isr
必须确认写入 __transaction_state 主题的最小副本数才能被视为成功。如果无法满足此最小值,则制作者将失败,但有一个例外。默认值为 2

5.7. 创建主题

kafka-topics.sh 工具可用于管理主题。kafka-topics.sh 是 AMQ Streams 发布的一部分,可以在 bin 目录中找到。

先决条件

  • AMQ Streams 集群已安装并运行

创建主题

  1. 使用 kafka-topics.sh 实用程序创建主题并指定以下内容:

    • --bootstrap-server 选项中 Kafka 代理的主机和端口。
    • 要在 --create 选项中创建的新主题。
    • --topic 选项中的主题名称。
    • --partitions 选项中的分区数量。
    • --replication-factor 选项中的主题复制因素。

      您还可以使用 --config 选项覆盖某些默认主题配置选项。这个选项可以多次用于覆盖不同的选项。

      bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --create --topic <TopicName> --partitions <NumberOfPartitions> --replication-factor <ReplicationFactor> --config <Option1>=<Value1> --config <Option2>=<Value2>

      创建名为 的主题的命令示例 mytopic

      bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic mytopic --partitions 50 --replication-factor 3 --config cleanup.policy=compact --config min.insync.replicas=2

  2. 使用 kafka-topics.sh 验证主题是否存在。

    bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --describe --topic <TopicName>

    描述名为 的主题的命令示例 mytopic

    bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic mytopic

其它资源

5.8. 列出并描述主题

kafka-topics.sh 工具可用于列出和描述主题。kafka-topics.sh 是 AMQ Streams 发布的一部分,可以在 bin 目录中找到。

先决条件

  • AMQ Streams 集群已安装并运行
  • 主题 mytopic 存在

描述主题

  1. 使用 kafka-topics.sh 工具描述一个主题并指定以下内容:

    • --bootstrap-server 选项中 Kafka 代理的主机和端口。
    • 使用 --describe 选项指定您要描述的主题。
    • 主题名称必须在 --topic 选项中指定。
    • 当省略 --topic 选项时,它将描述所有可用的主题。

      bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --describe --topic <TopicName>

      描述名为 的主题的命令示例 mytopic

      bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic mytopic

      describe 命令将列出属于此主题的所有分区和副本。它还会列出所有主题配置选项。

其它资源

5.9. 修改主题配置

kafka-configs.sh 工具可用于修改主题配置。kafka-configs.sh 是 AMQ Streams 发布的一部分,可以在 bin 目录中找到。

先决条件

  • AMQ Streams 集群已安装并运行
  • 主题 mytopic 存在

修改主题配置

  1. 使用 kafka-configs.sh 工具获取当前的配置。

    • --bootstrap-server 选项中指定 Kafka 代理的主机和端口。
    • --entity-type 设置为 topic,并将 --entity-name 设置为您的主题的名称。
    • 使用 --describe 选项获取当前的配置。

      bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --entity-type topics --entity-name <TopicName> --describe

      用于获取名为 的主题配置的 命令示例 mytopic

      bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type topics --entity-name mytopic --describe

  2. 使用 kafka-configs.sh 工具更改配置。

    • --bootstrap-server 选项中指定 Kafka 代理的主机和端口。
    • --entity-type 设置为 topic,并将 --entity-name 设置为您的主题的名称。
    • 使用 --alter 选项修改当前配置。
    • 指定您要在选项 --add-config 中添加或更改的选项。

      bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --entity-type topics --entity-name <TopicName> --alter --add-config <Option>=<Value>

      用于更改名为 主题的配置的命令示例 mytopic

      bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type topics --entity-name mytopic --alter --add-config min.insync.replicas=1

  3. 使用 kafka-configs.sh 工具删除现有配置选项。

    • --bootstrap-server 选项中指定 Kafka 代理的主机和端口。
    • --entity-type 设置为 topic,并将 --entity-name 设置为您的主题的名称。
    • 使用 --delete-config 选项删除现有配置选项。
    • 在选项 --remove-config 中指定要删除的选项。

      bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --entity-type topics --entity-name <TopicName> --alter --delete-config <Option>

      用于更改名为 主题的配置的命令示例 mytopic

      bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type topics --entity-name mytopic --alter --delete-config min.insync.replicas

其它资源

5.10. 删除主题

kafka-topics.sh 工具可用于管理主题。kafka-topics.sh 是 AMQ Streams 发布的一部分,可以在 bin 目录中找到。

先决条件

  • AMQ Streams 集群已安装并运行
  • 主题 mytopic 存在

删除主题

  1. 使用 kafka-topics.sh 实用程序删除主题。

    • --bootstrap-server 选项中 Kafka 代理的主机和端口。
    • 使用 --delete 选项指定应删除现有主题。
    • 主题名称必须在 --topic 选项中指定。

      bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --delete --topic <TopicName>

      创建名为 的主题的命令示例 mytopic

      bin/kafka-topics.sh --bootstrap-server localhost:9092 --delete --topic mytopic

  2. 使用 kafka-topics.sh 验证主题已被删除。

    bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --list

    列出所有主题的命令示例

    bin/kafka-topics.sh --bootstrap-server localhost:9092 --list

其它资源

第 6 章 管理 Kafka

使用额外的配置属性来维护 AMQ Streams 的部署。您可以添加和调整设置,以响应 AMQ Streams 的性能。例如,您可以引入其他配置来提高吞吐量和数据可靠性。

6.1. 调整 Kafka 配置

使用配置属性优化 Kafka 代理、生产者和使用者的性能。

需要最小的配置属性集合,但您可以添加或调整属性以更改生产者和使用者如何与 Kafka 代理交互。例如,您可以调整消息的延迟和吞吐量,以便客户端能够实时响应数据。

首先,您可以分析指标来测量进行初始配置的位置,然后逐步更改并进一步比较指标,直到您拥有所需的配置。

其它资源

6.1.1. Kafka 代理配置调整

使用配置属性优化 Kafka 代理的性能。您可以使用标准 Kafka 代理配置选项,但由 AMQ Streams 管理的属性除外。

6.1.1.1. 基本代理配置

基本配置将包括以下属性来识别代理并提供安全访问:

  • broker.id 是 Kafka 代理的 ID
  • log.dirs 是日志数据的目录
  • zookeeper.connect 是用于将 Kafka 与 ZooKeeper 连接的配置
  • listener 向客户端公开 Kafka 集群
  • authorization 机制允许或拒绝用户执行的操作
  • authentication 机制可证明需要访问 Kafka 的用户的身份

您可以在 配置 Kafka 中找到更多有关基本配置选项的详细信息。

典型的代理配置还包括与主题、线程和日志相关的属性设置。

基本代理配置属性

# ...
num.partitions=1
default.replication.factor=3
offsets.topic.replication.factor=3
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=2
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
num.network.threads=3
num.io.threads=8
num.recovery.threads.per.data.dir=1
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
group.initial.rebalance.delay.ms=0
zookeeper.connection.timeout.ms=6000
# ...

6.1.1.2. 复制高可用性主题

基本主题属性为主题设置默认分区和复制因子,它们将应用到没有明确设置这些属性的主题,包括在自动创建主题时。

# ...
num.partitions=1
auto.create.topics.enable=false
default.replication.factor=3
min.insync.replicas=2
replica.fetch.max.bytes=1048576
# ...

auto.create.topics.enable 属性默认启用,以便生产者和消费者需要时自动创建不存在的主题。如果您使用自动创建主题,可以使用 num.partitions 为主题设置默认分区数。但通常禁用此属性,以便通过显式创建主题来提供对主题的更多控制

对于高可用性环境,建议将主题的复制因素增加到至少 3,并将所需同步副本的最小数量设置为比复制因素少 1 个。

对于 数据持久性,您应该在主题配置中设置 min.insync.replicas,并在制作者配置中使用 acks=all 设置消息发送确认。

使用 replica.fetch.max.bytes 设置复制领导分区的每个后续程序获取的信息的最大大小(以字节为单位)。根据平均消息大小和吞吐量更改此值。在考虑读/写缓冲所需的总内存分配时,可用内存还必须能够适应所有跟随者乘以时的最大复制消息大小。大小必须大于 message.max.bytes,以便复制所有信息。

delete.topic.enable 属性默认启用,以允许删除主题。在生产环境中,您应该禁用此属性以避免意外删除主题,从而导致数据丢失。但是,您可以临时启用它并删除主题,然后再次禁用它。

# ...
auto.create.topics.enable=false
delete.topic.enable=true
# ...
6.1.1.3. 事务和提交的内部主题设置

如果您使用事务来 启用从生产者到分区的原子写入,事务状态会存储在内部 __transaction_state 主题中。默认情况下,代理被配置为有 3 个复制因素,这个主题最少需要 2 个 in-sync 副本,这意味着 Kafka 集群中至少需要三个代理。

# ...
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=2
# ...

同样,存储消费者状态的内部 __consumer_offsets 主题对分区数量和复制因素具有默认设置。

# ...
offsets.topic.num.partitions=50
offsets.topic.replication.factor=3
# ...

不要在生产环境中减少这些设置。您可以 在生产环境中 增加设置。作为例外,您可能要减少单broker 测试 环境中的设置。

6.1.1.4. 通过增加 I/O 线程改进请求处理吞吐量

网络线程处理对 Kafka 集群的请求,如从客户端应用程序生成和获取请求。将生成请求放入请求队列中。将响应放入响应队列中。

网络线程数量应当反映复制因素以及与 Kafka 集群交互的客户端生产者和消费者的活动级别。如果您要有大量请求,您可以增加线程数量,使用时间线程闲置来确定何时添加更多线程。

要减少拥塞并规范请求流量,您可以在阻止网络线程前限制请求队列中允许的请求数。

I/O 线程从请求队列获取请求来处理它们。添加更多线程可提高吞吐量,但 CPU 内核数和磁盘带宽会施加一个实际的上限。至少,I/O 线程数量应当等于存储卷的数量。

# ...
num.network.threads=3 1
queued.max.requests=500 2
num.io.threads=8 3
num.recovery.threads.per.data.dir=1 4
# ...
1
Kafka 集群的网络线程数量。
2
请求队列中允许的请求数。
3
Kafka 代理的 I/O 线程数量。
4
用于在启动时加载日志的线程数,在关机时用于清除日志。

所有代理的线程池的配置更新可能会在集群级别动态进行。这些更新限制为当前大小的一半和当前大小的两倍。

注意

Kafka 代理指标可帮助确定所需的线程数量。例如,平均时间网络线程闲置的指标(kafka.network:type=SocketServer,name=NetworkProcessorAvgIdlePercent)表示使用的资源百分比。如果有 0% 的空闲时间,则所有资源都在使用,这意味着添加更多线程可能很有用。

如果线程因为磁盘数量慢或受限,您可以尝试增加网络请求的缓冲大小以提高吞吐量:

# ...
replica.socket.receive.buffer.bytes=65536
# ...

另外,增加 bytes Kafka 可接收的最大字节数:

# ...
socket.request.max.bytes=104857600
# ...
6.1.1.5. 为高延迟连接增加带宽

Kafka 批量数据,以便在从 Kafka 到客户端的高延迟连接中实现合理的吞吐量,如数据中心之间的连接。但是,如果存在高延迟问题,您可以增加用于发送和接收消息的缓冲区的大小。

# ...
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576
# ...

您可以使用 带宽延迟(以字节/秒为单位)估算缓冲区的最大带宽,以估算保持最大 吞吐量所需的缓冲区的大小(以字节/为单位)。

6.1.1.6. 使用数据保留策略管理日志

Kafka 使用日志来存储消息数据。日志是与各种索引关联的一系列片段。新消息写入 活动 段,随后从不修改。服务片段从消费者获取请求时读取。活动片段定期被 滚动 为只读,并创建一个新的活跃网段来替换它。次只有一个部分处于活动状态。旧片段会保留,直到它们符合删除条件。

代理级别的配置设置日志片段的最大大小,以及推出活跃片段前以毫秒为单位的最大时间:

# ...
log.segment.bytes=1073741824
log.roll.ms=604800000
# ...

您可以使用 segment.bytessegment.ms 在主题级别覆盖这些设置。您是否需要降低还是提升这些值取决于片段删除策略。较大的大小意味着活跃片段包含更多信息,且不频繁地推出。段也不再频繁地符合删除条件。

您可以设置基于时间或基于大小的日志保留和清理策略,以便保持日志可被管理。根据您的要求,您可以使用日志保留配置来删除旧片段。如果使用日志保留策略,在达到保留限制时会删除非活跃日志片段。删除旧片段会绑定日志所需的存储空间,因此您不会超过磁盘容量。

对于基于时间的日志保留,您需要根据小时、分钟和毫秒设置保留期限。保留周期基于附加至网段的时间信息。

毫秒配置具有超过分钟的优先级,其优先级高于小时。默认情况下,分钟和毫秒配置为空,但这三个选项提供了对您要保留的数据的大量控制。应优先使用毫秒配置,因为它是唯一可动态更新的三个属性之一。

# ...
log.retention.ms=1680000
# ...

如果 log.retention.ms 设置为 -1,则不会对日志保留应用任何时间限制,因此所有日志都会保留。磁盘使用量应始终受到监控,但通常不建议 -1 设置,因为它可能会导致完整磁盘出现问题,而这可能难以修复。

对于基于大小的日志保留,您需要以字节为单位设置最大日志大小(日志中所有片段):

# ...
log.retention.bytes=1073741824
# ...

换句话说,当日志达到稳定状态后,通常大约有 log.retention.bytes/log.segment.bytes 片段。达到最大日志大小时,会删除旧的网段。

使用最大日志大小时潜在的问题在于它没有考虑消息附加到片段中的时间。您可以将基于时间和大小的日志保留用于清理策略,以获得所需的平衡。达到阈值时首先触发清理。

如果要在从系统中删除片段文件前添加时间延迟,您可以为代理级别的所有主题使用 log.segment.delete.delay.msfile.delete.delay.ms 为主题配置中的特定主题添加延迟。

# ...
log.segment.delete.delay.ms=60000
# ...
6.1.1.7. 使用清理策略删除日志数据

删除较旧日志数据的方法由 日志清理 配置决定。

默认情况下,为代理启用日志清理功能:

# ...
log.cleaner.enable=true
# ...

您可以在主题或代理级别设置清理策略。代理级配置是尚未设置策略的主题的默认设置。

您可以将策略设置为删除日志、紧凑日志,或同时执行这两者:

# ...
log.cleanup.policy=compact,delete
# ...

delete 策略与使用数据保留策略管理日志对应。当不需要永久保留数据时,它非常适合。compact 策略保证为每个消息键保留最新的消息。日志紧凑适合更改消息值,您想要保留最新的更新。

如果将清理策略设置为删除日志,则会根据日志保留限制删除旧的片段。否则,如果没有启用日志清理功能,且没有日志保留限制,日志将继续增加。

如果为日志紧凑设置了清理策略,日志 的头 将作为一个标准 Kafka 日志运行,按顺序为新消息写入操作。在紧凑日志的 尾部 (日志清理操作),如果日志中稍后出现具有相同密钥的另一条记录,则将删除记录。带有 null 值的消息也会被删除。如果不使用键,就无法使用紧凑,因为需要键来识别相关消息。虽然 Kafka 保证每个密钥的最新消息将被保留,但它不能保证整个紧凑的日志不会包含重复项。

图 6.1. 在压缩前以偏移位置显示键值写入的日志

Image of compaction showing key value writes

使用密钥来识别信息,Kafka 紧凑会保留特定消息键的最新消息(带有最高偏移值),最终丢弃之前具有相同密钥的消息。换句话说,其最新状态的消息始终可用,当日志安全运行时,该特定消息的任何过期记录最终都会被删除。您可以将消息恢复到以前的状态。

即使记录被删除,记录也会保留原始偏移。因此,尾部可能有非连续偏移。当消耗在尾部中不再可用的偏移时,会找到具有下一个高偏移量的记录。

图 6.2. 紧凑后日志

Image of compaction after log cleanup

如果您只选择紧凑的策略,您的日志仍然可以变得任意大。在这种情况下,您可以将策略设置为压缩 和删除 日志。如果您选择压缩和删除,则首先压缩日志数据,从而删除日志头带有键的记录。之后,在删除日志保留阈值之前发布的数据。

图 6.3. 日志保留点和压缩点

Image of compaction with retention point

您需要设置以毫秒为单位检查清理的频率:

# ...
log.retention.check.interval.ms=300000
# ...

调整与日志保留设置相关的日志保留检查间隔。较小的保留大小可能需要更频繁地检查。

清理的频率应该足以管理磁盘空间,但经常影响某个主题的性能。

您还可以以毫秒为单位设置一个时间,以便在没有要清理的日志时将清理干净到备用中:

# ...
log.cleaner.backoff.ms=15000
# ...

如果您选择删除旧的日志数据,您可以在清除数据前设置一个毫秒来保留删除的数据:

# ...
log.cleaner.delete.retention.ms=86400000
# ...

删除的数据保留期限给予了时间,可以注意到数据在不可删除之前已丢失。

若要删除与特定密钥相关的所有消息,制作者可以发送 tomb stone 消息。am bstone 具有 null 值,充当标记来告知消费者删除其值。紧凑后,只保留了 tombstone,它必须持续足够长的时间,使消费者能够知道该消息被删除。删除旧消息后,没有值,也会从分区中删除 tombstone 密钥。

6.1.1.8. 管理磁盘使用率

还有许多其他与日志清理相关的配置设置,但特别重要的是内存分配。

deduplication 属性指定在所有日志清理线程中清理的总内存。您可以设置通过缓冲区负载因数使用的内存百分比的上限。

# ...
log.cleaner.dedupe.buffer.size=134217728
log.cleaner.io.buffer.load.factor=0.9
# ...

每个日志条目都使用正好 24 字节,因此您可以计算一次缓冲区可以处理的日志条目数量,并相应地调整设置。

如果您希望减少日志清理时间,请考虑增加日志清理线程数量:

# ...
log.cleaner.threads=8
# ...

如果您遇到 100% 磁盘带宽使用情况的问题,您可以限制日志清理 I/O,根据执行操作的磁盘功能,读写操作的总和小于指定的双值:

# ...
log.cleaner.io.max.bytes.per.second=1.7976931348623157E308
# ...
6.1.1.9. 处理大消息大小

消息的默认批处理大小为 1MB,这是大多数用例中最大吞吐量的最佳选择。如果有足够的磁盘容量,Kafka 能够以更低的吞吐量来容纳较大的批处理。

处理较大的消息的大小有四种方式:

  1. 生产者侧消息压缩 将压缩的消息写入日志中。
  2. 基于参考的消息传递仅发送对消息值中某个其他系统中存储数据的引用。
  3. 内联消息传递将消息分割为使用相同键的块,然后通过 Kafka Streams 等流处理器将其组合在输出上。
  4. 为处理更大消息大小而构建的代理和制作者/消费者客户端应用配置.

建议使用基于参考的消息和消息压缩选项,并覆盖大多数情况。对于这些选项,必须小心谨慎以避免引入性能问题。

生产者侧压缩

对于制作者配置,您可以指定一个 compression.type,如 Gzip,然后应用到生产者生成的数据的批处理。使用代理配置 compression.type=producer,代理会保留使用的任何压缩程序。每当生产者和主题压缩不匹配时,代理必须在将批处理附加到日志中,这会影响代理性能。

压缩还会增加制作者的额外处理开销和消费者的解压缩开销,但在批量中包含更多数据,因此在消息数据压缩不错时,通常对吞吐量很有用。

将制作者侧压缩与批处理大小的微调相结合,促进最佳吞吐量。使用指标有助于测量所需的平均批处理大小。

基于参考的消息传递

当您不知道消息的大程度时,基于参考的消息传递对于数据复制非常有用。外部数据存储必须快速、持久且高度可用,此配置才能发挥作用。将数据写入数据存储,并返回对数据的引用。制作者发送一条包含对 Kafka 引用的消息。使用者从消息中获取引用,并使用它来从数据存储中获取数据。

图 6.4. 基于参考的消息传递流

Image of reference-based messaging flow

由于消息传递需要更多行程,端到端延迟会增加。这种方法的另一个显著缺点是,在清理 Kafka 消息时,没有自动清理外部系统中的数据。混合方法是仅向数据存储直接发送大型消息,并直接处理标准大小的消息。

内联消息传递

内联消息传递很复杂,但开销不会依赖于基于参考的消息传递等外部系统。

如果消息太大,产生客户端应用必须按顺序进行序列化,然后对数据进行块。然后,制作者使用 Kafka ByteArraySerializer 或者类似地再次对每个块进行序列化,然后再发送它。使用者跟踪消息和缓冲块,直到消息完整消息为止。消耗的客户端应用程序接收区块,这些区块在反序列化之前组装。根据每组区块消息的第一块或最后一个块的偏移,将完整消息传送到正在使用的应用的其余部分。针对偏移元数据检查成功发送完整消息,以避免在重新平衡期间重复。

图 6.5. 内联消息传递流

Image of inline messaging flow

由于需要缓冲,内联消息传递在消费者一侧具有性能开销,特别是在并行处理一系列大型消息时。大型消息的块可能会相互交集,因此,如果缓冲区中另一条大消息的块不完整,则始终无法在消息的所有块被使用时提交。因此,缓冲区通常由持久消息区块或实施提交逻辑来支持。

配置以处理较大的信息

如果无法避免较大的消息,并且为了避免在消息流的任意点上阻止,您可以增加消息限值。为此,请在主题级别配置 message.max.bytes,为各个主题设置最大记录批处理大小。如果您在代理级别设置了 message.max.bytes,则允许所有主题显示更大的信息。

代理将拒绝任何大于 message.max.bytes 设置的限制信息。生产者(max.request.size)和使用者(message.max.bytes)的缓冲大小必须能够容纳较大的信息。

6.1.1.10. 控制消息数据的日志清除

日志刷新属性控制缓存的消息数据的定期写入磁盘。调度程序以毫秒为单位指定日志缓存中的检查频率:

# ...
log.flush.scheduler.interval.ms=2000
# ...

您可以根据信息保存内存的最大时间以及日志中的信息在写入磁盘前的最大信息数来控制刷新的频率:

# ...
log.flush.interval.ms=50000
log.flush.interval.messages=100000
# ...

清空之间的等待包括检查的时间和执行清除前的指定间隔。增加清空的频率可能会影响吞吐量。

通常,建议不要设置明确的清空阈值,并让操作系统使用其默认设置执行后台刷新。分区复制比写入单个磁盘的数据持久性要高,因为故障代理可以从其同步副本中恢复。

如果您使用应用程序清空管理,如果使用更快的磁盘,则可能最好设置较低的清空阈值。

6.1.1.11. 对可用性进行分区重新平衡

分区可以在代理之间复制,以实现容错。对于给定的分区,一个代理被选为领导,并处理所有生成的请求(写入到日志)。在出现领导故障时,其他代理的分区跟踪者复制分区领导者的分区数据,以实现数据可靠性。

跟随者通常不为客户端服务,但 broker.rack 允许使用者在 Kafka 集群跨越多个数据中心时消耗来自最接近的副本的消息。跟随者只从分区领导机复制消息,并在领导机失败时允许恢复。恢复需要一个同步跟踪器。跟随者通过向领导发送获取请求来保持同步,后者按顺序向跟随者返回消息。如果跟踪者发现了领导上最近提交的邮件,则被视为同步。领导机通过查看跟随者请求的最后偏移来检查这一点。除非允许未清理的领导选举,否则无法同步跟进者作为当前的领导机 故障。

您可以调整跟随者被视为不同步前的滞后时间:

# ...
replica.lag.time.max.ms=30000
# ...

滞后时间为将消息复制到所有同步副本的时间施加了上限,以及生产者必须等待确认的时间。如果跟踪器无法发出获取请求并在指定滞后时间内跟上最新的消息,则会从同步副本中删除它。您可以缩短检测失败副本的滞后时间,但这样做可能会增加无用同步的后续者的数量。正确的滞后时间值取决于网络延迟和代理磁盘带宽。

当领导分区不再可用时,会选择同步内的副本之一作为新领导。分区副本列表中的第一个代理称为 首选 的领导。默认情况下,Kafka 会根据对领导发行的定期检查来为自动分区领导重新平衡启用 Kafka。也就是说,Kafka 检查首选的领导是否是 当前的 领导机。重新平衡可确保领先者在代理和代理之间均匀分布,不会过载。

您可以使用 AMQ Streams 的 Cruise Control 来找出副本分配,以便代理在整个集群中平均平衡负载。其计算考虑了领导者和追随者所经历的不同负载。失败的领导机会影响 Kafka 集群的平衡,因为剩余的代理会获得前导额外分区的额外工作。

要使 Cruise Control 发现的分配真正达到平衡,分区必须要由首选领导领导。Kafka 可以自动确保使用首选的领导机(在可能的情况下),根据需要更改当前的领导机。这样可确保集群保持 Cruise Control 找到的均衡状态。

您可以在触发重新平衡前,以秒为单位控制重新平衡检查的频率和代理允许的最大发生率。

#...
auto.leader.rebalance.enable=true
leader.imbalance.check.interval.seconds=300
leader.imbalance.per.broker.percentage=10
#...

代理的领导地位百分比是代理作为当前领导者的分区数量与首选领导者分区数量之间的比例。您可以将百分比设置为零,以确保始终选中首选领导者,假设他们同步。

如果重新平衡的检查需要更多控制,您可以禁用自动重新平衡。然后,您可以选择何时使用 kafka-leader-election.sh 命令行工具触发重新平衡。

注意

随 AMQ Streams 提供的 Grafana 仪表板显示没有活跃领导的复制分区和分区的指标。

6.1.1.12. 未清理领导选举机制

同步副本的领导选举被视为干净,因为它保证不会丢失数据。这是默认情况下会发生的情况。但是,如果没有可以承担领导地位的同步副本,情况会怎样?或许 ISR(同步副本)仅在领导磁盘终止时包含领导机。如果没有设置最少的同步副本数,且其硬盘驱动器出现故障时没有跟随分区领导器同步,则数据已经丢失。不仅 不能这种情况,而且不能选择新的领导,因为不存在同步的追随者。

您可以配置 Kafka 如何处理领导故障:

# ...
unclean.leader.election.enable=false
# ...

Unclean leader 选举默认被禁用,这意味着不同步的副本不能成为领导。使用干净的领导选举机制时,如果没有其他代理在旧领导丢失时处于 ISR 中,Kafka 会等待该领导者重新在线,然后再写入或读取消息。unclean leader 选举机制意味着不同步的副本可能会成为领导者,但您会面临丢失消息的风险。您选择的选择取决于您的需求是否有利于可用性或持久性。

您可以覆盖主题级别上特定主题的默认配置。如果无法承担数据丢失的风险,请保留默认配置。

6.1.1.13. 避免不必要的消费者组重新平衡

对于加入新消费者组的消费者,您可以添加延迟,以避免不必要的重新平衡到代理:

# ...
group.initial.rebalance.delay.ms=3000
# ...

延迟是协调会等待会员加入的时间。延迟时间越长,所有成员越有可能加入并避免重新平衡。但是,这一延迟也会阻止该组在句点结束前被消耗掉。

6.1.2. Kafka 生成器配置调整

使用基本制作者配置,以及为特定用例量身定制的可选属性。

调整配置以最大化吞吐量可能会增加延迟,反之亦然。您将需要试验并调优制作者配置,以获得所需的平衡。

6.1.2.1. 基本制作者配置

每个制作者都需要连接和序列化程序属性。通常而言,最好是添加客户端 ID 以进行跟踪,并对制作者使用压缩来减少请求中的批处理大小。

在基本制作者配置中:

  • 无法保证分区中消息的顺序。
  • 确认到达代理的消息不能保证持久性。

基本制作者配置属性

# ...
bootstrap.servers=localhost:9092 1
key.serializer=org.apache.kafka.common.serialization.StringSerializer 2
value.serializer=org.apache.kafka.common.serialization.StringSerializer 3
client.id=my-client 4
compression.type=gzip 5
# ...

1
(必需)告诉制作者使用 Kafka 代理的 host:port bootstrap 服务器地址连接到 Kafka 集群。制作者使用该地址来发现和连接集群中的所有代理。在服务器停机时使用逗号分隔列表来指定两个或三个地址,但不需要提供集群中所有代理的列表。
2
(必需)在将每条消息的密钥发送到代理前将其转换为字节。
3
(必需)在将每个消息发送到代理前将每条消息的值转换为字节。
4
(可选)客户端的逻辑名称,用于日志和指标来标识请求的来源。
5
(可选)压缩消息的编码器(发送并可能以压缩格式存储),然后在到达消费者时解压缩。压缩对于提高吞吐量和减少存储负载非常有用,但可能不适用于低延迟应用程序,因为压缩或解压成本可能过高。
6.1.2.2. 数据持久性

您可以使用消息发送确认,应用更大的数据持久性,以最大程度降低消息丢失的可能性。

# ...
acks=all 1
# ...
1
指定 acks=all 在确认消息请求已成功接收前,强制分区领导将信息复制到一定数量的跟随者。由于附加检查,acks=all 会增加制作者发送消息和接收确认之间的延迟。

在将确认发送到生产者之前,需要将信息附加到日志的代理数量由主题的 min.insync.replicas 配置决定。典型的起点是将主题复制因数为 3,其他代理上有两个内联副本。在这种配置中,如果单个代理不可用,生产者可以继续不受影响。如果第二个代理不可用,生产者将不会收到确认并且无法生成更多消息。

要支持的主题配置 acks=all

# ...
min.insync.replicas=2 1
# ...

1
使用同步副本 2。默认值为 1
注意

如果系统失败,则缓冲区中存在不正确的数据丢失的风险。

6.1.2.3. 订购交付

幂等制作者避免重复,因为消息只发送一次。为消息分配了 ID 和序列号,以确保传送顺序,即使出现故障也是如此。如果您使用 acks=all 以实现数据一致性,启用幂等性对有序交付有利。

使用幂等方式订购交付

# ...
enable.idempotence=true 1
max.in.flight.requests.per.connection=5 2
acks=all 3
retries=2147483647 4
# ...

1
设置为 true 以启用幂等生成器。
2
通过幂等发送,即时请求数可能大于 1,同时仍然提供消息排序保证。默认值为 5 个 in-flight 请求。
3
acks 设置为 all
4
设置重新发送失败消息请求的尝试次数。

如果您没有因为性能成本而使用 acks=all 和幂等性,请将提示内(未确认)请求数设置为 1 来保持排序。否则,只有在 Message- B 已写入代理后 Message- A 可能无法成功。

在没有幂等的情况下订购交付

# ...
enable.idempotence=false 1
max.in.flight.requests.per.connection=1 2
retries=2147483647
# ...

1
设置为 false 以禁用幂等生成器。
2
将 in-flight 请求数设置为正好 1
6.1.2.4. 可靠性保证

仅对写入单个分区一次,Idempotence 非常有用。事务处理与幂等性一起使用时,允许在多个分区间只写入一次。

事务可确保使用相同事务 ID 的消息只生成一次,并且将 所有 消息都成功写入到对应的日志中,或者其中任何消息 都不是.

# ...
enable.idempotence=true
max.in.flight.requests.per.connection=5
acks=all
retries=2147483647
transactional.id=UNIQUE-ID 1
transaction.timeout.ms=900000 2
# ...
1
指定唯一的事务 ID。
2
在返回超时错误前,设置以毫秒为单位进行事务的最大允许时间。默认值为 900000 或 15 分钟。

选择 transactional.id 非常重要,以便保持事务保证。每个事务 id 都应该用于一组唯一的主题分区。例如,这可以通过外部映射主题分区名称到事务 id 来实现,或者通过使用避免冲突的功能计算主题分区名称中的事务 ID。

6.1.2.5. 优化吞吐量和延迟

通常,系统的要求是满足给定延迟内一定比例消息的特定吞吐量目标。例如,以每秒 500,000条消息为目标,95% 的消息会在 2 秒内得到确认。

生产者的消息传递语义(消息排序和持久性)很可能根据您的应用程序的要求进行定义。例如,您可以选择在不破坏某些重要属性的情况下使用 acks=0acks=1 或者应用程序提供保证。

Broker 重新启动对高百分比统计数据有显著影响。例如,在很长一段时间内,99 百分点延迟由围绕代理重启的行为占据主导地位。在设计基准测试时,或比较基准测试与生产中显示的性能数字时,需要考虑这一点。

根据您的目标,Kafka 提供了多个配置参数和技术来调节吞吐量和延迟的性能。

消息批处理(linger.msbatch.size
消息批处理会延迟发送消息,希望将发送更多目标为同一代理的消息,允许它们批处理到单个生成请求。批处理是在高吞吐量时返回的更高延迟之间的妥协。使用 linger.ms 配置基于时间的批处理,并使用 batch.size 配置基于大小的批处理。
压缩(compression.type)
消息压缩增加了制作者延迟(CPU 时间用于压缩消息),但会更小(可能进行磁盘写入),这可以提高吞吐量。压缩是否必要,以及要使用的最佳压缩程度取决于所发送的消息。压缩发生在调用 KafkaProducer.send() 的线程中,因此如果此方法的延迟与您需要使用更多线程的应用程序相关。
pipelining(max.in.flight.requests.per.connection)
pipelining 意味着在收到对上一个请求的响应前发送更多请求。通常,更多流水线意味着更好的吞吐量,最高是一个阈值,达到其他效果(例如更糟糕的批处理)开始消除对吞吐量的影响。

降低延迟

当您的应用程序调用 KafkaProducer.send() 时,信息为:

  • 由任何拦截器处理
  • serialized
  • 分配给分区
  • 已压缩
  • 添加到每个分区队列中的批量消息

send() 方法返回的时间点。send() 被阻塞的时间由以下方法决定:

  • 拦截器、序列程序和分区器花费的时间
  • 使用的压缩算法
  • 等待缓冲区用于压缩所需的时间

批处理将保留在队列中,直到出现以下情况之一:

  • 批处理已满(根据 batch.size
  • linger.ms 引入的延迟已过
  • 发送方即将向同一代理发送其他分区的消息批处理,也可以添加此批处理
  • 生产者被清空或关闭

查看批处理和缓冲的配置,以减轻 send() 阻塞对延迟的影响。

# ...
linger.ms=100 1
batch.size=16384 2
buffer.memory=33554432 3
# ...
1
linger 属性添加了一个毫秒的延迟,以便在请求中累积和发送更大规模的消息。默认值为 0'.
2
如果使用最大 batch.size (以字节为单位),则会在达到最大值时发送请求,或者信息排队的时间超过 linger.ms (以较快者为准)。添加延迟可让批处理积累消息到批处理大小。
3
缓冲区的大小必须至少与批处理大小相同,并且能够适应缓冲区、压缩和内向请求。

增加吞吐量

通过调整消息传输和完成发送请求前等待的最长时间,提高消息请求的吞吐量。

您还可以通过编写自定义分区程序来替换默认分区,将消息定向到指定分区。

# ...
delivery.timeout.ms=120000 1
partitioner.class=my-custom-partitioner 2

# ...
1
等待完整发送请求的最长时间,以毫秒为单位。您可以将值设置为 MAX_LONG 来委派给 Kafka 无限期重试次数。默认值为 120000 或 2 分钟。
2
指定自定义分区器的类名称。

6.1.3. Kafka 使用者配置调整

使用基本使用者配置,以及根据特定用例量身定制的可选属性。

调优您的消费者时,您的主要顾虑是确保它们能高效地应对被窃取的数据量。与制作者调优一样,准备好进行增量更改,直到消费者按预期工作。

6.1.3.1. 基本使用者配置

每个消费者都需要连接和反序列化器属性。通常,最好添加客户端 ID 进行跟踪。

在使用者配置中,无论后续配置如何:

  • 消费者从给定的偏移获取并按顺序使用消息,除非偏差被更改为跳过或重新读取消息。
  • 代理不知道消费者是否处理了响应,即使对 Kafka 提交偏移也是如此,因为偏移可能会发送到集群中的不同代理。

基本使用者配置属性

# ...
bootstrap.servers=localhost:9092 1
key.deserializer=org.apache.kafka.common.serialization.StringDeserializer  2
value.deserializer=org.apache.kafka.common.serialization.StringDeserializer  3
client.id=my-client 4
group.id=my-group-id 5
# ...

1
(必需)告诉使用者使用 Kafka 代理的 host:port bootstrap 服务器地址连接到 Kafka 集群。使用者使用该地址来发现并连接到集群中的所有代理。在服务器停机时使用逗号分隔列表来指定两个或三个地址,但不需要提供集群中所有代理的列表。如果您使用负载均衡器服务公开 Kafka 集群,则只需要该服务的地址,因为负载均衡器处理其可用性。
2
(必需)Deserializer 将从 Kafka 代理获取的字节转换为消息密钥。
3
(必需)Deserializer 将从 Kafka 代理获取的字节转换为消息值。
4
(可选)客户端的逻辑名称,用于日志和指标来标识请求的来源。id 也可用于根据处理时间配额对消费者进行限流。
5
(条件) 用户需要 组 ID 才能加入消费者组。
6.1.3.2. 使用消费者组扩展数据消耗

消费者组共享一个由一个或多个生产者从给定主题生成的大型数据流。用户使用 group.id 属性分组,允许信息分散到成员中。组中的一个消费者被选为领导,并决定如何将该分区分配给组中的使用者。每个分区只能分配给一个消费者。

如果您还没有多少消费者作为分区,可以通过添加相同 group.id 的更多消费者实例来扩展数据消耗。将更多的消费者添加到组中,超过现有分区,但这意味着如果一个分区停止工作,就表示待机使用者处于待机状态。如果您能够以更少的消费者达到吞吐量目标,就可以节省资源。

同一消费者组中的消费者发送偏移提交和心跳到同一代理。因此组中的消费者数量越多,代理上的请求负载就越大。

# ...
group.id=my-group-id 1
# ...
1
使用组 ID 将使用者添加到消费者组中。
6.1.3.3. 消息排序保证

Kafka 代理从客户接收请求,要求代理从主题、分区和偏移位置列表中发送消息。

用户会按照提交至代理的顺序以单个分区中观察消息,这意味着 Kafka 仅在 单一分区中为消息提供排序保证。相反,如果消费者使用来自多个分区的消息,则使用者观察到的不同分区中消息的顺序不一定反映它们的发送顺序。

如果您需要严格排序一个主题的消息,请为每个使用者使用一个分区。

6.1.3.4. 优化吞吐量和延迟

控制客户端应用调用 KafkaConsumer.poll() 时返回的消息数量。

使用 fetch.max.wait.msfetch.min.bytes 属性增加消费者从 Kafka 代理获取的最小数据量。使用 fetch.max.wait.ms 配置基于时间的批处理,并使用 fetch.min.bytes 配置基于大小的批处理。

如果消费者或代理中的 CPU 使用率较高,则可能是因为消费者的请求太多。您可以调整 fetch.max.wait.msfetch.min.bytes 属性,以便在更大的批处理中发送的请求和信息较少。通过调整较高的吞吐量,可以降低延迟成本。如果产生的数据量较低,您也可以调整更高的值。

例如:如果您将 fetch.max.wait.ms 设置为 500ms,fetch.min.bytes 设置为 16384 字节,当 Kafka 收到来自消费者的获取请求时,它会在达到任一阈值的第一个阈值时响应。

相反,您可以降低 fetch.max.wait.msfetch.min.bytes 属性调整,以改进端到端延迟。

# ...
fetch.max.wait.ms=500 1
fetch.min.bytes=16384 2
# ...
1
代理在完成获取请求前将等待的最长时间,以毫秒为单位。默认值为 500 毫秒。
2
如果使用的最小批处理大小(以字节为单位),则会在达到最小值时发送请求,或者消息排队的时间超过 fetch.max.wait.ms (以较快者为准)。添加延迟可让批处理积累消息到批处理大小。

通过增大获取请求大小来降低延迟

使用 fetch.max.bytesmax.partition.fetch.bytes 属性增加使用者从 Kafka 代理获取的最大数据量。

fetch.max.bytes 属性设置一次从代理获取的数据量上限,以字节为单位。

max.partition.fetch.bytes 为每个分区返回的数据量以字节为单位设置的最大限制,必须始终大于代理或 max.message.bytes 主题配置中设置的字节数。

客户端可消耗的最大内存量计算如下:

NUMBER-OF-BROKERS * fetch.max.bytes and NUMBER-OF-PARTITIONS * max.partition.fetch.bytes

如果内存用量可以容纳它,您可以增加这两个属性的值。通过在每个请求中允许更多数据,可以提高延迟,因为获取请求的数量较少。

# ...
fetch.max.bytes=52428800 1
max.partition.fetch.bytes=1048576 2
# ...
1
为获取请求返回的最大数据量,以字节为单位。
2
每个分区返回的最大数据量,以字节为单位。
6.1.3.5. 在提交偏移时避免数据丢失或重复

Kafka 自动提交机制 允许使用者自动提交消息偏移。如果启用,消费者将以 5000ms 间隔提交从轮询代理收到的偏移。

自动提交机制很方便,但会带来数据丢失和复制风险。如果使用者已获取并转换了大量消息,但执行自动提交时,系统会对消费者缓冲区中已处理的消息崩溃,该数据将会丢失。如果系统在处理消息后崩溃,但在执行自动使用前,数据会在重新平衡后在另一个消费者实例上重复。

仅当在下一次轮询到代理或消费者关闭之前处理所有消息时,自动使用才可以避免数据丢失。

要最小化数据丢失或重复的可能性,您可以将 enable.auto.commit 设置为 false,并开发您的客户端应用程序,使其对提交的偏移拥有更多控制权。或者您可以使用 auto.commit.interval.ms 减少提交之间的间隔。

# ...
enable.auto.commit=false 1
# ...
1
自动提交设为 false,以提供对提交偏移的更多控制。

通过将 enable.auto.commit 设置为 false,您可以在执行了 所有 处理并且消息已被使用后提交偏移。例如,您可以将应用程序设置为调用 Kafka commitSynccommitAsync 提交 API。

commitSync API 在从轮询返回的消息批处理中提交偏移。完成批处理中的所有消息后,您将调用 API。如果您使用 commitSync API,在提交批处理中的最后一个偏移前,应用不会轮询新信息。如果这会对吞吐量造成负面影响,您可以降低提交的频率,也可以使用 commitAsync API。commitAsync API 不等待代理响应提交请求,但会在重新平衡时造成更多的重复。种常见的做法是将应用中的两个提交 API 与刚刚在关闭使用者或重新平衡前使用的 commitSync API 合并,以确保最终提交成功。

6.1.3.5.1. 控制事务性消息

考虑在制作者一侧使用事务 id 并启用幂等性(enable.idempotence=true)来保证准确交付。在消费者方面,您可以使用 isolation.level 属性控制消费者如何读取事务性消息。

isolation.level 属性有两个有效值:

  • read_committed
  • read_uncommitted (默认)

使用 read_committed 确保消费者只读取提交的事务信息。但是,这会导致端到端延迟增加,因为在代理写入了记录事务结果的事务标记(已承诺 或中止)之前,消费者将无法返回消息

# ...
enable.auto.commit=false
isolation.level=read_committed 1
# ...
1
设置为 read_committed,以便消费者只读取提交的信息。
6.1.3.6. 从失败中恢复,以避免数据丢失

使用 session.timeout.msheartbeat.interval.ms 属性配置检查并恢复消费者组中的消费者故障的时间。

session.timeout.ms 属性指定在被视为不活跃并在组中活跃消费者之间触发 重新平衡 前,消费者组中的最大时间(毫秒)可以无法与代理联系。当组重新平衡时,这些分区将重新分配给组的成员。

heartbeat.interval.ms 属性指定心跳与消费者组协调器之间的 心跳 之间的间隔,以指示消费者活跃并连接。heartbeat 间隔必须小于会话超时间隔,通常为第三个。

如果您将 session.timeout.ms 属性设置为较低,则之前检测到失败的使用者,重新平衡可以更快地进行。但是,请不要设置超时时间,以便代理无法及时收到心跳,并触发不必要的重新平衡。

减少心跳间隔降低了意外重新平衡的可能性,但更频繁的心跳会增加对代理资源的开销。

6.1.3.7. 管理偏移策略

使用 auto.offset.reset 属性控制当没有提交偏移时消费者的行为方式,或者提交偏移无效或删除。

假设您第一次部署使用者应用,并且它从现有主题读取消息。因为这是第一次使用 group.id,所以 __consumer_offsets 主题不包含这个应用程序的任何偏移信息。新应用可以从日志开始时开始处理所有现有消息,或者仅处理新消息。默认重置值为 latest,它从分区末尾开始,因此表示丢失了一些信息。要避免数据丢失,但增加处理量,将 auto.offset.reset 设置为 earliest 以从分区开头开始。

另请考虑使用 earliest 选项避免在为代理配置的偏移保留周期(offsets.retention.minutes)终止时丢失消息。如果消费者组或独立消费者不活跃,且在保留周期内未提交偏移,则之前提交的偏移会从 __consumer_offsets 中删除。

# ...
heartbeat.interval.ms=3000 1
session.timeout.ms=10000 2
auto.offset.reset=earliest 3
# ...
1
根据预期的重新平衡,调整心跳间隔越低。
2
如果 Kafka 代理在超时期限到期前未收到 heartbeat,则消费者会从消费者组中移除,并启动重新平衡。如果代理配置有 group.min.session.timeout.msgroup.max.session.timeout.ms,会话超时值必须在那个范围内。
3
设置为 earliest 以返回到分区的开头,并在未提交偏移时避免数据丢失。

如果单个获取请求中返回的数据量较大,则使用者处理数据之前可能会发生超时。在这种情况下,您可以降低 max.partition.fetch.bytes 或增加 session.timeout.ms

6.1.3.8. 最小化重新平衡的影响

在组中活跃使用者之间重新平衡分区是以下时间:

  • 消费者提交偏移
  • 要成立的新消费者组
  • 将分区分配给组成员的组领导
  • 组中的消费者接收其分配并开始获取

显然,这个过程会增加服务的停机时间,特别是在客户组群集滚动重启期间重复发生时。

在这种情况下,您可以使用 静态成员资格 的概念来减少重新平衡的数量。重新平衡使用者组成员之间均匀分配主题分区。静态成员资格使用持久性,以便在会话超时后在重启期间识别使用者实例。

用户组协调可以使用使用 group.instance.id 属性指定的唯一 ID 来识别新的消费者实例。在重启期间,会为消费者分配一个新成员 ID,但作为静态成员,它将继续使用相同的实例 ID,并分配相同的主题分区。

如果消费者应用程序没有调用来至少轮询每个 max.poll.interval.ms 毫秒,则消费者会被视为失败,从而导致重新平衡。如果应用无法及时处理轮询返回的所有记录,您可以使用 max.poll.interval.ms 属性为消费者的新消息指定轮询间隔,以避免重新平衡。或者您可以使用 max.poll.records 属性设置从消费者缓冲区返回的记录数上限,允许您的应用程序处理较少的 max.poll.interval.ms 限制中的记录。

# ...
group.instance.id=_UNIQUE-ID_ 1
max.poll.interval.ms=300000 2
max.poll.records=500 3
# ...
1
唯一的实例 ID 可确保新使用者实例接收相同的主题分区分配。
2
设置检查消费者是否继续处理消息的时间间隔。
3
设置从使用者返回的已处理记录数。

6.2. 使用 Kafka Static Quota 插件设置代理的限制

重要

Kafka 静态配额插件只是一个技术预览。技术预览功能不被红帽产品服务级别协议(SLA)支持,且可能无法完成功能。红帽不推荐在生产环境中实施任何技术预览功能。此技术预览功能为您提供对即将推出的产品创新的早期访问,允许您在开发过程中测试并提供反馈。有关红帽技术预览功能支持范围的更多信息,请参阅 技术预览功能支持范围

使用 Kafka Static Quota 插件,为 Kafka 集群中的代理设置吞吐量和存储限制。您可以通过在 Kafka 配置文件中添加属性来启用插件并设置限制。您可以设置字节阈值和存储配额,对与代理交互的客户端设定限制。

您可以为生产者和消费者带宽设置字节速率阈值。总限值分布在所有访问代理的客户端中。例如,您可以为生产者设置 40 MBps 的字节阈值。如果两个制作者正在运行,则每个生产者的吞吐量限制为 20 MBps。

存储配额在软限制和硬限制之间节流 Kafka 磁盘存储限制。这些限制适用于所有可用磁盘空间。在软限制和硬限制之间逐渐减慢生产者的速度。这些限制可防止磁盘过快占用并超出其容量。完整磁盘可能会导致问题难以解决。硬限制是最大存储限制。

注意

对于 JBOD 存储,限制适用于所有磁盘。如果代理使用两个 1 TB 磁盘,且配额为 1.1 TB,则一个磁盘可能会填满,另一个磁盘将几乎为空。

先决条件

流程

  1. 编辑 /opt/kafka/config/server.properties Kafka 配置文件。

    示例配置中显示了插件属性。

    Kafka 静态配额插件配置示例

    # ...
    client.quota.callback.class=io.strimzi.kafka.quotas.StaticQuotaCallback 1
    client.quota.callback.static.produce=1000000 2
    client.quota.callback.static.fetch=1000000 3
    client.quota.callback.static.storage.soft=400000000000 4
    client.quota.callback.static.storage.hard=500000000000 5
    client.quota.callback.static.storage.check-interval=5 6
    # ...

    1
    加载 Kafka 静态配额插件。
    2
    设置制作者字节率阈值。本例中为 1 Mbps。
    3
    设置使用者字节率阈值。本例中为 1 Mbps。
    4
    为存储设置下限。本例中为 400 GB。
    5
    为存储设置较高的硬限制。本例中为 500 GB。
    6
    设置存储检查间隔(以秒为单位)。在这个示例中为 5 秒。您可以将此项设置为 0 以禁用检查。
  2. 使用默认配置文件启动 Kafka 代理。

    su - kafka
    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  3. 验证 Kafka 代理正在运行。

    jcmd | grep Kafka

6.3. 扩展集群

6.3.1. 扩展 Kafka 集群

6.3.1.1. 在集群中添加代理

提高某个主题吞吐量的主要方法是增加该主题的分区数量。这是因为分区允许在集群中的代理之间共享该主题的负载。当代理都受到某些资源(通常是 I/O)的限制时,使用更多分区将不会产生吞吐量的增长。相反,您必须在集群中添加代理。

当您在集群中添加额外的代理时,AMQ Streams 不会自动为其分配任何分区。您必须决定哪些分区需要从现有代理迁移到新代理。

在所有代理之间重新分布分区后,每个代理的资源使用率应较低。

6.3.1.2. 从集群中删除代理

在从集群中删除代理前,您必须确定它没有被分配给任何分区。您应该决定剩余的代理将负责代理的每个要停用的分区。代理没有分配分区后,就可以停止它。

6.3.2. 重新分配分区

kafka-reassign-partitions.sh 工具用于将分区重新分配给不同的代理。

它有三种不同的模式:

--generate
取一组主题和代理,并生成 重新分配 JSON 文件,该文件将导致这些主题的分区分配给这些代理。这是生成 重新分配 JSON 文件 的一种简单方法,但它作用于整个主题,因此使用它不一定是合适的。
--execute
重新分配 JSON 文件 并将其应用到集群中的分区和代理。正在获得分区的代理将成为分区领导者的追随者。对于给定分区,新代理一旦发现并加入 ISR 后,旧的代理将停止作为追随者并删除其副本。
--verify
使用与 --execute 步骤相同的 重新分配 JSON 文件--verify 检查文件中的所有分区是否已移到预期的代理中。如果重新分配完成后,它也会移除任何生效的 节流。除非被删除,否则节流将继续影响群集,即使重新分配完成后也是如此。

在任意给定时间只能在集群中运行一个重新分配,且无法取消正在运行的重新分配。如果您需要取消重新分配,必须等待它完成,然后执行另一个重新分配来恢复第一个分配的效果。kafka-reassign-partitions.sh 将输出这个重新版本的重新分配 JSON 作为其输出的一部分。在需要停止进行中的重新分配时,应将非常大的重新分配分成几个较小的重新分配。

6.3.2.1. 重新分配 JSON 文件

重新分配 JSON 文件 有一个特定的结构:

{
  "version": 1,
  "partitions": [
    <PartitionObjects>
  ]
}

其中 <PartitionObjects> 是一个用逗号分开的对象列表,例如:

{
  "topic": <TopicName>,
  "partition": <Partition>,
  "replicas": [ <AssignedBrokerIds> ],
  "log_dirs": [<LogDirs>]
}

"log_dirs" 属性是可选的,用于将分区移到特定的日志目录中。

以下是重新分配 JSON 文件的示例,该文件分配主题 topic-a,分区 4 分配给代理 247,以及主题 topic-b 分区 2 分配给代理 157

{
  "version": 1,
  "partitions": [
    {
      "topic": "topic-a",
      "partition": 4,
      "replicas": [2,4,7]
    },
    {
      "topic": "topic-b",
      "partition": 2,
      "replicas": [1,5,7]
    }
  ]
}

JSON 中没有包括的分区不会更改。

6.3.2.2. 生成重新分配 JSON 文件

将给定主题集的所有分区分配给给定代理集合的最简单方法是使用 kafka-reassign-partitions.sh --generate 命令生成重新分配 JSON 文件。

bin/kafka-reassign-partitions.sh --zookeeper <ZooKeeper> --topics-to-move-json-file <TopicsFile> --broker-list <BrokerList> --generate

<TopicsFile> 是一个 JSON 文件,列出了要移动的主题。它具有以下结构:

{
  "version": 1,
  "topics": [
    <TopicObjects>
  ]
}

其中 <TopicObjects> 是一个以逗号分隔的对象列表,例如:

{
  "topic": <TopicName>
}

例如,将 topic-atopic-b 的所有分区移动到代理 47

bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to-move-json-file topics-to-be-moved.json --broker-list 4,7 --generate

其中 topics-to-be-moved.json 包含内容:

{
  "version": 1,
  "topics": [
    { "topic": "topic-a"},
    { "topic": "topic-b"}
  ]
}
6.3.2.3. 手动创建重新分配 JSON 文件

如果要移动特定的分区,可以手动创建重新分配 JSON 文件。

6.3.3. 重新分配节流

重新分配分区可能是一个缓慢的过程,因为它可能需要在代理之间移动大量数据。为避免这会对客户端造成负面影响,可以对重新分配进行 限流。使用节流可能意味着重新分配需要更长的时间。如果限流太低,新分配的代理将无法与正在发布的记录保持同步,并且重新分配永远不会完成。如果限流太高,客户端就会受到影响。例如,对于制作者而言,这可能会比等待确认的正常延迟更高。对于消费者而言,这可能会因为轮询之间延迟较高而导致吞吐量下降。

6.3.4. 扩展 Kafka 集群

这个步骤描述了如何在 Kafka 集群中增加代理数量。

先决条件

  • 现有的 Kafka 集群。
  • 安装了 AMQ 代理的新机器。
  • 重新分配 JSON 文件,说明在扩大的集群中如何将分区重新分配给代理。

流程

  1. 使用与集群中的其他代理相同的设置创建新代理的配置文件,但 broker.id 应该是一个尚未被其他代理使用的数字。
  2. 启动新的 Kafka 代理,将您在上一步中创建的配置文件作为参数传递给 kafka-server-start.sh 脚本:

    su - kafka
    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  3. 验证 Kafka 代理正在运行。

    jcmd | grep Kafka
  4. 为每个新代理重复上述步骤。
  5. 使用 kafka-reassign-partitions.sh 命令行工具执行分区重新分配。

    kafka-reassign-partitions.sh --zookeeper <ZooKeeperHostAndPort> --reassignment-json-file <ReassignmentJsonFile> --execute

    如果您要节流复制,您还可以使用每秒字节数(以字节为单位)传递 --throttle 选项。例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --throttle 5000000 --execute

    此命令将显示两个重新分配 JSON 对象:第一个记录了正在移动的分区的当前分配。您应该将其保存到文件中,以便稍后需要恢复重新分配。第二个 JSON 对象是您在重新分配 JSON 文件中传递的目标重新分配。

  6. 如果您需要在重新分配期间更改节流,您可以使用具有不同节流率的同一命令行。例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --throttle 10000000 --execute
  7. 使用 kafka-reassign-partitions.sh 命令行工具定期验证重新分配是否已完成。这与上一步中的命令相同,但使用 --verify 选项而不是 --execute 选项。

    kafka-reassign-partitions.sh --zookeeper <ZooKeeperHostAndPort> --reassignment-json-file <ReassignmentJsonFile> --verify

    例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --verify
  8. --verify 命令报告每个分区成功完成时,重新分配已完成。最后的 --verify 也会产生删除任何重新分配节的效果。现在,如果您保存了 JSON,将分配还原到其原始代理中,您可以删除还原文件。

6.3.5. 缩减 Kafka 集群

其它资源

这个步骤描述了如何减少 Kafka 集群中的代理数量。

先决条件

  • 现有的 Kafka 集群。
  • 一个 重新分配 JSON 文件,说明如何在代理被删除后将分区重新分配给集群中的代理。

流程

  1. 使用 kafka-reassign-partitions.sh 命令行工具执行分区重新分配。

    kafka-reassign-partitions.sh --zookeeper <ZooKeeperHostAndPort> --reassignment-json-file <ReassignmentJsonFile> --execute

    如果您要节流复制,您还可以使用每秒字节数(以字节为单位)传递 --throttle 选项。例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --throttle 5000000 --execute

    此命令将显示两个重新分配 JSON 对象:第一个记录了正在移动的分区的当前分配。您应该将其保存到文件中,以便稍后需要恢复重新分配。第二个 JSON 对象是您在重新分配 JSON 文件中传递的目标重新分配。

  2. 如果您需要在重新分配期间更改节流,您可以使用具有不同节流率的同一命令行。例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --throttle 10000000 --execute
  3. 使用 kafka-reassign-partitions.sh 命令行工具定期验证重新分配是否已完成。这与上一步中的命令相同,但使用 --verify 选项而不是 --execute 选项。

    kafka-reassign-partitions.sh --zookeeper <ZooKeeperHostAndPort> --reassignment-json-file <ReassignmentJsonFile> --verify

    例如:

    kafka-reassign-partitions.sh --zookeeper zookeeper1:2181 --reassignment-json-file reassignment.json --verify
  4. --verify 命令报告每个分区成功完成时,重新分配已完成。最后的 --verify 也会产生删除任何重新分配节的效果。现在,如果您保存了 JSON,将分配还原到其原始代理中,您可以删除还原文件。
  5. 所有分区重新分配完成后,删除的代理不应对集群中的任何分区负责。您可以通过检查代理 log.dirs 配置参数给出的每个目录来验证这一点。如果代理中的任何日志目录都包含与扩展正则表达式 [a-zA-Z0-9.-]+\.[a-z0-9]+-delete$ 不匹配的目录,则代理仍然有实时分区,且不应停止它。

    您可以执行以下命令检查:

    ls -l <LogDir> | grep -E '^d' | grep -vE '[a-zA-Z0-9.-]+\.[a-z0-9]+-delete$'

    如果上述命令显示任何输出,则代理仍然有实时分区。在这种情况下,重新分配没有完成,或者重新分配 JSON 文件不正确。

  6. 确认代理没有实时分区后,您可以停止它。

    su - kafka
    /opt/kafka/bin/kafka-server-stop.sh
  7. 确认 Kafka 代理已被停止。

    jcmd | grep kafka

6.3.6. 扩展 ZooKeeper 集群

这个步骤描述了如何将服务器(节点)添加到 ZooKeeper 集群。ZooKeeper 的动态重新配置 功能在向上扩展过程中维护一个稳定的 ZooKeeper 集群。

先决条件

  • ZooKeeper 配置文件中启用了动态重新配置(reconfigEnabled=true)。
  • zookeeper 身份验证已启用,您可以使用身份验证机制访问新服务器。

流程

对每个 ZooKeeper 服务器执行以下步骤,一次一个服务器:

  1. 在 ZooKeeper 集群中添加服务器,如 第 3.3 节 “运行多节点 ZooKeeper 集群” 所述,然后启动 ZooKeeper。
  2. 注意新服务器的 IP 地址和配置访问端口。
  3. 为服务器启动一个 zookeeper-shell 会话。从可访问集群的机器中运行以下命令(如果可以访问,这可能是 ZooKeeper 节点或本地机器之一)。

    su - kafka
    /opt/kafka/bin/zookeeper-shell.sh <ip-address>:<zk-port>
  4. 在 shell 会话中,在运行 ZooKeeper 节点的情况下,输入以下行,将新服务器作为投票成员添加到仲裁中:

    reconfig -add server.<positive-id> = <address1>:<port1>:<port2>[:role];[<client-port-address>:]<client-port>

    例如:

    reconfig -add server.4=172.17.0.4:2888:3888:participant;172.17.0.4:2181

    其中 <positive-id> 是新服务器 ID 4

    对于两个端口,<port1> 2888 用于 ZooKeeper 服务器之间的通信,<port2> 3888 则用于领导选举机制。

    新配置传播到 ZooKeeper 群集中的其他服务器;新服务器现在是仲裁的完整成员。

  5. 对您要添加的其他服务器重复第 1-4 步。

6.3.7. 缩减 ZooKeeper 集群

这个步骤描述了如何从 ZooKeeper 集群中删除服务器(节点)。ZooKeeper 的动态重新配置 功能在缩减过程中维护一个稳定的 ZooKeeper 集群。

先决条件

  • ZooKeeper 配置文件中启用了动态重新配置(reconfigEnabled=true)。
  • zookeeper 身份验证已启用,您可以使用身份验证机制访问新服务器。

流程

对每个 ZooKeeper 服务器执行以下步骤,一次一个服务器:

  1. 在缩减后将 保留的 其中一台服务器中登录到 zookeeper-shell (例如 server 1)。

    注意

    使用为 ZooKeeper 集群配置的身份验证机制访问服务器。

  2. 移除服务器,如 server 5。

    reconfig -remove 5
  3. 取消激活您删除的服务器。
  4. 重复步骤 1-3 以减少集群大小。

第 7 章 使用 JMX 监控集群

zookeeper、Kafka 代理、Kafka Connect 和 Kafka 客户端都使用 Java 管理扩展( JMX)公开管理信息。大多数管理信息采用指标形式,可用于监控 Kafka 集群的条件和性能。与其他 Java 应用程序一样,Kafka 通过受管 Bean 或 MBeans 提供这些管理信息。

JMX 在 JVM(Java 虚拟机)的级别上工作。要获取管理信息,外部工具可以连接到运行 ZooKeeper 和 Kafka 代理等的 JVM。默认情况下,只有同一计算机上的工具和以与 JVM 相同的用户运行的工具才能连接。

注意

ZooKeeper 的管理信息在此未记录。您可以在 JConsole 中查看 ZooKeeper 指标。如需更多信息,请参阅使用 JConsole 监控

7.1. JMX 配置选项

您可以使用 JVM 系统属性配置 JMX。由 AMQ Streams 提供的脚本(bin/kafka-server-start.shbin/connect-distributed.sh 等)使用 KAFKA_JMX_OPTS 环境变量来设置这些系统属性。配置 JMX 的系统属性相同,即使 Kafka 制作者、使用者和流应用程序通常以不同的方式启动 JVM。

7.2. 禁用 JMX 代理

您可以通过禁用 AMQ Streams 组件的 JMX 代理来防止本地 JMX 工具连接到 JVM(例如出于合规性原因)。以下流程解释了如何为 Kafka 代理禁用 JMX 代理。

流程

  1. 使用 KAFKA_JMX_OPTS 环境变量将 com.sun.management.jmxremote 设置为 false

    export KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote=false
    bin/kafka-server-start.sh
  2. 启动 JVM。

7.3. 从其他机器连接到 JVM

您可以通过配置 JMX 代理侦听的端口,从其他计算机连接 JVM。这是不安全的,因为它允许 JMX 工具从任何位置进行连接,而无需身份验证。

流程

  1. 使用 KAFKA_JMX_OPTS 环境变量设置 -Dcom.sun.management.jmxremote.port=<port>。对于 <port>,输入您希望 Kafka 代理侦听 JMX 连接的端口名称。

    export KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote=true
      -Dcom.sun.management.jmxremote.port=<port>
      -Dcom.sun.management.jmxremote.authenticate=false
      -Dcom.sun.management.jmxremote.ssl=false"
    bin/kafka-server-start.sh
  2. 启动 JVM。
重要

建议您配置身份验证和 SSL,以确保远程 JMX 连接安全。有关执行此操作所需的系统属性的更多信息,请参阅 JMX 文档

7.4. 使用 JConsole 监控

JConsole 工具随 Java 开发工具包(JDK)一起分发。您可以使用 JConsole 连接到本地或远程 JVM,并从 Java 应用发现和显示管理信息。如果使用 JConsole 连接到本地 JVM,则 JVM 进程的名称与 AMQ Streams 的不同组件对应。

表 7.1. AMQ Streams 组件的 JVM 进程
AMQ Streams 组件JVM 进程

ZooKeeper

org.apache.zookeeper.server.quorum.QuorumPeerMain

Kafka 代理

kafka.Kafka

Kafka Connect 独立

org.apache.kafka.connect.cli.ConnectStandalone

Kafka Connect 分布式

org.apache.kafka.connect.cli.ConnectDistributed

Kafka 制作者、使用者或 Streams 应用程序

包含应用的 main 方法的类名称。

在使用 JConsole 连接到远程 JVM 时,请使用适当的主机名和 JMX 端口。

许多其他工具和监控产品可用于利用 JMX 获取指标,并根据这些指标提供监控和警报。有关这些工具,请参阅产品文档。

7.5. 重要的 Kafka 代理指标

Kafka 提供很多 MBean 来监控 Kafka 集群中代理的性能。这些适用于单个代理,而不是整个集群。

下表显示了将这些代理级别 MBean 整理到服务器、网络、日志记录和控制器指标中的选择。

7.5.1. Kafka 服务器指标

下表显示了报告 Kafka 服务器信息的一系列指标。

表 7.2. Kafka 服务器的指标
指标MBean描述预期值

每秒 中的消息

kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec

代理使用各个消息的速率。

大约与集群中的其他代理相同。

字节数(以每秒为单位)

kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec

代理使用生产者发送数据的速率。

大约与集群中的其他代理相同。

复制字节(以每秒为单位)

kafka.server:type=BrokerTopicMetrics,name=ReplicationBytesInPerSec

后续代理使用从其他代理发送的数据的频率。

不适用

每秒字节数

kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec

使用者从代理获取和读取数据的速率。

不适用

每秒复制字节数

kafka.server:type=BrokerTopicMetrics,name=ReplicationBytesOutPerSec

从代理将数据发送到其他代理的速度。这个指标可用于监控代理是否为一组分区的领导者。

不适用

复制式分区

kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions

在后续副本中未完全复制的分区数量。

最小 ISR 分区数

kafka.server:type=ReplicaManager,name=UnderMinIsrPartitionCount

最小 In-Sync Replica(ISR)计数下的分区数量。ISR 计数表示与领导(leader)同步的副本集合。

分区数

kafka.server:type=ReplicaManager,name=PartitionCount

代理中的分区数量。

几乎与其他代理比较。

领导机数量

kafka.server:type=ReplicaManager,name=LeaderCount

此代理作为领导的副本数。

大约与集群中的其他代理相同。

ISR 每秒缩小一次

kafka.server:type=ReplicaManager,name=IsrShrinksPerSec

代理中的 ISR 数量下降率

ISR 每秒扩展次数

kafka.server:type=ReplicaManager,name=IsrExpandsPerSec

代理中的 ISR 数量增加的频率。

最大滞后

kafka.server:type=ReplicaFetcherManager,name=MaxLag,clientId=Replica

领导副本和后续副本收到消息的时间上限。

与生成请求的最大批处理大小成比例。

生产者清除请求

kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Produce

生产者清除中的发送请求数。

不适用

获取清除请求

kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Fetch

获取清除中的获取请求数。

不适用

请求处理程序平均空闲百分比

kafka.server:type=KafkaRequestHandlerPool,name=RequestHandlerAvgIdlePercent

表示请求处理程序(IO)线程没有使用的时间百分比。

较低的值表示代理的工作负载较高。

请求(请求免于节流)

kafka.server:type=Request

免于节流的请求数。

不适用

zookeeper 请求延迟(毫秒)

kafka.server:type=ZooKeeperClientMetrics,name=ZooKeeperRequestLatencyMs

代理的 ZooKeeper 请求延迟,以毫秒为单位。

不适用

zookeeper 会话状态

kafka.server:type=SessionExpireListener,name=SessionState

代理与 ZooKeeper 的连接状态。

已连接

7.5.2. Kafka 网络指标

下表显示了报告请求相关信息的一系列指标。

指标MBean描述预期值

每秒请求数

kafka.network:type=RequestMetrics,name=RequestsPerSec,request={Produce|FetchConsumer|FetchFollower}

针对每秒请求类型发出的请求总数。ProduceFetchConsumerFetchFollower 请求类型各自都有自己的 MBean。

不适用

请求字节(请求大小,以字节为单位)

kafka.network:type=RequestMetrics,name=RequestBytes,request=([-.\w]+)

为 MBean 名称的 request 属性标识的请求类型发出的请求大小,以字节为单位。RequestBytes 节点下列出了所有可用请求类型的独立 MBean。

不适用

临时内存大小,以字节为单位

kafka.network:type=RequestMetrics,name=TemporaryMemoryBytes,request={Produce|Fetch}

用于转换消息格式和解压缩消息的临时内存量。

不适用

消息转换时间

kafka.network:type=RequestMetrics,name=MessageConversionsTimeMs,request={Produce|Fetch}

转换消息格式花费的时间(毫秒)。

不适用

请求总时间(毫秒)

kafka.network:type=RequestMetrics,name=TotalTimeMs,request={Produce|FetchConsumer|FetchFollower}

处理请求的总时间,以毫秒为单位。

不适用

请求队列时间(毫秒)

kafka.network:type=RequestMetrics,name=RequestQueueTimeMs,request={Produce|FetchConsumer|FetchFollower}

请求当前在队列中花费在 request 属性中指定的请求类型的队列中的时间(毫秒)。

不适用

本地时间(领导本地处理时间)以毫秒为单位

kafka.network:type=RequestMetrics,name=LocalTimeMs,request={Produce|FetchConsumer|FetchFollower}

领导处理请求的时间(毫秒)。

不适用

远程时间(更远程处理时间)以毫秒为单位

kafka.network:type=RequestMetrics,name=RemoteTimeMs,request={Produce|FetchConsumer|FetchFollower}

请求等待后续者的时间长度,以毫秒为单位。RemoteTimeMs 节点下列出了所有可用请求类型的独立 MBean。

不适用

以毫秒为单位的响应队列时间

kafka.network:type=RequestMetrics,name=ResponseQueueTimeMs,request={Produce|FetchConsumer|FetchFollower}

请求在响应队列中等待的时间长度,以毫秒为单位。

不适用

响应发送时间(毫秒)

kafka.network:type=RequestMetrics,name=ResponseSendTimeMs,request={Produce|FetchConsumer|FetchFollower}

发送响应所需的时间(毫秒)。

不适用

网络处理器平均空闲百分比

kafka.network:type=SocketServer,name=NetworkProcessorAvgIdlePercent

网络处理器空闲的平均时间百分比。

零到一之间.

7.5.3. Kafka 日志指标

下表显示了报告有关日志信息的一系列指标。

指标MBean描述预期值

以毫秒为单位记录刷新率和时间

kafka.log:type=LogFlushStats,name=LogFlushRateAndTimeMs

日志数据写入磁盘的速度(以毫秒为单位)。

不适用

离线日志目录数

kafka.log:type=LogManager,name=OfflineLogDirectoryCount

脱机日志目录的数量(例如,硬件故障之后)。

7.5.4. Kafka 控制器指标

下表显示了报告集群控制器信息的一系列指标。

指标MBean描述预期值

活跃控制器计数

kafka.controller:type=KafkaController,name=ActiveControllerCount

指定为控制器的代理数量。

个表示代理是集群的控制器。

领导选举率和时间(毫秒)

kafka.controller:type=ControllerStats,name=LeaderElectionRateAndTimeMs

获取新领导副本的速率。

7.5.5. yammer 指标

显示速率或时间单位的指标作为 Yammer 指标提供。使用 Yammer 指标的 MBean 的类名称前缀为 com.yammer.metrics

yammer 速率指标具有以下属性来监控请求:

  • 数量
  • EventType (Bytes)
  • FifteenMinuteRate
  • RateUnit(Seconds)
  • MeanRate
  • OneMinuteRate
  • FiveMinuteRate

yammer 时间指标具有以下属性来监控请求:

  • Max
  • Min
  • mean
  • StdDev
  • 75/95/98/99/99.9th Percentile

7.6. 制作人 MBeans

Kafka producer 应用程序中将存在以下 MBeans,包括 Kafka Streams 应用程序和 Kafka Connect 与源连接器。

7.6.1. Mbeans 匹配 kafka.producer:type=producer-metrics,client-id=*

这些是在制作者级别上的指标。

属性描述

batch-size-avg

每个请求发送每个分区的平均字节数。

batch-size-max

每个请求发送每个分区的最大字节数。

batch-split-rate

每秒批量分割的平均数量。

batch-split-total

批量分割总数。

buffer-available-bytes

未使用的缓冲内存总量(未分配或可用列表中)。

buffer-total-bytes

客户端可以使用的最大缓冲内存量(无论当前是否正在使用)。

bufferpool-wait-time

追加人等待空间分配的时间占比。

compression-rate-avg

记录批处理的平均压缩率,定义为压缩批处理大小与未压缩大小的平均比率。

connection-close-rate

在窗口中每秒关闭连接。

connection-count

当前活动连接的数量。

connection-creation-rate

在窗口中每秒建立的新连接。

failed-authentication-rate

身份验证失败的连接.

incoming-byte-rate

字节/秒读取所有插槽.

io-ratio

I/O 线程花费 I/O 线程完成 I/O 工作所需的时间。

io-time-ns-avg

每次选择调用的 I/O 平均时长(以纳秒为单位)。

io-wait-ratio

I/O 线程等待的一小部分时间。

io-wait-time-ns-avg

I/O 线程等待套接字准备读或写的平均时长(以纳秒为单位)。

metadata-age

使用的当前制作器元数据的年龄(以秒为单位)。

network-io-rate

每秒所有连接上网络操作(读取或写入)的平均数量。

outgoing-byte-rate

平均每秒发送到所有服务器的传出字节数。

produce-throttle-time-avg

请求的平均时间由代理节流。

produce-throttle-time-max

请求中的最大时间由代理节流。

record-error-rate

记录的平均每秒数发送,导致错误。

record-error-total

发送导致错误的记录总数。

record-queue-time-avg

ms 记录中的平均时间会被批处理在发送缓冲区中。

record-queue-time-max

ms 记录中的最大时间批处理花费在发送缓冲区中。

record-retry-rate

重试记录发送的平均/秒数。

record-retry-total

重试记录的总数发送。

record-send-rate

每秒发送的记录平均数量。

record-send-total

发送的记录总数。

record-size-avg

平均记录大小。

record-size-max

最大记录大小。

records-per-request-avg

每个请求的平均记录数。

request-latency-avg

ms 的平均请求延迟。

request-latency-max

ms 中的最大请求延迟。

request-rate

每秒发送的请求平均数量。

request-size-avg

窗口中所有请求的平均大小。

request-size-max

窗口中发送的任何请求的最大大小。

requests-in-flight

当前等待响应的运行中请求数。

response-rate

每秒收到的回复数。

select-rate

I/O 层检查新 I/O 每秒执行的次数。

successful-authentication-rate

使用 SASL 或 SSL 成功验证的连接.

wait-threads

用户线程数阻止等待缓冲区内存来排队其记录。

7.6.2. Mbeans 匹配 kafka.producer:type=producer-metrics,client-id=*,node-id=*

这些是在制作者级别有关与每个代理连接的指标。

属性描述

incoming-byte-rate

节点每秒收到的平均响应数。

outgoing-byte-rate

节点每秒发送的平均传出字节数。

request-latency-avg

节点的平均请求延迟 ms。

request-latency-max

节点的最大请求延迟(以 ms 为单位)。

request-rate

节点每秒发送的请求数平均每秒数。

request-size-avg

节点窗口中所有请求的平均大小。

request-size-max

在窗口中为节点发送的最大请求大小。

response-rate

为节点每秒发送的响应数。

7.6.3. Mbeans 匹配 kafka.producer:type=producer-topic-metrics,client-id=*,topic=*

这些是生产者将消息发送到的主题级别的指标。

属性描述

byte-rate

主题每秒发送的平均字节数。

byte-total

为主题发送的字节总数。

compression-rate

个主题的平均压缩记录率,定义为压缩批处理大小与未压缩大小的平均比率。

record-error-rate

记录的平均每秒数发送,导致一个主题出现错误。

record-error-total

发送的记录总数,导致某个主题出现错误。

record-retry-rate

为主题发送每秒平均重试记录数。

record-retry-total

为主题发送的重试记录总数。

record-send-rate

对于一个主题,每秒发送的记录平均数量。

record-send-total

为某个主题发送的记录总数。

7.7. 消费者 MBeans

Kafka 消费者应用程序中将存在以下 MBeans,包括 Kafka Streams 应用程序和 Kafka Connect with sink 连接器。

7.7.1. Mbeans 匹配 kafka.consumer:type=consumer-metrics,client-id=*

这些指标在使用者级别上。

属性描述

connection-close-rate

在窗口中每秒关闭连接。

connection-count

当前活动连接的数量。

connection-creation-rate

在窗口中每秒建立的新连接。

failed-authentication-rate

身份验证失败的连接.

incoming-byte-rate

字节/秒读取所有插槽.

io-ratio

I/O 线程花费 I/O 线程完成 I/O 工作所需的时间。

io-time-ns-avg

每次选择调用的 I/O 平均时长(以纳秒为单位)。

io-wait-ratio

I/O 线程等待的一小部分时间。

io-wait-time-ns-avg

I/O 线程等待套接字准备读或写的平均时长(以纳秒为单位)。

network-io-rate

每秒所有连接上网络操作(读取或写入)的平均数量。

outgoing-byte-rate

平均每秒发送到所有服务器的传出字节数。

request-rate

每秒发送的请求平均数量。

request-size-avg

窗口中所有请求的平均大小。

request-size-max

窗口中发送的任何请求的最大大小。

response-rate

每秒收到的回复数。

select-rate

I/O 层检查新 I/O 每秒执行的次数。

successful-authentication-rate

使用 SASL 或 SSL 成功验证的连接.

7.7.2. Mbeans 匹配 kafka.consumer:type=consumer-metrics,client-id=*,node-id=*

这些是在消费者级别有关每个代理连接的指标。

属性描述

incoming-byte-rate

节点每秒收到的平均响应数。

outgoing-byte-rate

节点每秒发送的平均传出字节数。

request-latency-avg

节点的平均请求延迟 ms。

request-latency-max

节点的最大请求延迟(以 ms 为单位)。

request-rate

节点每秒发送的请求数平均每秒数。

request-size-avg

节点窗口中所有请求的平均大小。

request-size-max

在窗口中为节点发送的最大请求大小。

response-rate

为节点每秒发送的响应数。

7.7.3. Mbeans 匹配 kafka.consumer:type=consumer-coordinator-metrics,client-id=*

这些指标在消费者级别有关使用者组的指标。

属性描述

assigned-partitions

目前分配给这个消费者的分区数量。

commit-latency-avg

提交请求的平均时间。

commit-latency-max

提交请求所用的最长时间。

commit-rate

每秒提交调用数。

heartbeat-rate

平均每秒心跳数。

heartbeat-response-time-max

收到心跳请求响应所需的时间上限。

join-rate

每秒组加入数。

join-time-avg

重新加入组的平均时间。

join-time-max

重新加入组所用的最长时间。

last-heartbeat-seconds-ago

上一控制器心跳起的秒数。

sync-rate

每秒组同步数。

sync-time-avg

组同步的平均时间。

sync-time-max

组同步花费的最大时间。

7.7.4. Mbeans 匹配 kafka.consumer:type=consumer-fetch-manager-metrics,client-id=*

这些指标在消费者级别上有关使用者的获取者的指标。

属性描述

bytes-consumed-rate

每秒消耗的平均字节数。

bytes-consumed-total

使用的字节总数。

fetch-latency-avg

获取请求的平均时间。

fetch-latency-max

任何获取请求所花费的最大时间。

fetch-rate

每秒获取请求数。

fetch-size-avg

每个请求获取的平均字节数。

fetch-size-max

每个请求获取的最大字节数。

fetch-throttle-time-avg

毫秒的平均限时时间。

fetch-throttle-time-max

ms 中最大节流时间。

fetch-total

获取请求的总数。

records-consumed-rate

每秒消耗的记录平均数量。

records-consumed-total

使用的记录总数。

records-lag-max

此窗口中任何分区的记录数量上限。

records-lead-min

此窗口中任何分区的记录数量最少的前期信息。

records-per-request-avg

每个请求中的记录平均数量。

7.7.5. Mbeans 匹配 kafka.consumer:type=consumer-fetch-manager-metrics,client-id=*,topic=*

这些是关于消费者提取器的主题级别的指标。

属性描述

bytes-consumed-rate

主题每秒使用的平均字节数。

bytes-consumed-total

主题所消耗的字节总数。

fetch-size-avg

主题的每个请求获取的平均字节数。

fetch-size-max

每个请求为主题获取的最大字节数。

records-consumed-rate

个主题每秒使用的平均记录数。

records-consumed-total

某个主题所用的记录总数。

records-per-request-avg

每个请求中主题的平均记录数。

7.7.6. Mbeans 匹配 kafka.consumer:type=consumer-fetch-manager-metrics,client-id=*,topic=*,partition=*

这些是关于使用者获取器的分区级别的指标。

属性描述

preferred-read-replica

分区的当前读取副本;如果从领导机读取,则为 -1。

records-lag

分区的最新滞后。

records-lag-avg

分区的平均滞后情况。

records-lag-max

分区的最大滞后。

records-lead

分区的最新领导点.

records-lead-avg

分区的平均领导点.

records-lead-min

分区的最小领导.

7.8. Kafka Connect MBeans

注意

7.8.1. Mbeans 匹配 kafka.connect:type=connect-metrics,client-id=*

这些是连接级别的指标。

属性描述

connection-close-rate

在窗口中每秒关闭连接。

connection-count

当前活动连接的数量。

connection-creation-rate

在窗口中每秒建立的新连接。

failed-authentication-rate

身份验证失败的连接.

incoming-byte-rate

字节/秒读取所有插槽.

io-ratio

I/O 线程花费 I/O 线程完成 I/O 工作所需的时间。

io-time-ns-avg

每次选择调用的 I/O 平均时长(以纳秒为单位)。

io-wait-ratio

I/O 线程等待的一小部分时间。

io-wait-time-ns-avg

I/O 线程等待套接字准备读或写的平均时长(以纳秒为单位)。

network-io-rate

每秒所有连接上网络操作(读取或写入)的平均数量。

outgoing-byte-rate

平均每秒发送到所有服务器的传出字节数。

request-rate

每秒发送的请求平均数量。

request-size-avg

窗口中所有请求的平均大小。

request-size-max

窗口中发送的任何请求的最大大小。

response-rate

每秒收到的回复数。

select-rate

I/O 层检查新 I/O 每秒执行的次数。

successful-authentication-rate

使用 SASL 或 SSL 成功验证的连接.

7.8.2. Mbeans 匹配 kafka.connect:type=connect-metrics,client-id=*,node-id=*

这些是连接每个代理的相关指标。

属性描述

incoming-byte-rate

节点每秒收到的平均响应数。

outgoing-byte-rate

节点每秒发送的平均传出字节数。

request-latency-avg

节点的平均请求延迟 ms。

request-latency-max

节点的最大请求延迟(以 ms 为单位)。

request-rate

节点每秒发送的请求数平均每秒数。

request-size-avg

节点窗口中所有请求的平均大小。

request-size-max

在窗口中为节点发送的最大请求大小。

response-rate

为节点每秒发送的响应数。

7.8.3. Mbeans 匹配 kafka.connect:type=connect-worker-metrics

这些是连接级别的指标。

属性描述

connector-count

在此 worker 中运行的连接器数量。

connector-startup-attempts-total

此 worker 尝试的连接器启动的总数。

connector-startup-failure-percentage

此 worker 连接器的平均百分比启动失败。

connector-startup-failure-total

启动失败的连接器的总数。

connector-startup-success-percentage

此工作程序连接器的平均百分比启动成功。

connector-startup-success-total

启动的连接器总数。

task-count

在这个 worker 中运行的任务数量。

task-startup-attempts-total

此 worker 尝试的任务启动总数。

task-startup-failure-percentage

此 worker 任务的平均百分比启动失败。

task-startup-failure-total

任务总数启动失败。

task-startup-success-percentage

此工作程序任务的平均百分比都会启动。

task-startup-success-total

成功启动的任务总数。

7.8.4. Mbeans 匹配 kafka.connect:type=connect-worker-rebalance-metrics

属性描述

completed-rebalances-total

此 worker 完成重新平衡的总数。

connect-protocol

此集群使用的连接协议。

epoch

此 worker 的 epoch 或 generation 数量。

leader-name

组 leader 的名称。

rebalance-avg-time-ms

此 worker 重新平衡所需的平均时间(毫秒)。

rebalance-max-time-ms

此 worker 重新平衡的最大时间,以毫秒为单位。

重新平衡

此 worker 当前是否重新平衡。

time-since-last-rebalance-ms

此 worker 完成最新重新平衡后的时间以毫秒为单位。

7.8.5. Mbeans 匹配 kafka.connect:type=connector-metrics,connector=*

属性描述

connector-class

连接器类的名称。

connector-type

连接器的类型。其中一个 'source' 或 'sink'。

connector-version

连接器类的版本,如连接器报告。

status

连接器的状态。'unassigned'、'running'、'paused'、'failed' 或 'destroyed' 中的一个。

7.8.6. Mbeans 匹配 kafka.connect:type=connector-task-metrics,connector=*,task=*

属性描述

batch-size-avg

连接器处理的批处理的平均大小。

batch-size-max

连接器处理的批处理的最大大小。

offset-commit-avg-time-ms

此任务提交偏移所需的平均时间(以毫秒为单位)。

offset-commit-failure-percentage

此任务偏移提交的平均百分比尝试失败。

offset-commit-max-time-ms

此任务提交偏移所花费的最长时间,以毫秒为单位。

offset-commit-success-percentage

此任务偏移提交的平均百分比尝试成功。

pause-ratio

此任务花费在 pause 状态的时间占比。

running-ratio

此任务花费在运行中状态的时间占比。

status

连接器任务的状态。'unassigned'、'running'、'paused'、'failed' 或 'destroyed' 中的一个。

7.8.7. Mbeans 匹配 kafka.connect:type=sink-task-metrics,connector=*,task=*

属性描述

offset-commit-completion-rate

成功完成的每秒的平均误差提交完成数。

offset-commit-completion-total

成功完成的偏移提交完成总数。

offset-commit-seq-no

用于偏移提交的当前序列号。

offset-commit-skip-rate

收到过延迟并跳过/忽略的每秒的平均误差提交完成数。

offset-commit-skip-total

收到过延迟并跳过/忽略的误差提交完成总数。

partition-count

分配给此任务的主题分区数量,属于这个 worker 中命名的 sink 连接器。

put-batch-avg-time-ms

该任务放置大量 sink 记录所需的平均时间。

put-batch-max-time-ms

该任务放置大量 sink 记录所需的时间上限。

sink-record-active-count

从 Kafka 读取但还没有完全由 sink 任务提交/清空/确认的记录数。

sink-record-active-count-avg

从 Kafka 读取、但尚未完全提交/清空/被 sink 任务批准的记录的平均数量。

sink-record-active-count-max

从 Kafka 读取但尚未完全提交/清空/被 sink 任务批准的最大记录数。

sink-record-lag-max

在 sink 任务的记录数上,用户对于任何主题分区都处于最大的滞后。

sink-record-read-rate

这个任务从 Kafka 读取的平均记录数,属于这个 worker 中命名的 sink 连接器。这是在应用转换之前。

sink-record-read-total

此任务从 Kafka 读取的记录总数在此 worker 中属于指定的 sink 连接器,因为任务上次重启。

sink-record-send-rate

转换和发送/输出到此 worker 中属于指定 sink 连接器的任务的平均每秒记录输出数。这是应用转换后,并排除任何被转换过滤出的记录。

sink-record-send-total

此 worker 中属于指定 sink 连接器的转换和发送/输出的记录总数,因为任务上次重启。

7.8.8. Mbeans 匹配 kafka.connect:type=source-task-metrics,connector=*,task=*

属性描述

poll-batch-avg-time-ms

该任务花费的平均时间(毫秒为单位)轮询一系列源记录。

poll-batch-max-time-ms

该任务为一系列源记录轮询所花费的最长时间,以毫秒为单位。

source-record-active-count

此任务生成的记录数,但尚未完全写入 Kafka。

source-record-active-count-avg

该任务产生但尚未完全写入 Kafka 的平均记录数。

source-record-active-count-max

此任务生成的但尚未完全写入 Kafka 的最大记录数。

source-record-poll-rate

此任务从属于此 worker 中指定源连接器的任务所生成/推断(转换前)的每秒的平均记录数。

source-record-poll-total

此任务属于此 worker 中指定源连接器的记录总数,在转换前生成(前转换)。

source-record-write-rate

转换中平均每秒的记录输出,并写入此 worker 中属于指定源连接器的任务的 Kafka。这是应用转换后,并排除任何被转换过滤出的记录。

source-record-write-total

此任务在此 worker 中属于指定源连接器的记录数并写入 Kafka,因为任务上次重启。

7.8.9. Mbeans 匹配 kafka.connect:type=task-error-metrics,connector=*,task=*

属性描述

deadletterqueue-produce-failures

失败写入死信队列的数量。

deadletterqueue-produce-requests

尝试写入死信队列的次数。

last-error-timestamp

此任务上次遇到错误时的 epoch 时间戳。

total-errors-logged

所记录的错误数。

total-record-errors

此任务中的记录处理错误数。

total-record-failures

此任务中的记录处理失败数量。

total-records-skipped

由于错误而跳过的记录数。

total-retries

重试的操作数量。

7.9. Kafka Streams MBeans

注意

Streams 应用程序除这里记录的 生产者和消费者 M Bean 之外 还将包含生产者和消费者 MBean。

7.9.1. Mbeans 匹配 kafka.streams:type=stream-metrics,client-id=*

metrics.recording.level 配置参数是 infodebug 时,会收集这些指标。

属性描述

commit-latency-avg

此线程所有正在运行的任务的平均执行时间(以 ms 为单位)。

commit-latency-max

ms 中用于在此线程的所有运行任务之间提交的最长执行时间。

commit-rate

每秒提交的平均数量。

commit-total

所有任务的提交调用总数。

poll-latency-avg

此线程所有正在运行的任务的平均执行时间(以 ms 为单位)。

poll-latency-max

此线程所有运行任务之间轮询的最大执行时间(以 ms 为单位)。

poll-rate

平均每秒轮询数。

poll-total

所有任务的轮询调用总数。

process-latency-avg

此线程所有正在运行的任务的平均执行时间(以 ms 为单位)。

process-latency-max

此线程所有正在运行的任务的最大执行时间(以 ms 为单位)。

process-rate

每秒进程调用平均数量。

process-total

所有任务的进程调用总数。

punctuate-latency-avg

此线程所有正在运行的任务的平均执行时间(以 ms 为单位)。

punctuate-latency-max

ms 中用于在该线程的所有运行任务之间标点的最大执行时间。

punctuate-rate

平均每秒标点数。

punctuate-total

所有任务的标点调用总数。

skipped-records-rate

平均每秒跳过的记录数。

skipped-records-total

跳过的记录总数。

task-closed-rate

平均每秒关闭的任务数量。

task-closed-total

已关闭的任务总数。

task-created-rate

新创建的任务平均每秒数。

task-created-total

创建的任务总数。

7.9.2. Mbeans 匹配 kafka.streams:type=stream-task-metrics,client-id=*,task-id=*

任务指标.

metrics.recording.level 配置参数是 debug 时,会收集这些指标。

属性描述

commit-latency-avg

此任务的平均提交时间(以 ns 为单位)。

commit-latency-max

此任务的提交时间上限(以 ns 为单位)。

commit-rate

每秒提交调用的平均数量。

commit-total

提交调用的总数。

7.9.3. Mbeans 匹配 kafka.streams:type=stream-processor-node-metrics,client-id=*,task-id=*,processor-node-id=*

处理器节点指标.

metrics.recording.level 配置参数是 debug 时,会收集这些指标。

属性描述

create-latency-avg

平均创建执行时间为 ns。

create-latency-max

创建执行时间上限(以 ns 为单位)。

create-rate

平均每秒创建操作数。

create-total

创建操作的总数,称为.

destroy-latency-avg

平均销毁执行时间(ns)。

destroy-latency-max

最大销毁执行时间(以 ns 为单位)。

destroy-rate

每秒销毁操作平均数量。

destroy-total

称为.

forward-rate

下游平均记录的速度(仅从源节点每秒传输一次)。

forward-total

下游转发的记录总数,仅来自源节点。

process-latency-avg

平均进程执行时间(以 ns 为单位)。

process-latency-max

进程执行时间上限(以 ns 为单位)。

process-rate

每秒处理操作平均数量。

process-total

称为.

punctuate-latency-avg

平均执行时间以 ns 为单位.

punctuate-latency-max

执行时间上限(以 ns 为单位)。

punctuate-rate

每秒标点操作的平均数量。

punctuate-total

标点操作总数,称为.

7.9.4. Mbeans 匹配 kafka.streams:type=stream-[store-scope]-metrics,client-id=*,task-id=*,[store-scope]-id=*

状态存储指标.

metrics.recording.level 配置参数是 debug 时,会收集这些指标。

属性描述

all-latency-avg

以 ns 为单位执行所有操作的平均时间。

all-latency-max

所有操作执行时间上限(以 ns 为单位)。

all-rate

此存储的平均操作率。

all-total

此存储的所有操作调用总数。

delete-latency-avg

平均删除执行时间(以 ns 为单位)。

delete-latency-max

删除执行时间上限(以 ns 为单位)。

delete-rate

此存储的平均删除费率。

delete-total

此存储的删除调用总数。

flush-latency-avg

平均清空执行时间(以 ns 为单位)。

flush-latency-max

最大清空执行时间(以 ns 为单位)。

flush-rate

此商店的平均清空率。

flush-total

此存储的清空调用总数。

get-latency-avg

平均以 ns 为单位获得执行时间。

get-latency-max

最大获取执行时间以 ns 为单位。

get-rate

此商店的平均获取率.

get-total

此商店的 get 调用总数。

put-all-latency-avg

平均放放执行时间(ns)。

put-all-latency-max

最大放置执行时间以 ns 为单位。

e-all-rate

此商店的平均放载率.

put-all-total

此商店的所有呼叫总数。

put-if-absent-latency-avg

平均放置执行时间(以 ns 为单位)。

put-if-absent-latency-max

最大 put-if-absent 执行时间以 ns 为单位。

put-if-absent-rate

此商店的平均放大速率.

put-if-absent-total

此商店的 put-if-absent 调用总数。

put-latency-avg

平均以 ns 为单位放置执行时间.

put-latency-max

最大执行时间以 ns 为单位。

rate-rate

此商店的平均放置率.

最新

此商店的放置调用总数。

range-latency-avg

平均范围执行时间(以 ns 为单位)。

range-latency-max

执行时间上限(以 ns 为单位)。

range-rate

此商店的平均范围速率。

range-total

此存储的范围调用总数。

restore-latency-avg

平均恢复执行时间以 ns 为单位。

restore-latency-max

最长恢复执行时间(以 ns 为单位)。

restore-rate

此存储的平均恢复率。

restore-total

此存储的恢复调用总数。

7.9.5. Mbeans 匹配 kafka.streams:type=stream-record-cache-metrics,client-id=*,task-id=*,record-cache-id=*

记录缓存指标.

metrics.recording.level 配置参数是 debug 时,会收集这些指标。

属性描述

hitRatio-avg

定义的平均缓存命中率,由缓存读取请求的总缓存命中率所定义。

hitRatio-max

最大缓存命中率。

hitRatio-min

最小缓存命中率。

第 8 章 Kafka Connect

Kafka Connect 是一个在 Apache Kafka 和外部系统间流传输数据的工具。它为迁移大量数据提供了框架,同时保持了可扩展性和可靠性。Kafka Connect 通常用于将 Kafka 与您的 Kafka 集群外部的数据库、存储和消息系统集成。

Kafka Connect 使用连接器插件来为不同类型的外部系统实现连接。连接器插件有两种: sink 和 source。sink 连接器数据从 Kafka 到外部系统。源连接器数据从外部系统流传输到 Kafka。

Kafka Connect 能够以独立模式或分布式模式运行。

单机模式
在单机模式下,Kafka Connect 在单一节点上运行,且用户定义的配置从属性文件中读取。
分布式模式
在分布式模式中,Kafka Connect 在一个或多个 worker 节点上运行,工作负载分布在这些节点上。您可以使用 HTTP REST 接口管理连接器及其配置。

8.1. 以独立模式的 Kafka Connect

在单机模式中,Kafka Connect 作为单个进程在单一节点上运行。您可以使用属性文件管理单机模式的配置。

8.1.1. 以独立模式配置 Kafka Connect

要在独立模式下配置 Kafka Connect,编辑 config/connect-standalone.properties 配置文件。以下选项最为重要:

bootstrap.servers
用作到 Kafka 的 bootstrap 连接的 Kafka 代理地址列表。例如: kafka0.my-domain.com:9092,kafka1.my-domain.com:9092,kafka2.my-domain.com:9092
key.converter
用于将消息键转换为 Kafka 格式的类。例如: org.apache.kafka.connect.json.JsonConverter
value.converter
用于将消息有效负载转换为 Kafka 格式的类。例如: org.apache.kafka.connect.json.JsonConverter
offset.storage.file.filename
指定存储偏移数据的文件。

安装目录中提供了 config/connect-standalone.properties 的示例配置文件。有关所有支持的 Kafka Connect 配置选项的完整列表,请参阅 [kafka-connect-configuration-parameters-str]。

连接器插件使用 bootstrap 地址打开与 Kafka 代理的客户端连接。要配置这些连接,请使用前缀为 producer.consumer. 的标准 Kafka 制作者和消费者配置选项。

有关配置 Kafka 生产者和消费者的详情,请参考:

8.1.2. 以独立模式在 Kafka Connect 中配置连接器

您可以使用属性文件在单机模式中为 Kafka Connect 配置连接器插件。大多数配置选项都特定于每个连接器。以下选项适用于所有连接器:

name
连接器的名称,在当前 Kafka Connect 实例中必须是唯一的。
connector.class
连接器插件的类。例如: org.apache.kafka.connect.file.FileStreamSinkConnector
tasks.max
指定连接器可以使用的任务数量上限。任务使连接器能够并行执行任务。连接器可能会创建比指定更少的任务。
key.converter
用于将消息键转换为 Kafka 格式的类。这会覆盖 Kafka Connect 配置设置的默认值。例如: org.apache.kafka.connect.json.JsonConverter
value.converter
用于将消息有效负载转换为 Kafka 格式的类。这会覆盖 Kafka Connect 配置设置的默认值。例如: org.apache.kafka.connect.json.JsonConverter

另外,您必须为 sink 连接器至少设置以下选项之一:

topics
用作输入的主题的逗号分隔列表。
topics.regex
用作输入的主题的 Java 正则表达式。

有关所有其他选项,请查看可用连接器的文档。

AMQ Streams 包括连接器配置文件示例 - 请参阅 AMQ Streams 安装目录中的 config/connect-file-sink.propertiesconfig/connect-file-source.properties

8.1.3. 以独立模式运行 Kafka Connect

这个步骤描述了如何在独立模式下配置和运行 Kafka Connect。

先决条件

  • 已安装并运行的 AMQ Streams} 集群。

流程

  1. 编辑 /opt/kafka/config/connect-standalone.properties Kafka Connect 配置文件并将 bootstrap.server 设置为指向 Kafka 代理。例如:

    bootstrap.servers=kafka0.my-domain.com:9092,kafka1.my-domain.com:9092,kafka2.my-domain.com:9092
  2. 使用 配置文件启动 Kafka Connect 并指定一个或多个连接器配置。

    su - kafka
    /opt/kafka/bin/connect-standalone.sh /opt/kafka/config/connect-standalone.properties connector1.properties
    [connector2.properties ...]
  3. 验证 Kafka Connect 是否正在运行。

       jcmd | grep ConnectStandalone

其它资源

8.2. 以分布式模式进行 Kafka Connect

在分布式模式中,Kafka Connect 在一个或多个 worker 节点上运行,工作负载分布在这些节点上。您可以使用 HTTP REST 接口管理连接器插件及其配置。

8.2.1. 在分布式模式下配置 Kafka Connect

要在分布式模式下配置 Kafka Connect,编辑 config/connect-distributed.properties 配置文件。以下选项最为重要:

bootstrap.servers
用作到 Kafka 的 bootstrap 连接的 Kafka 代理地址列表。例如: kafka0.my-domain.com:9092,kafka1.my-domain.com:9092,kafka2.my-domain.com:9092
key.converter
用于将消息键转换为 Kafka 格式的类。例如: org.apache.kafka.connect.json.JsonConverter
value.converter
用于将消息有效负载转换为 Kafka 格式的类。例如: org.apache.kafka.connect.json.JsonConverter
group.id
分布式 Kafka Connect 集群的名称。这必须是唯一的,且不得与其他消费者组 ID 冲突。默认值为 connect-cluster
config.storage.topic
用于存储连接器配置的 Kafka 主题。默认值为 connect-configs
offset.storage.topic
用于存储偏移的 Kafka 主题。默认值为 connect-offset
status.storage.topic
用于 worker 节点状态的 Kafka 主题。默认值为 connect-status

AMQ Streams 在分布式模式中包括 Kafka Connect 的示例配置文件 - 请参阅 AMQ Streams 安装目录中的 config/connect-distributed.properties

有关所有支持的 Kafka Connect 配置选项的完整列表,请参阅 附录 F, Kafka Connect 配置参数

连接器插件使用 bootstrap 地址打开与 Kafka 代理的客户端连接。要配置这些连接,请使用前缀为 producer.consumer. 的标准 Kafka 制作者和消费者配置选项。

有关配置 Kafka 生产者和消费者的详情,请参考:

8.2.2. 在分布式 Kafka Connect 中配置连接器

HTTP REST 接口

用于分布式 Kafka Connect 的连接器是使用 HTTP REST 接口配置的。REST 接口默认侦听端口 8083。它支持以下端点:

GET /connectors
返回现有连接器列表。
POST /connectors
创建连接器.请求正文必须是带有连接器配置的 JSON 对象。
GET /connectors/<name>
获取有关特定连接器的信息。
GET /connectors/<name>/config
获取特定连接器的配置。
PUT /connectors/<name>/config
更新特定连接器的配置。
GET /connectors/<name>/status
获取特定连接器的状态.
PUT /connectors/<name>/pause
暂停连接器及其所有任务。连接器将停止处理任何消息。
PUT /connectors/<name>/resume
恢复暂停的连接器。
POST /connectors/<name>/restart
如果连接器失败,请重新启动连接器。
DELETE /connectors/<name>
删除连接器.
GET /connector-plugins
获取所有支持的连接器插件的列表。

连接器配置

大多数配置选项都是特定的连接器,并包含在连接器的文档中。以下字段对所有连接器通用:

name
连接器的名称。必须在给定 Kafka Connect 实例中唯一。
connector.class
连接器插件的类。例如 org.apache.kafka.connect.file.FileStreamSinkConnector
tasks.max
此连接器使用的任务数量上限。任务由连接器用于并行工作。Connetors 可以创建比指定的任务更少的任务。
key.converter
用于将消息密钥转换为 Kafka 格式的类。这会覆盖 Kafka Connect 配置设置的默认值。例如: org.apache.kafka.connect.json.JsonConverter
value.converter
用于将消息有效负载转换为 Kafka 格式的类。这会覆盖 Kafka Connect 配置设置的默认值。例如: org.apache.kafka.connect.json.JsonConverter

另外,必须为 sink 连接器设置以下选项之一:

topics
用作输入的主题的逗号分隔列表。
topics.regex
用作输入的主题的 Java 正则表达式。

有关所有其他选项,请查看特定连接器的文档。

AMQ Streams 包括连接器配置文件示例。您可以在 AMQ Streams 安装目录中的 config/connect-file-sink.propertiesconfig/connect-file-source.properties 中找到它们。

8.2.3. 运行分布式 Kafka 连接

这个步骤描述了如何在分布式模式下配置和运行 Kafka Connect。

先决条件

  • 已安装并运行的 AMQ Streams 集群。

运行集群

  1. 编辑所有 Kafka Connect worker 节点上的 /opt/kafka/config/connect-distributed.properties Kafka Connect 配置文件。

    • bootstrap.server 选项设置为指向 Kafka 代理。
    • 设置 group.id 选项。
    • 设置 config.storage.topic 选项。
    • 设置 offset.storage.topic 选项。
    • 设置 status.storage.topic 选项。

      例如:

      bootstrap.servers=kafka0.my-domain.com:9092,kafka1.my-domain.com:9092,kafka2.my-domain.com:9092
      group.id=my-group-id
      config.storage.topic=my-group-id-configs
      offset.storage.topic=my-group-id-offsets
      status.storage.topic=my-group-id-status
  2. 使用所有 Kafka Connect 节点上的 /opt/kafka/config/connect-distributed.properties 配置文件启动 Kafka Connect worker。

    su - kafka
    /opt/kafka/bin/connect-distributed.sh /opt/kafka/config/connect-distributed.properties
  3. 验证 Kafka Connect 是否正在运行。

    jcmd | grep ConnectDistributed

其它资源

8.2.4. 创建连接器

这个步骤描述了如何使用 Kafka Connect REST API 在分布式模式下创建连接器插件以用于 Kafka Connect。

先决条件

  • 以分布式模式运行的 Kafka Connect 安装。

流程

  1. 使用连接器配置准备 JSON 有效负载。例如:

    {
      "name": "my-connector",
      "config": {
      "connector.class": "org.apache.kafka.connect.file.FileStreamSinkConnector",
        "tasks.max": "1",
        "topics": "my-topic-1,my-topic-2",
        "file": "/tmp/output-file.txt"
      }
    }
  2. 发送 POST 请求到 <KafkaConnectAddress>:8083/connectors 以创建连接器。以下示例使用 curl

    curl -X POST -H "Content-Type: application/json" --data @sink-connector.json http://connect0.my-domain.com:8083/connectors
  3. 通过向 <KafkaConnectAddress>:8083/connectors 发送 GET 请求来验证连接器是否已部署。以下示例使用 curl

    curl http://connect0.my-domain.com:8083/connectors

8.2.5. 删除连接器

这个步骤描述了如何使用 Kafka Connect REST API 在分布式模式中从 Kafka Connect 中删除连接器插件。

先决条件

  • 以分布式模式运行的 Kafka Connect 安装。

删除连接器

  1. 通过向 <KafkaConnectAddress>:8083/connectors/<ConnectorName> 发送 GET 请求来验证连接器是否存在。以下示例使用 curl

    curl http://connect0.my-domain.com:8083/connectors
  2. 要删除连接器,将 DELETE 请求发送到 <KafkaConnectAddress>:8083/connectors。以下示例使用 curl

    curl -X DELETE http://connect0.my-domain.com:8083/connectors/my-connector
  3. 通过向 <KafkaConnectAddress>:8083/connectors 发送 GET 请求来验证连接器是否已被删除。以下示例使用 curl

    curl http://connect0.my-domain.com:8083/connectors

8.3. 连接器插件

以下连接器插件包含在 AMQ Streams 中:

FileStreamSink 从 Kafka 主题读取数据并将数据写入文件中。

FileStreamSource 从文件中读取数据,并将数据发送到 Kafka 主题。

如果需要,您可以添加更多连接器插件。Kafka Connect 会在启动时搜索并运行其他连接器插件。要定义 kafka Connect 搜索插件的路径,设置 plugin.path configuration 选项:

plugin.path=/opt/kafka/connector-plugins,/opt/connectors

plugin.path 配置选项可以包含用逗号分开的路径列表。

当以分布式模式运行 Kafka Connect 时,插件必须在所有 worker 节点上可用。

8.4. 添加连接器插件

此流程演示了如何添加其他连接器插件。

先决条件

  • 已安装并运行的 AMQ Streams 集群。

流程

  1. 创建 /opt/kafka/connector-plugins 目录。

    su - kafka
    mkdir /opt/kafka/connector-plugins
  2. 编辑 /opt/kafka/config/connect-standalone.properties/opt/kafka/config/connect-distributed.properties Kafka Connect 配置文件,并将 plugin.path 选项设置为 /opt/kafka/connector-plugins。例如:

    plugin.path=/opt/kafka/connector-plugins
  3. 将连接器插件复制到 /opt/kafka/connector-plugins
  4. 启动或重启 Kafka Connect worker。

其它资源

第 9 章 使用带有 MirrorMaker 2.0 的 AMQ Streams

MirrorMaker 2.0 用于在数据中心内或之间的两个或多个活跃 Kafka 集群之间复制数据。

集群间的数据复制支持以下条件:

  • 发生系统故障时恢复数据
  • 聚合数据以进行分析
  • 对特定集群的数据访问的限制
  • 在特定位置置备数据以缩短延迟
注意

MirrorMaker 2.0 具有以前版本的 MirrorMaker 不支持的功能。但是,您可以将 MirrorMaker 2.0 配置为在旧模式中使用

9.1. MirrorMaker 2.0 数据复制

MirrorMaker 2.0 使用源 Kafka 集群的信息,并将其写入目标 Kafka 集群。

MirrorMaker 2.0 使用:

  • 源集群配置以使用源集群的数据
  • 将数据输出到目标集群的目标集群配置

MirrorMaker 2.0 基于 Kafka Connect 框架,即管理集群间数据传输的 连接器。MirrorMaker 2.0 MirrorSourceConnector 将源集群中的主题复制到目标集群。

将数据从一个集群 镜像 到另一个集群的过程是异步的。建议的模式是让信息与源 Kafka 集群一起生成,然后远程使用与目标 Kafka 集群类似的信息。

MirrorMaker 2.0 可以用于多个源集群。

图 9.1. 在两个集群间复制

MirrorMaker 2.0 replication

默认情况下,每 10 分钟检查源集群中的新主题。您可以通过在源连接器配置中添加 refresh.topics.interval.seconds 来更改频率。但是,增加操作的频率可能会影响整体性能。

9.2. 集群配置

您可以在 主动/ 被动或主动/主动 集群配置中使用 MirrorMaker 2.0。

  • 主动/主动 配置中,两个集群都处于活动状态并同时提供相同的数据,如果您想在不同的地理位置在本地提供相同的数据,这很有用。
  • 主动/被动 配置中,来自主动/被动群集的数据复制到被动群集中,该群集仍处于备用状态,例如,在发生系统故障时进行数据恢复。

预计生产者和消费者只能连接到活跃的集群。

每个目标目的地都需要一个 MirrorMaker 2.0 集群。

9.2.1. 双向复制(主动/主动)

MirrorMaker 2.0 架构支持 主动/主动 集群配置中的双向复制。

每个集群使用 和远程 主题的概念复制其他集群的数据。由于每个集群中存储了相同的主题,因此 MirrorMaker 2.0 会自动重命名远程主题来代表源集群。原始集群的名称前面是主题名称的前面。

图 9.2. 主题重命名

MirrorMaker 2.0 bidirectional architecture

通过标记原始集群,主题不会复制到该集群中。

在配置需要数据聚合的架构时,通过 远程 主题复制的概念非常有用。消费者可以订阅同一群集内的源和远程主题,无需单独的聚合集群。

9.2.2. 单向复制(主动/被动)

MirrorMaker 2.0 架构支持 主动/被动 集群配置中的单向复制。

您可以使用 主动/被动 集群配置进行备份,或将数据迁移到另一个集群。在这种情况下,您可能不希望自动重命名远程主题。

您可以通过在源连接器配置中添加 IdentityReplicationPolicy 来覆盖自动重命名。应用此配置后,主题会保留其原始名称。

9.2.3. 主题配置同步

主题配置会在源集群和目标集群之间自动同步。通过同步配置属性,可以减少重新平衡的需求。

9.2.4. 数据完整性

MirrorMaker 2.0 监控源主题,并将配置更改传播到远程主题,检查并创建缺少的分区。只有 MirrorMaker 2.0 可以写入远程主题。

9.2.5. 偏移跟踪

MirrorMaker 2.0 使用 内部主题 跟踪消费者组的偏移量。

  • 偏移同步 主题映射从记录元数据中复制主题分区的来源和目标偏移
  • checkpoint 主题映射源和目标集群中为各个消费者组中复制主题分区的最后提交偏移

检查点 主题的偏移会通过配置预先确定的时间间隔进行跟踪。这两个主题都允许从故障转移上的正确偏移位置完全恢复复制。

MirrorMaker 2.0 使用其 MirrorCheckpointConnector 发出 检查点 进行偏移跟踪。

9.2.6. 同步消费者组偏移

__consumer_offsets 主题存储每个消费者组提交的偏移信息。偏移同步定期将源集群使用者组的使用者偏移量传输到目标集群的使用者偏移主题。

偏移同步在 主动/被动 配置中特别有用。如果活跃集群停机,使用者应用可以切换到被动(standby)集群,并从最近传输的偏移位置获取。

使用主题偏移同步:

  • 通过将 sync.group.offsets.enabled 添加到 checkpoint 连接器配置并设置为 true 来启用同步。默认情况下禁用同步。
  • IdentityReplicationPolicy 添加到源和检查点连接器配置中,以便目标集群中的主题保留其原始名称。

要进行主题偏移同步,目标集群中的消费者组无法使用与源集群中的组相同的 id。

如果启用,则定期与源集群进行偏移同步。您可以通过在检查点连接器配置中添加 sync.group.offsets.interval.secondsemit.checkpoints.interval.seconds 来更改频率。属性指定消费者组偏移同步的频率(以秒为单位),以及发出用于偏移跟踪的检查点频率。两个属性的默认值都是 60 秒。您还可以使用 refresh.groups.interval.seconds 属性更改新使用者组的检查频率,该属性默认每 10 分钟执行一次。

由于同步是基于时间的,因此使用者到被动群集的任何切换都可能会导致消息出现某种重复。

9.2.7. 连接检查

一个 心跳 的内部主题检查集群之间的连通性。

heartbeat 主题从源集群中复制。

目标集群使用该主题检查:

  • 集群之间的连接器正在运行
  • 源集群可用

MirrorMaker 2.0 使用其 MirrorHeartbeatConnector 来发送执行这些检查的 心跳

9.3. ACL 规则同步

如果使用 AclAuthorizer,管理对代理访问权限的 ACL 规则也适用于远程主题。能够读取源主题的用户可以读取其远程等效内容。

注意

OAuth 2.0 授权不支持以这种方式访问远程主题。

9.4. 使用 MirrorMaker 2.0 在 Kafka 集群间同步数据

使用 MirrorMaker 2.0 通过配置同步 Kafka 集群之间的数据。

以前版本的 MirrorMaker 仍然受到支持,方法是在 旧模式下运行 MirrorMaker 2.0

配置必须指定:

  • 每个 Kafka 集群
  • 每个集群的连接信息,包括 TLS 身份验证
  • 复制流和方向

    • 集群到集群
    • 主题
  • 复制规则
  • 实施了偏移跟踪间隔

这个步骤描述了如何通过在属性文件中创建配置来实施 MirrorMaker 2.0,然后在使用 MirrorMaker 脚本文件时传递属性来设置连接。

注意

MirrorMaker 2.0 使用 Kafka Connect 进行连接,以在集群间传输数据。Kafka 提供 MirrorMaker sink 和源连接器以进行数据复制。如果要使用连接器而不是 MirrorMaker 脚本,必须在 Kafka Connect 集群中配置连接器。如需更多信息,请参阅 Apache Kafka 文档

开始前

./config/connect-mirror-maker.properties 中提供了一个示例配置属性文件。

先决条件

  • 您需要在您要复制的每个 Kafka 集群节点的主机上安装 AMQ Streams。

流程

  1. 在文本编辑器中打开示例属性文件,或创建一个新属性文件,再编辑 文件以包含连接信息和每个 Kafka 集群的复制流。

    以下示例显示了连接两个集群 cluster-1 和 cluster -2 (双向)的配置。集群名称可以通过 clusters 属性进行配置。

    clusters=cluster-1,cluster-2 1
    
    cluster-1.bootstrap.servers=CLUSTER-NAME-kafka-bootstrap-PROJECT-NAME:443 2
    cluster-1.security.protocol=SSL 3
    cluster-1.ssl.truststore.password=TRUSTSTORE-NAME
    cluster-1.ssl.truststore.location=PATH-TO-TRUSTSTORE/truststore.cluster-1.jks
    cluster-1.ssl.keystore.password=KEYSTORE-NAME
    cluster-1.ssl.keystore.location=PATH-TO-KEYSTORE/user.cluster-1.p12_
    
    cluster-2.bootstrap.servers=CLUSTER-NAME-kafka-bootstrap-<my-project>:443 4
    cluster-2.security.protocol=SSL 5
    cluster-2.ssl.truststore.password=TRUSTSTORE-NAME
    cluster-2.ssl.truststore.location=PATH-TO-TRUSTSTORE/truststore.cluster-2.jks_
    cluster-2.ssl.keystore.password=KEYSTORE-NAME
    cluster-2.ssl.keystore.location=PATH-TO-KEYSTORE/user.cluster-2.p12_
    
    cluster-1->cluster-2.enabled=true 6
    cluster-1->cluster-2.topics=.* 7
    cluster-2->cluster-1.enabled=true 8
    cluster-2->cluster-1B->C.topics=.* 9
    
    replication.policy.separator=- 10
    sync.topic.acls.enabled=false 11
    refresh.topics.interval.seconds=60 12
    refresh.groups.interval.seconds=60 13
    1
    每个 Kafka 集群都使用其别名识别。
    2
    cluster-1 的连接信息,使用 bootstrap 地址和 端口 443。两个集群都使用端口 443 来使用 OpenShift Route 连接到 Kafka。
    3
    ssl. 属性为 cluster-1 定义 TLS 配置。
    4
    cluster-2 的连接信息。
    5
    ssl. 属性为 cluster-2 定义 TLS 配置。
    6
    cluster-1 集群 启用到 cluster-2 集群的 复制流。
    7
    cluster-1 集群中的所有主题复制到 cluster-2 集群。
    8
    cluster-2 集群 启用到 cluster-1 集群的 复制流。
    9
    将特定主题从 cluster-2 集群复制到 cluster-1 集群。
    10
    定义用于重命名远程主题的分隔符。
    11
    启用后,ACL 将应用到同步的主题。默认值为 false
    12
    检查要同步的新主题之间的期间。
    13
    检查要同步的新消费者组之间的期间。
  2. 选项:如果需要,添加可覆盖远程主题自动重命名的策略。该主题不会用源集群的名称来附加名称,而是保留其原始名称。

    此可选设置用于主动/被动备份和数据迁移。

    replication.policy.class=io.strimzi.kafka.connect.mirror.IdentityReplicationPolicy
  3. OPTION:如果要同步消费者组偏移,请添加配置来启用和管理同步:

    refresh.groups.interval.seconds=60
    sync.group.offsets.enabled=true 1
    sync.group.offsets.interval.seconds=60 2
    emit.checkpoints.interval.seconds=60 3
    1
    可选设置来同步消费者组偏移,这对于主动/被动配置中的恢复非常有用。默认情况下不启用同步。
    2
    如果启用了消费者组偏移的同步,您可以调整同步的频率。
    3
    调整检查偏移跟踪的频率。如果更改了偏移同步的频率,您可能还需要调整这些检查的频率。
  4. 在目标集群中启动 ZooKeeper 和 Kafka:

    su - kafka
    /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties
    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  5. 使用您在属性文件中定义的集群连接配置和复制策略启动 MirrorMaker:

    /opt/kafka/bin/connect-mirror-maker.sh /config/connect-mirror-maker.properties

    MirrorMaker 设置集群间的连接。

  6. 对于每个目标集群,验证是否正在复制这些主题:

    /bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --list

9.5. 在旧模式下使用 MirrorMaker 2.0

这个步骤描述了如何配置 MirrorMaker 2.0 以在旧模式下使用它。旧模式支持先前版本的 MirrorMaker。

MirrorMaker 脚本 /opt/kafka/bin/kafka-mirror-maker.sh 可以在旧模式下运行 MirrorMaker 2.0。

先决条件

您需要当前用于 MirrorMaker 旧版本的属性文件。

  • /opt/kafka/config/consumer.properties
  • /opt/kafka/config/producer.properties

流程

  1. 编辑 MirrorMaker consumer.propertiesproducer.properties 文件,以关闭 MirrorMaker 2.0 功能。

    例如:

    replication.policy.class=org.apache.kafka.mirror.LegacyReplicationPolicy 1
    
    refresh.topics.enabled=false 2
    refresh.groups.enabled=false
    emit.checkpoints.enabled=false
    emit.heartbeats.enabled=false
    sync.topic.configs.enabled=false
    sync.topic.acls.enabled=false
    1
    模拟先前版本的 MirrorMaker。
    2
    MirrorMaker 2.0 功能已禁用,包括内部 检查点心跳 主题
  2. 使用您在以前的 MirrorMaker 版本中使用的属性文件保存更改并重启 MirrorMaker:

    su - kafka /opt/kafka/bin/kafka-mirror-maker.sh \
    --consumer.config /opt/kafka/config/consumer.properties \
    --producer.config /opt/kafka/config/producer.properties \
    --num.streams=2

    consumer 属性提供源集群的配置,producer 属性提供目标集群配置。

    MirrorMaker 设置集群间的连接。

  3. 在目标集群中启动 ZooKeeper 和 Kafka:

    su - kafka
    /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties
    su - kafka
    /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
  4. 对于目标集群,验证主题是否正在复制:

    /bin/kafka-topics.sh --bootstrap-server <BrokerAddress> --list

第 10 章 Kafka 客户端

kafka-clients JAR 文件包含 Kafka Producer 和 Consumer API,以及 Kafka AdminClient API。

  • Producer API 允许应用程序将数据发送到 Kafka 代理。
  • Consumer API 允许应用程序使用 Kafka 代理中的数据。
  • AdminClient API 提供用于管理 Kafka 集群的功能,包括主题、代理和其他组件。

10.1. 将 Kafka 客户端作为依赖项添加到 Maven 项目中

此流程演示了如何将 AMQ Streams Java 客户端添加为 Maven 项目的依赖项。

先决条件

  • 具有现有 pom.xml 的 Maven 项目。

流程

  1. 将 Red Hat Maven 存储库添加到 pom.xml 文件的 <repositories> 部分。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <!-- ... -->
    
        <repositories>
            <repository>
                <id>redhat-maven</id>
                <url>https://maven.repository.redhat.com/ga/</url>
            </repository>
        </repositories>
    
        <!-- ... -->
    
    </project>
  2. 将客户端添加到 pom.xml 文件的 <dependencies> 部分。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <!-- ... -->
    
        <dependencies>
            <dependency>
                <groupId>org.apache.kafka</groupId>
                <artifactId>kafka-clients</artifactId>
                <version>2.8.0.redhat-00002</version>
            </dependency>
        </dependencies>
    
        <!-- ... -->
    </project>
  3. 构建您的 Maven 项目。

第 11 章 Kafka Streams API 概述

Kafka Streams API 允许应用程序从一个或多个输入流接收数据,执行映射、过滤或加入等复杂操作,并将结果写入一个或多个输出流。它是 Red Hat Maven 存储库中提供的 kafka-streams JAR 软件包的一部分。

11.1. 将 Kafka Streams API 添加为 Maven 项目的依赖项

此流程演示了如何将 AMQ Streams Java 客户端添加为 Maven 项目的依赖项。

先决条件

  • 具有现有 pom.xml 的 Maven 项目。

流程

  1. 将 Red Hat Maven 存储库添加到 pom.xml 文件的 <repositories> 部分。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <!-- ... -->
    
        <repositories>
            <repository>
                <id>redhat-maven</id>
                <url>https://maven.repository.redhat.com/ga/</url>
            </repository>
        </repositories>
    
        <!-- ... -->
    
    </project>
  2. kafka-streams 添加到 pom.xml 文件的 <dependencies> 部分。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <!-- ... -->
    
        <dependencies>
            <dependency>
                <groupId>org.apache.kafka</groupId>
                <artifactId>kafka-streams</artifactId>
                <version>2.8.0.redhat-00002</version>
            </dependency>
        </dependencies>
    
        <!-- ... -->
    </project>
  3. 构建您的 Maven 项目。

第 12 章 Kafka Bridge

本章概述了 Red Hat Enterprise Linux 上的 AMQ Streams Kafka Bridge,并帮助您开始使用 REST API 与 AMQ Streams 交互。要在您的本地环境中尝试 Kafka 网桥,请参阅本章后面的 第 12.2 节 “Kafka Bridge quickstart”

其它资源

12.1. Kafka 网桥概述

Kafka Bridge 提供了一个 RESTful 接口,允许基于 HTTP 的客户端与 Kafka 集群交互。它提供了与 AMQ Streams 的 Web API 连接的优势,不需要客户端应用程序来解释 Kafka 协议。

API 有两个主要资源:consumerstopics,它们通过端点公开并可访问,以便与 Kafka 集群中的用户和生产者交互。资源仅与 Kafka 网桥相关,而不是与 Kafka 直接连接的消费者和生产者。

HTTP 请求

Kafka Bridge 支持对 Kafka 集群的 HTTP 请求,其方法如下:

  • 发送消息到一个主题。
  • 从主题检索消息.
  • 检索主题的分区列表。
  • 创建和删除消费者.
  • 订阅消费者了解主题,以便他们开始接收来自这些主题的信息。
  • 检索消费者订阅的主题列表。
  • 取消订阅消费者的主题.
  • 将分区分配给消费者.
  • 提交消费者偏移列表。
  • 寻找分区,以便使用者开始接受来自第一个或最后一个偏移位置的信息,或者给定的偏移位置。

这些方法提供 JSON 响应和 HTTP 响应代码错误处理。消息可以 JSON 或二进制格式发送。

客户端可以生成和使用消息,而无需使用原生 Kafka 协议。

与 AMQ Streams 安装类似,您可以下载用于在 Red Hat Enterprise Linux 上安装的 Kafka Bridge 文件。请参阅 第 12.1.5 节 “下载 Kafka 网桥存档”

有关为 KafkaBridge 资源配置主机和端口的详情请参考 第 12.1.6 节 “配置 Kafka Bridge 属性”

12.1.1. 身份验证和加密

尚不支持 HTTP 客户端和 Kafka 网桥之间的身份验证和加密。这意味着,从客户端发送到 Kafka Bridge 的请求是:

  • 未加密,且必须使用 HTTP 而不是 HTTPS
  • 在没有验证的情况下发送

您可以在 Kafka Bridge 和 Kafka 集群间配置 TLS 或 SASL 的身份验证

您已配置 Kafka Bridge 以通过其 属性文件 进行身份验证。

12.1.2. 对 Kafka Bridge 的请求

指定数据格式和 HTTP 标头,以确保向 Kafka Bridge 提交有效的请求。

API 请求和响应正文始终编码为 JSON。

12.1.2.1. 内容类型标头

必须为所有请求提交 Content-Type 标头。唯一的例外是,POST 请求正文为空时,添加 Content-Type 标头将导致请求失败。

消费者操作(/consumers 端点)和制作者操作(/topics 端点)需要不同的 Content-Type 标头。

用于消费者操作的内容类型标头

无论 嵌入式数据格式是什么,如果请求正文包含数据,对消费者操作的POST 请求必须提供以下 Content-Type 标头:

Content-Type: application/vnd.kafka.v2+json

用于制作者操作的 content-Type 标头

在执行制作者操作时,POST 请求必须提供 Content-Type 标头指定生成的信息的 嵌入式数据格式。这可以是 jsonbinary

表 12.1. 数据格式的内容类型标头
嵌入式数据格式content-Type 标头

JSON

Content-Type: application/vnd.kafka.json.v2+json

二进制

Content-Type: application/vnd.kafka.binary.v2+json

嵌入式数据格式为每个消费者设置,如下一节所述。

如果 POST 请求有空正文,则不能 设置 Content-Type。空正文可用于创建具有默认值的消费者。

12.1.2.2. 嵌入式数据格式

嵌入式数据格式是 Kafka 消息通过 HTTP 从生产者传输到使用 Kafka 网桥的消费者的格式。支持两种嵌入的数据格式:JSON 或二进制。

当使用 /consumers/groupid 端点创建消费者时,POST 请求正文必须指定 JSON 或二进制的嵌入式数据格式。这在请求正文的 format 字段中指定,例如:

{
  "name": "my-consumer",
  "format": "binary", 1
...
}
1
二进制嵌入式数据格式.

如果没有为使用者指定嵌入式数据格式,则会设置二进制格式。

创建使用者时指定的嵌入式数据格式必须与它将使用的 Kafka 消息的数据格式匹配。

如果您选择指定二进制嵌入式数据格式,后续制作者请求必须在请求正文中以 Base64 编码的字符串形式提供二进制数据。例如,当通过向 /topics/topicname 端点发出 POST 请求来发送信息时,value 必须使用 Base64 编码:

{
  "records": [
    {
      "key": "my-key",
      "value": "ZWR3YXJkdGhldGhyZWVsZWdnZWRjYXQ="
    },
  ]
}

制作者请求还必须提供与嵌入式数据格式对应的 Content-Type 标头,如 Content-Type: application/vnd.kafka.binary.v2+json

12.1.2.3. 消息格式

当使用 /topics 端点发送消息时,您可以在请求正文中在 records 参数中输入消息有效负载。

records 参数可以包含这些可选字段:

  • message key
  • message value
  • 目的地 partition
  • message headers

对 /topics 的 POST 请求示例

curl -X POST \
  http://localhost:8080/topics/my-topic \
  -H 'content-type: application/vnd.kafka.json.v2+json' \
  -d '{
    "records": [
        {
            "key": "my-key",
            "value": "sales-lead-0001"
            "partition": 2
            "headers": [
              {
                "key": "key1",
                "value": "QXBhY2hlIEthZmthIGlzIHRoZSBib21iIQ==" 1
              }
            ]
        },
    ]
}'

1
二进制格式的标头值,编码为 Base64。
12.1.2.4. 接受标头

创建消费者后,所有后续 GET 请求都必须以以下格式提供 Accept 标头:

Accept: application/vnd.kafka.embedded-data-format.v2+json

embedded -data-formatjsonbinary

例如,当使用嵌入的 JSON 数据格式获取订阅的消费者的记录时,包括这个 Accept 标头:

Accept: application/vnd.kafka.json.v2+json

12.1.3. 为 Kafka Bridge 配置日志记录器

AMQ Streams Kafka 网桥允许您为相关 OpenAPI 规格定义的每个操作设置不同的日志级别。

每一操作具有对应的 API 端点,网桥通过它接收来自 HTTP 客户端的请求。您可以更改每个端点的日志级别,以生成有关传入和传出 HTTP 请求的更多或更少的精细日志信息。

日志记录器在 log4j.properties 文件中定义,该文件具有 healthyready 端点的以下默认配置:

log4j.logger.http.openapi.operation.healthy=WARN, out
log4j.additivity.http.openapi.operation.healthy=false
log4j.logger.http.openapi.operation.ready=WARN, out
log4j.additivity.http.openapi.operation.ready=false

所有其他操作的日志级别默认设置为 INFO。日志记录器的格式如下:

log4j.logger.http.openapi.operation.<operation-id>

其中 <operation-id> 是特定操作的标识符。以下是 OpenAPI 规范定义的操作列表:

  • createConsumer
  • deleteConsumer
  • subscribe
  • unsubscribe
  • poll
  • assign
  • commit
  • send
  • sendToPartition
  • seekToBeginning
  • seekToEnd
  • seek
  • healthy
  • ready
  • openapi

12.1.4. Kafka Bridge API 资源

有关 REST API 端点和描述的完整列表,包括请求和响应示例,请查看 Kafka Bridge API 参考

12.1.5. 下载 Kafka 网桥存档

从红帽网站下载 AMQ Streams Kafka Bridge 的压缩发行版。

流程

12.1.6. 配置 Kafka Bridge 属性

此流程描述了如何配置 AMQ Streams Kafka Bridge 使用的 Kafka 和 HTTP 连接属性。

您可以使用与 Kafka 相关的属性的适当前缀,将 Kafka Bridge 配置为任何其他 Kafka 客户端。

  • kafka. 对于适用于生产者和消费者的一般配置,如服务器连接和安全。
  • kafka.consumer. 对于仅传递给使用者的特定于消费者的配置。
  • kafka.producer. 对于仅传递给制作者的特定制作者的配置。

除了启用对 Kafka 集群的 HTTP 访问外,HTTP 属性还提供通过跨操作资源共享(CORS)启用和定义 Kafka 网桥访问控制的功能。CORS 是一种 HTTP 机制,它允许浏览器从多个来源访问选定的资源。要配置 CORS,您可以定义允许的资源来源列表以及访问它们的 HTTP 方法。请求中的附加 HTTP 标头描述了允许访问 Kafka 集群的原始数据

流程

  1. 编辑 AMQ Streams Kafka Bridge 安装存档提供的 application.properties 文件。

    使用 属性文件指定 Kafka 和 HTTP 相关的属性,并启用分布式追踪。

    1. 配置标准的 Kafka 相关属性,包括特定于 Kafka 用户和生产者的属性。

      使用:

      • kafka.bootstrap.servers 定义到 Kafka 集群的主机/端口连接
      • kafka.producer.acks 向 HTTP 客户端提供确认
      • kafka.consumer.auto.offset.reset 确定如何在 Kafka 中管理重置偏移

        有关 Kafka 属性配置的更多信息,请参阅 Apache Kafka 网站

    2. 配置与 HTTP 相关的属性,以启用对 Kafka 集群的 HTTP 访问。

      例如:

      http.enabled=true
      http.host=0.0.0.0
      http.port=8080 1
      http.cors.enabled=true 2
      http.cors.allowedOrigins=https://strimzi.io 3
      http.cors.allowedMethods=GET,POST,PUT,DELETE,OPTIONS,PATCH 4
      1
      Kafka Bridge 侦听端口 8080 的默认 HTTP 配置。
      2
      设置为 true 以启用 CORS。
      3
      允许的 CORS 原始源以逗号分隔的列表。您可以使用 URL 或 Java 正则表达式。
      4
      以逗号分隔的 CORS 允许 HTTP 方法列表。
    3. 启用或禁用分布式追踪。

      bridge.tracing=jaeger

      从属性中删除代码注释,以启用分布式追踪

12.1.7. 安装 Kafka Bridge

按照以下步骤在 Red Hat Enterprise Linux 上安装 AMQ Streams Kafka Bridge。

流程

  1. 如果您还没有这样做,请将 AMQ Streams Kafka Bridge 安装存档解压缩到任何目录。
  2. 使用配置属性作为参数运行 Kafka Bridge 脚本:

    例如:

    ./bin/kafka_bridge_run.sh --config-file=_path_/configfile.properties
  3. 检查日志中是否成功安装了。

    HTTP-Kafka Bridge started and listening on port 8080
    HTTP-Kafka Bridge bootstrap servers localhost:9092

12.2. Kafka Bridge quickstart

使用这个快速入门尝试 Red Hat Enterprise Linux 上的 AMQ Streams Kafka Bridge。您将学习如何:

  • 安装 Kafka Bridge
  • 生成到 Kafka 集群中主题和分区的信息
  • 创建 Kafka 网桥消费者
  • 执行基本的消费者操作,如将消费者订阅到主题并检索您生成的信息

在这个快速启动中,HTTP 请求格式化为 curl 命令,您可以将它们复制并粘贴到您的终端。

确保您具有先决条件,然后按照本章中提供的顺序按照任务进行操作。

关于数据格式

在此快速入门中,您将以 JSON 格式(而非二进制)生成和使用消息。有关示例请求中使用的数据格式和 HTTP 标头的更多信息,请参阅 第 12.1.1 节 “身份验证和加密”

12.2.1. 本地部署 Kafka Bridge

将 AMQ Streams Kafka Bridge 的实例部署到主机。使用安装归档提供的 application.properties 文件来应用默认配置设置。

流程

  1. 打开 application.properties 文件,检查是否定义了默认 HTTP related settings

    http.enabled=true
    http.host=0.0.0.0
    http.port=8080

    这会将 Kafka Bridge 配置为侦听端口 8080 上的请求。

  2. 使用配置属性作为参数运行 Kafka Bridge 脚本:

    ./bin/kafka_bridge_run.sh --config-file=<path>/application.properties

接下来要做什么

12.2.2. 生成到主题和分区的消息

使用 主题 端点以 JSON 格式生成消息。

您可以在请求正文中为消息指定目的地分区,如下所示。分区 端点 提供了一种备选方法,用于指定所有消息的单一目标分区,作为路径参数。

流程

  1. 使用 kafka-topics.sh 实用程序创建 Kafka 主题:

    bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic bridge-quickstart-topic --partitions 3 --replication-factor 1 --config retention.ms=7200000 --config segment.bytes=1073741824

    指定三个分区。

  2. 验证该主题是否已创建:

    bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic bridge-quickstart-topic
  3. 使用 Kafka Bridge,为您创建的主题生成三个信息:

    curl -X POST \
      http://localhost:8080/topics/bridge-quickstart-topic \
      -H 'content-type: application/vnd.kafka.json.v2+json' \
      -d '{
        "records": [
            {
                "key": "my-key",
                "value": "sales-lead-0001"
            },
            {
                "value": "sales-lead-0002",
                "partition": 2
            },
            {
                "value": "sales-lead-0003"
            }
        ]
    }'
    • sales-lead-0001 根据密钥的散列发送到分区。
    • sales-lead-0002 直接发送到分区 2。
    • sales-lead-0003 使用循环方法发送到 bridge-quickstart-topic 主题中的分区。
  4. 如果请求成功,Kafka Bridge 会返回 offsets 数组,以及 200 (OK)代码和 content-type 标头 application/vnd.kafka.v2+json。对于每个消息,offsets 数组描述:

    • 消息发送到的分区
    • 分区的当前消息偏移

      响应示例

      #...
      {
        "offsets":[
          {
            "partition":0,
            "offset":0
          },
          {
            "partition":2,
            "offset":0
          },
          {
            "partition":0,
            "offset":1
          }
        ]
      }

接下来要做什么

在向主题和分区生成消息后,创建一个 Kafka 网桥使用者

其它资源

12.2.3. 创建 Kafka 网桥消费者

在 Kafka 集群上执行任何消费者操作前,您必须首先使用使用者端点创建 消费者。用户称为 Kafka 网桥消费者

流程

  1. 在名为 bridge-quickstart-consumer-group 的新消费者组中创建一个 Kafka 网桥消费者:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "name": "bridge-quickstart-consumer",
        "auto.offset.reset": "earliest",
        "format": "json",
        "enable.auto.commit": false,
        "fetch.min.bytes": 512,
        "consumer.request.timeout.ms": 30000
      }'
    • 使用者名为 bridge-quickstart-consumer,嵌入式数据格式被设置为 json
    • 由于 enable.auto.commit 设置是 false,因此使用者不会自动向日志提交偏移。在此快速入门稍后您将手动提交偏移。

      注意

      如果您没有在请求正文中指定消费者名称,Kafka Bridge 将生成随机消费者名称。

      如果请求成功,Kafka Bridge 返回响应正文中的消费者 ID(instance_id)和基本 URL(base_uri),以及 200 (OK)代码。

      响应示例

      #...
      {
        "instance_id": "bridge-quickstart-consumer",
        "base_uri":"http://<bridge-name>-bridge-service:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer"
      }

  2. 复制基本 URL(base_uri),以便在这个快速启动的其他消费者操作中使用。

接下来要做什么

现在,您已创建了 Kafka 网桥消费者,您可以为 它订阅主题

其它资源

12.2.4. 将 Kafka 网桥消费者订阅到主题

使用订阅端点将 Kafka Bridge 用户 订阅 到一个或多个主题。订阅后,消费者开始收到生成到该主题的所有消息。

流程

  • 在向 主题和分区生成信息时,将消费者订阅到 您之前创建的 bridge-quickstart-topic 主题:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/subscription \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "topics": [
            "bridge-quickstart-topic"
        ]
    }'

    topics 数组可以包含一个主题(如上所示)或多个主题。如果要将消费者订阅与正则表达式匹配的多个主题,您可以使用 topic_pattern 字符串而不是 topics 数组。

    如果请求成功,Kafka Bridge 只会返回 204 No Content 代码。

接下来要做什么

在将 Kafka 网桥使用者订阅到主题后,您可以从 消费者检索消息

其它资源

12.2.5. 从 Kafka Bridge 用户检索最新信息

通过从 记录 端点请求数据,从 Kafka 网桥使用者检索最新的消息。在生产环境中,HTTP 客户端可以重复调用此端点(在循环中)。

流程

  1. 为 Kafka 网桥使用者生成其他信息,如 向主题和分区生成消息 中所述。
  2. records 端点提交 GET 请求:

    curl -X GET http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/records \
      -H 'accept: application/vnd.kafka.json.v2+json'

    创建并订阅 Kafka 网桥消费者后,第一个 GET 请求将返回空响应,因为轮询操作会触发重新平衡过程来分配分区。

  3. 重复步骤二,从 Kafka Bridge consumer 检索消息。

    Kafka Bridge 返回一组消息来代表主题名称、键、值、分区和偏移跟踪正文信息,以及 200 (OK)代码。消息默认从最新的偏移检索。

    HTTP/1.1 200 OK
    content-type: application/vnd.kafka.json.v2+json
    #...
    [
      {
        "topic":"bridge-quickstart-topic",
        "key":"my-key",
        "value":"sales-lead-0001",
        "partition":0,
        "offset":0
      },
      {
        "topic":"bridge-quickstart-topic",
        "key":null,
        "value":"sales-lead-0003",
        "partition":0,
        "offset":1
      },
    #...
    注意

    如果返回空的响应,会按照 向主题和分区生成消息 中所述为消费者生成更多记录,然后尝试再次检索消息。

接下来要做什么

从 Kafka 网桥使用者检索消息后,尝试 向日志提交偏移

其它资源

12.2.6. 将偏移提交到日志

使用 偏移端点,将偏移手动提交到 Kafka Bridge使用者接收的所有消息的日志中。这是必要的,因为您在创建 Kafka Bridge 用户时之前创建的 Kafka 网桥消费者 使用 enable.auto.commit 设置配置为 false

流程

  • bridge-quickstart-consumer 的日志提交偏移:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/offsets

    由于没有提交请求正文,将为消费者收到的所有记录提交偏移。或者,请求正文可以包含一个数组(OffsetCommitSeekList),用于指定您要提交偏移的主题和分区。

    如果请求成功,Kafka Bridge 只会返回 204 No Content 代码。

接下来要做什么

向日志提交偏移后,尝试查找要 偏移的 端点。

其它资源

12.2.7. 寻找分区的偏移

使用 位置 端点配置 Kafka 网桥使用者,以从特定偏移检索分区的消息,然后从最新的偏移中检索。这在 Apache Kafka 中称为搜索操作。

流程

  1. quickstart-bridge-topic 主题的分区 0 寻找特定的偏移:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/positions \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "offsets": [
            {
                "topic": "bridge-quickstart-topic",
                "partition": 0,
                "offset": 2
            }
        ]
    }'

    如果请求成功,Kafka Bridge 只会返回 204 No Content 代码。

  2. records 端点提交 GET 请求:

    curl -X GET http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/records \
      -H 'accept: application/vnd.kafka.json.v2+json'

    Kafka Bridge 从您要查找的偏移返回消息。

  3. 通过查找同一分区的最后偏移来恢复默认消息检索行为。这一次使用 position /end 端点。

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/positions/end \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "partitions": [
            {
                "topic": "bridge-quickstart-topic",
                "partition": 0
            }
        ]
    }'

    如果请求成功,Kafka Bridge 会返回另一个 204 No Content 代码。

注意

您还可以使用 位置/探测端点 来查找一个或多个分区的第一个偏移。

接下来要做什么

在这个快速入门中,您已使用 AMQ Streams Kafka Bridge 在 Kafka 集群上执行几个常用操作。现在 ,您可以删除之前创建的 Kafka 网桥消费者

12.2.8. 删除 Kafka 网桥消费者

最后,删除整个快速入门中使用的 Kafa Bridge 消费者。

流程

  • 通过向 实例 端点发送 DELETE 请求来删除 Kafka 网桥消费者。

    curl -X DELETE http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer

    如果请求成功,Kafka Bridge 只会返回 204 No Content 代码。

其它资源

第 13 章 使用 Kerberos(GSSAPI)身份验证

AMQ Streams 支持使用 Kerberos(GSSAPI)身份验证协议来保护对 Kafka 集群的单点登录访问。GSSAPI 是一个用于 Kerberos 功能的 API 打包程序,使应用程序免受底层实施的变化。

Kerberos 是一种网络身份验证系统,允许客户端和服务器使用对称加密和受信任的第三方 - Kerberos 密钥分发中心(KDC)相互身份验证。

13.1. 设置 AMQ 流以使用 Kerberos(GSSAPI)身份验证

此流程演示了如何配置 AMQ Streams,以便 Kafka 客户端可以使用 Kerberos(GSSAPI)身份验证访问 Kafka 和 ZooKeeper。

该流程假定已在 Red Hat Enterprise Linux 主机上设置了 Kerberos krb5 资源服务器。

该流程演示了如何配置:

  1. 服务主体
  2. Kafka 代理使用 Kerberos 登录
  3. zookeeper 使用 Kerberos 登录
  4. 使用 Kerberos 身份验证访问 Kafka 的生产者和消费者客户端

该说明描述了在单个主机上为单个 ZooKeeper 和 Kafka 安装设置的 Kerberos,并为制作者和消费者客户端设置额外的配置。

先决条件

要配置 Kafka 和 ZooKeeper 以验证和授权 Kerberos 凭证,您需要:

  • 访问 Kerberos 服务器
  • 每个 Kafka 代理主机上的 Kerberos 客户端

有关设置 Kerberos 服务器的步骤以及代理主机上的客户端的详情,请查看 RHEL 设置配置中的示例 Kerberos

如何部署 Kerberos 取决于您的操作系统。红帽建议在 Red Hat Enterprise Linux 中设置 Kerberos 时使用 Identity Management(IdM)。Oracle 或 IBM JDK 的用户必须安装 Java 加密扩展(JCE)。

添加用于身份验证的服务主体

从您的 Kerberos 服务器,为 ZooKeeper、Kafka 代理以及 Kafka 制作者和消费者客户端创建服务主体(用户)。

服务主体必须使用 SERVICE-NAME/FULLY-QUALIFIED-HOST-NAME@DOMAIN-REALM 格式

  1. 通过 Kerberos KDC 创建服务主体,以及存储主要密钥的 keytab。

    例如:

    • zookeeper/node1.example.redhat.com@EXAMPLE.REDHAT.COM
    • kafka/node1.example.redhat.com@EXAMPLE.REDHAT.COM
    • producer1/node1.example.redhat.com@EXAMPLE.REDHAT.COM
    • consumer1/node1.example.redhat.com@EXAMPLE.REDHAT.COM

      ZooKeeper 服务主体必须具有与 Kafka config/server.properties 文件中的 zookeeper.connect 配置相同的主机名:

      zookeeper.connect=node1.example.redhat.com:2181

      如果主机名不同,则使用 localhost,身份验证将失败。

  2. 在主机上创建目录并添加 keytab 文件:

    例如:

    /opt/kafka/krb5/zookeeper-node1.keytab
    /opt/kafka/krb5/kafka-node1.keytab
    /opt/kafka/krb5/kafka-producer1.keytab
    /opt/kafka/krb5/kafka-consumer1.keytab
  3. 确保 kafka 用户可以访问该目录:

    chown kafka:kafka -R /opt/kafka/krb5
将 ZooKeeper 配置为使用 Kerberos 登录

将 ZooKeeper 配置为使用 Kerberos 密钥分发中心(KDC)通过之前为 zookeeper 创建的用户主体和 keytab 进行身份验证。

  1. 创建或修改 opt/kafka/config/jaas.conf 文件以支持 ZooKeeper 客户端和服务器操作:

    Client {
        com.sun.security.auth.module.Krb5LoginModule required debug=true
        useKeyTab=true 1
        storeKey=true 2
        useTicketCache=false 3
        keyTab="/opt/kafka/krb5/zookeeper-node1.keytab" 4
        principal="zookeeper/node1.example.redhat.com@EXAMPLE.REDHAT.COM"; 5
    };
    
    Server {
        com.sun.security.auth.module.Krb5LoginModule required debug=true
        useKeyTab=true
        storeKey=true
        useTicketCache=false
        keyTab="/opt/kafka/krb5/zookeeper-node1.keytab"
        principal="zookeeper/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    };
    
    QuorumServer {
        com.sun.security.auth.module.Krb5LoginModule required debug=true
        useKeyTab=true
        storeKey=true
        keyTab="/opt/kafka/krb5/zookeeper-node1.keytab"
        principal="zookeeper/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    };
    
    QuorumLearner {
        com.sun.security.auth.module.Krb5LoginModule required debug=true
        useKeyTab=true
        storeKey=true
        keyTab="/opt/kafka/krb5/zookeeper-node1.keytab"
        principal="zookeeper/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    };
    1
    设置为 true,从 keytab 获取主密钥。
    2
    设置为 true 以存储主体密钥。
    3
    设置为 true,从票据缓存中获取 Ticket Granting Ticket(TGT)。
    4
    keyTab 属性指向从 Kerberos KDC 复制的 keytab 文件的位置。位置和文件必须可由 kafka 用户读取。
    5
    principal 属性配置为与 KDC 主机上创建的完全限定主体名称匹配,其格式为 SERVICE-NAME/FULLY-QUALIFIED-HOST-NAME@DOMAIN-NAME
  2. 编辑 opt/kafka/config/zookeeper.properties 以使用更新的 JAAS 配置:

    # ...
    
    requireClientAuthScheme=sasl
    jaasLoginRenew=3600000 1
    kerberos.removeHostFromPrincipal=false 2
    kerberos.removeRealmFromPrincipal=false 3
    quorum.auth.enableSasl=true 4
    quorum.auth.learnerRequireSasl=true 5
    quorum.auth.serverRequireSasl=true
    quorum.auth.learner.loginContext=QuorumLearner 6
    quorum.auth.server.loginContext=QuorumServer
    quorum.auth.kerberos.servicePrincipal=zookeeper/_HOST 7
    quorum.cnxn.threads.size=20
    1
    控制登录续订的频率(毫秒),可调整该频率以适应票据续订间隔。默认值为 1 小时。
    2
    指示主机名是否用作登录主体名称的一部分。如果对群集中的所有节点使用单个 keytab,这设置为 true。但是,建议为每个代理主机生成一个单独的 keytab 和完全限定主体来进行故障排除。
    3
    控制是否从 Kerberos 协商的主要名称中分离域名。建议将此设置设置为 false
    4
    为 ZooKeeper 服务器和客户端启用 SASL 身份验证机制。
    5
    RequireSasl 属性控制仲裁事件(如 master 选举)是否需要 SASL 身份验证。
    6
    loginContext 属性标识用于验证指定组件配置的 JAAS 配置中的登录上下文名称。loginContext 名称与 opt/kafka/config/jaas.conf 文件中相关部分的名称对应。
    7
    控制用于组成用于识别的主要名称的命名约定。占位符 _HOST 在运行时自动解析为由 server.1 属性定义的主机名。
  3. 使用 JVM 参数启动 ZooKeeper 以指定 Kerberos 登录配置:

    su - kafka
    export EXTRA_ARGS="-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/config/jaas.conf"; /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

    如果您不使用默认服务名称(zookeeper),请使用 -Dzookeeper.sasl.client.username=NAME 参数添加名称。

    注意

    如果您使用 /etc/krb5.conf 位置,在启动 ZooKeeper、Kafka 或者 Kafka 制作者和消费者时,您不需要指定 -Djava.security.krb5.conf=/etc/krb5.conf

将 Kafka 代理服务器配置为使用 Kerberos 登录

配置 Kafka,以使用 Kerberos 密钥分发中心(KDC)通过之前为 kafka 创建的用户主体和 keytab 进行身份验证。

  1. 使用以下元素修改 opt/kafka/config/jaas.conf 文件:

    KafkaServer {
        com.sun.security.auth.module.Krb5LoginModule required
        useKeyTab=true
        storeKey=true
        keyTab="/opt/kafka/krb5/kafka-node1.keytab"
        principal="kafka/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    };
    KafkaClient {
        com.sun.security.auth.module.Krb5LoginModule required debug=true
        useKeyTab=true
        storeKey=true
        useTicketCache=false
        keyTab="/opt/kafka/krb5/kafka-node1.keytab"
        principal="kafka/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    };
  2. 通过修改 config/server.properties 文件中的监听程序配置,使监听器使用 SASL/GSSAPI 登录,在 Kafka 集群中配置每个代理。

    将 SASL 协议添加到监听器的安全协议映射中,并删除任何不需要的协议。

    例如:

    # ...
    broker.id=0
    # ...
    listeners=SECURE://:9092,REPLICATION://:9094 1
    inter.broker.listener.name=REPLICATION
    # ...
    listener.security.protocol.map=SECURE:SASL_PLAINTEXT,REPLICATION:SASL_PLAINTEXT 2
    # ..
    sasl.enabled.mechanisms=GSSAPI 3
    sasl.mechanism.inter.broker.protocol=GSSAPI 4
    sasl.kerberos.service.name=kafka 5
    ...
    1
    配置了两个侦听器:一个用于与客户端通用通信的安全监听程序(支持 TLS 用于通信),以及用于代理间通信的复制监听器。
    2
    对于启用 TLS 的监听程序,协议名称为 SASL_PLAINTEXT。对于非 TLS 的连接器,协议名称为 SASL_PLAINTEXT。如果不需要 SSL,您可以删除 ssl.* 属性。
    3
    用于 Kerberos 验证的 SASL 机制为 GSSAPI
    4
    用于代理间通信的 Kerberos 身份验证.
    5
    指定了用于身份验证请求的服务名称,以便将其与可能使用相同的 Kerberos 配置的其他服务区分开来。
  3. 使用 JVM 参数启动 Kafka 代理,以指定 Kerberos 登录配置:

    su - kafka
    export KAFKA_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/config/jaas.conf"; /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

    如果之前配置了 broker 和 ZooKeeper 集群,并使用基于非 Kerberos 的身份验证系统,则可以启动 ZooKeeper 和代理集群,并检查日志中的配置错误。

    在启动代理和 Zookeeper 实例后,集群现在被配置用于 Kerberos 身份验证。

配置 Kafka 制作者和消费者客户端以使用 Kerberos 身份验证

配置 Kafka 制作者和消费者客户端,以使用 Kerberos 密钥分发中心(KDC)通过之前为 producer1consumer1 创建的用户主体和 keytab 进行身份验证。

  1. 将 Kerberos 配置添加到制作者或使用者配置文件。

    例如:

    /opt/kafka/config/producer.properties

    # ...
    sasl.mechanism=GSSAPI 1
    security.protocol=SASL_PLAINTEXT 2
    sasl.kerberos.service.name=kafka 3
    sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \ 4
        useKeyTab=true  \
        useTicketCache=false \
        storeKey=true  \
        keyTab="/opt/kafka/krb5/producer1.keytab" \
        principal="producer1/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    # ...

    1
    Kerberos(GSSAPI)身份验证配置.
    2
    Kerberos 使用 SASL 纯文本(用户名/密码)安全协议。
    3
    在 Kerberos KDC 中配置的 Kafka 的服务主体(用户)。
    4
    使用 jaas.conf 中定义的相同属性配置 JAAS。

    /opt/kafka/config/consumer.properties

    # ...
    sasl.mechanism=GSSAPI
    security.protocol=SASL_PLAINTEXT
    sasl.kerberos.service.name=kafka
    sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
        useKeyTab=true  \
        useTicketCache=false \
        storeKey=true  \
        keyTab="/opt/kafka/krb5/consumer1.keytab" \
        principal="consumer1/node1.example.redhat.com@EXAMPLE.REDHAT.COM";
    # ...

  2. 运行客户端以验证您可以从 Kafka 代理发送和接收消息。

    制作者客户端:

    export KAFKA_HEAP_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"; /opt/kafka/bin/kafka-console-producer.sh --producer.config /opt/kafka/config/producer.properties  --topic topic1 --bootstrap-server node1.example.redhat.com:9094

    消费者客户端:

    export KAFKA_HEAP_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"; /opt/kafka/bin/kafka-console-consumer.sh --consumer.config /opt/kafka/config/consumer.properties  --topic topic1 --bootstrap-server node1.example.redhat.com:9094

第 14 章 用于集群重新平衡的精简控制

重要

用于集群重新平衡的精简控制只是一个技术预览。技术预览功能不被红帽产品服务级别协议(SLA)支持,且可能无法完成功能。红帽不推荐在生产环境中实施任何技术预览功能。此技术预览功能为您提供对即将推出的产品创新的早期访问,允许您在开发过程中测试并提供反馈。有关红帽技术预览功能支持范围的更多信息,请参阅 技术预览功能支持范围

您可以将 Cruise Control 部署到 AMQ Streams 集群,并使用它在 Kafka 代理间重新平衡负载。

cruise Control 是一个开源系统,用于自动执行 Kafka 操作,如监控集群工作负载、根据预定义的限制重新平衡集群,以及检测和修复异常情况。它包含四个组件(Load Monitor、Analyzer、Anomaly Detector 和 Executor)以及 REST API。

当 AMQ Streams 和 Cruise Control 都部署到红帽企业 Linux 中时,您可以通过 Cruise Control REST API 访问 Cruise Control 功能。支持以下功能:

  • 配置 优化目标和 容量限制
  • 使用 /rebalance 端点:

    • 根据配置的 优化目标 或作为请求参数提供的用户提供 的目标, 生成空运行优化调整信息
    • 启动优化建议以重新平衡 Kafka 集群
  • 使用 /user_tasks 端点检查活跃的重新平衡操作的进度
  • 使用 /stop_proposal_execution 端点停止活跃的重新平衡操作

目前不支持所有其他 Cruise 控制功能,包括异常检测、通知、写入目标以及更改主题复制因素。不支持 Web UI 组件(Cruise Control Frontend)。

Red Hat Enterprise Linux 中的 AMQ Streams 控制作为一个单独的压缩发行版提供。如需更多信息,请参阅 第 14.2 节 “下载清理控制存档”

14.1. 为什么使用清理控制?

cruise Control 可减少运行高效 Kafka 集群所需的时间和工作量,跨代理更均匀地平衡工作负载。

典型的群集可能会随着时间推移而变得异常加载。处理大量消息流量的分区可能会在可用的代理中不均匀分布。要重新平衡集群,管理员必须监控代理上的负载,并手动将繁忙的分区重新分配给具有备用容量的代理。

整合控制可自动执行此集群重新平衡过程。它根据 CPU、磁盘和网络负载构建资源利用率 的工作负载模型。通过使用一组可配置的优化目标,您可以指示 Cruise Control 生成空运行优化,从而实现更均衡的分区分配。

在审查了空运行优化建议后,您可以指示 Cruise Control 根据该建议启动集群重新平衡,或者生成新的提议。

当集群重新平衡操作完成后,代理会更有效地使用,Kafka 集群上的负载也会更加均匀地平衡。

14.2. 下载清理控制存档

Red Hat Enterprise Linux 上的 AMQ Streams Cruise Controls 压缩版的发布可从 红帽客户门户 下载。

流程

  1. 红帽客户门户 下载最新版本的 Red Hat AMQ Streams Cruise Control 存档。
  2. 创建 /opt/cruise-control 目录:

    sudo mkdir /opt/cruise-control
  3. 将 Cruise Control ZIP 文件的内容提取到新目录中:

    unzip amq-streams-y.y.y-cruise-control-bin.zip -d /opt/cruise-control
  4. /opt/cruise-control 目录的所有权改为 kafka 用户:

    sudo chown -R kafka:kafka /opt/cruise-control

14.3. 部署 Cruise 控制指标报告器

在启动 Cruise Control 前,您必须将 Kafka 代理配置为使用提供的 Cruise Control Metrics Reporter。

在运行时载入时,Metric Reporter 会将指标发送到 __CruiseControlMetrics 主题,该主题由三个 自动创建的主题 之一。整合控制使用这些指标来创建和更新工作负载模型,并计算优化方法。

先决条件

流程

对于 Kafka 集群中的每个代理,一次一个代理:

  1. 停止 Kafka 代理:

    /opt/kafka/bin/kafka-server-stop.sh
  2. 将 Cruise Control Metrics Reporter .jar 文件复制到 Kafka 库目录中:

    cp /opt/cruise-control/libs/cruise-control-metrics-reporter-y.y.yyy.redhat-0000x.jar /opt/kafka/libs
  3. 在 Kafka 配置文件中(/opt/kafka/config/server.properties)配置 Cruise Control Metrics Reporter:

    1. CruiseControlMetricsReporter 类添加到 metric.reporters 配置选项中。不要删除任何现有的指标报告器。

      metric.reporters=com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter
    2. 在 Kafka 配置文件中添加以下配置选项和值:

      cruise.control.metrics.topic.auto.create=true
      cruise.control.metrics.topic.num.partitions=1
      cruise.control.metrics.topic.replication.factor=1

      这些选项可让 Cruise Control Metrics Reporter 使用日志清理策略 DELETE 创建 __CruiseControlMetrics 主题。如需更多信息,请参阅 自动创建主题和 Cruise Control Metrics 主题的日志清理策略

  4. 如果需要,配置 SSL。

    1. 在 Kafka 配置文件中(/opt/kafka/config/server.properties)通过设置相关的客户端配置属性,在 Cruise Control Metrics Reporter 和 Kafka 代理之间配置 SSL。

      Metrics Reporter 使用 cruise.control.metrics.reporter 前缀接受所有特定于标准的配置属性。例如: cruise.control.metrics.reporter.ssl.truststore.password

    2. 在 Cruise Control 属性文件中(/opt/cruise-control/config/cruisecontrol.properties)通过设置相关的客户端配置属性,在 Kafka 代理和 Cruise Control 服务器之间配置 SSL。

      插入控制从 Kafka 继承 SSL 客户端属性选项,并将这些属性用于所有 Cruise Control 服务器客户端。

  5. 重启 Kafka 代理:

    /opt/kafka/bin/kafka-server-start.sh
  6. 为剩余的代理重复第 1-5 步。

14.4. 配置和启动清理控制

配置 Cruise Control 使用的属性,然后使用 cruise-control-start.sh 脚本启动 Cruise Control 服务器。该服务器托管于整个 Kafka 集群的单一机器上。

在 Cruise Control 启动时会自动创建三个主题。如需更多信息,请参阅 自动创建的主题

先决条件

流程

  1. 编辑 Cruise Control 属性文件(/opt/cruise-control/config/cruisecontrol.properties)。
  2. 配置以下示例配置中显示的属性:

    # The Kafka cluster to control.
    bootstrap.servers=localhost:9092 1
    
    # The replication factor of Kafka metric sample store topic
    sample.store.topic.replication.factor=2 2
    
    # The configuration for the BrokerCapacityConfigFileResolver (supports JBOD, non-JBOD, and heterogeneous CPU core capacities)
    #capacity.config.file=config/capacity.json
    #capacity.config.file=config/capacityCores.json
    capacity.config.file=config/capacityJBOD.json 3
    
    # The list of goals to optimize the Kafka cluster for with pre-computed proposals
    default.goals={List of default optimization goals} 4
    
    # The list of supported goals
    goals={list of master optimization goals} 5
    
    # The list of supported hard goals
    hard.goals={List of hard goals} 6
    
    # How often should the cached proposal be expired and recalculated if necessary
    proposal.expiration.ms=60000 7
    
    # The zookeeper connect of the Kafka cluster
    zookeeper.connect=localhost:2181 8
    1
    Kafka 代理的主机和端口号(始终端口 9092)。
    2
    Kafka 指标示例存储主题的复制因素。如果您要在单节点 Kafka 和 ZooKeeper 集群中评估 Cruise Control,请将此属性设置为 1。对于生产环境,将此属性设置为 2 或更多。
    3
    为代理资源设置最大容量限制的配置文件。使用应用于您的 Kafka 部署配置的 文件。如需更多信息,请参阅 容量配置
    4
    使用完全限定域名(FQDN)的逗号分隔默认优化目标列表。许多主优化目标(参见 5)已设置为默认优化目标;如果需要,您可以添加或删除目标。如需更多信息,请参阅 第 14.5 节 “优化目标概述”
    5
    使用 FQDN 以逗号分隔的主优化目标列表。为了完全排除用于生成优化判断的目标,请将其从列表中删除。如需更多信息,请参阅 第 14.5 节 “优化目标概述”
    6
    使用 FQDN 以逗号分隔的硬目标列表。七个主优化目标已被设置为硬目标;如果需要,您可以添加或删除目标。如需更多信息,请参阅 第 14.5 节 “优化目标概述”
    7
    从默认优化目标生成的缓存优化建议的间隔,以毫秒为单位。如需更多信息,请参阅 第 14.6 节 “优化调整概述”
    8
    ZooKeeper 连接的主机和端口号(始终端口 2181)。
  3. 启动清理控制服务器。默认情况下,服务器在端口 9092 上启动;可选,指定不同的端口。

    cd /opt/cruise-control/
    ./bin/cruise-control-start.sh config/cruisecontrol.properties PORT
  4. 要验证 Cruise Control 是否正在运行,请向 Cruise Control 服务器的 /state 端点发送 GET 请求:

    curl 'http://HOST:PORT/kafkacruisecontrol/state'
自动创建的主题

下表显示了 Cruise Control 启动时自动创建的三个主题。这些主题是必需的,清理控制才能正常工作,且不得删除或更改。

表 14.1. 自动创建的主题
自动创建的主题创建者功能

__CruiseControlMetrics

Sything Control Metrics Reporter

将 Metrics Reporter 中的原始指标存储在每个 Kafka 代理中。

__KafkaCruiseControlPartitionMetricSamples

Sything Control

存储每个分区派生的指标。它们由 Metric Sample Aggregator 创建。

__KafkaCruiseControlModelTrainingSamples

Sything Control

存储用于创建集群 工作负载模型 的指标示例。

要确保在自动创建的主题中 禁用 了日志紧凑,请确保配置 Cruise Control Metrics Reporter,如 第 14.3 节 “部署 Cruise 控制指标报告器” 所述。日志紧凑可以删除 Cruise Control 所需的记录,并阻止其正常工作。

14.5. 优化目标概述

为了重新平衡 Kafka 集群,Cruise Control 使用优化目标来生成 优化方法。优化目标是针对 Kafka 集群内工作负载重新分配和资源利用率的限制。

红帽企业 Linux 上的 AMQ 流支持 Cruise Control 项目中开发的所有优化目标。支持的目标(按默认降序排列)如下:

  1. 机架感知
  2. 每个代理针对一组主题的领导副本最少数量
  3. 副本容量
  4. 容量:磁盘容量、网络入站容量、网络出站容量
  5. CPU 容量
  6. 副本发布
  7. 潜在的网络输出
  8. 资源分布:磁盘利用率分布、网络入站利用率分布、网络出站利用率分布
  9. 领导字节速率分布
  10. 主题副本发布
  11. CPU 用量分布
  12. 领导程序副本发布
  13. 首选领导选举机制
  14. Kafka Assigner 磁盘用量分布
  15. Broker 磁盘容量
  16. Broker 磁盘内部使用情况

有关每个优化目标的更多信息,请参阅 Cruise Control Wiki 中的目标

清理控制属性文件中的目标配置

您可以在 cruise-control/config/ 目录中的 cruisecontrol.properties 文件中配置优化目标。有些配置必须满足 优化目标,以及 默认 优化目标。

用户提供的可选 优化目标在运行时被设置为请求 /rebalance 端点的参数。

优化目标受到 broker 资源的任何 容量限制

以下小节更详细地描述了每个目标配置。

主优化目标

主优化目标适用于所有用户。主优化目标中没有列出的目标不适用于 Cruise 控制操作。

cruisecontrol.properties 文件中以降序为优先级顺序在 goals 属性中预先设置以下 master 优化目标:

RackAwareGoal; MinTopicLeadersPerBrokerGoal; ReplicaCapacityGoal; DiskCapacityGoal; NetworkInboundCapacityGoal; NetworkOutboundCapacityGoal; ReplicaDistributionGoal; PotentialNwOutGoal; DiskUsageDistributionGoal; NetworkInboundUsageDistributionGoal; NetworkOutboundUsageDistributionGoal; CpuUsageDistributionGoal; TopicReplicaDistributionGoal; LeaderReplicaDistributionGoal; LeaderBytesInDistributionGoal; PreferredLeaderElectionGoal

为简单起见,我们建议您不要更改预先设定的主优化目标,除非您需要完全排除一个或多个目标用于生成优化调整。如果需要,可以在配置默认优化目标时修改主优化目标的优先级顺序。

如果您需要修改预先设定的主优化目标,请在 goals 属性中指定一个目标列表,按优先级降序排列。使用完全限定域名,如 cruisecontrol.properties 文件中所示。

您必须至少指定一个主目标,否则 Cruise Control 将崩溃。

注意

如果您更改了预先设置的主优化目标,您必须确保配置的 hard.goals 是您配置的主优化目标的子集。否则,生成优化时会出现错误。

硬目标和软目标

硬目标就是在优化调整时 必须满足 的目标。未配置为硬目标的目标称为 软目标。您可以将软目标视为 最佳工作 目标:它们在优化调整时不需要满足,而是包含在优化计算中。

粗体控件将计算出符合所有硬目标和尽可能多的软目标(按优先顺序)的优化条件。无法 满足所有硬目标的优化建议被拒绝,不会发送给用户。

注意

例如,您可能有一个软目标来在集群中平均分发主题的副本(主题副本分发目标)。如果这样做能够实现所有配置的硬目标,挑战控制将忽略此目标。

以下主优化目标作为 cruisecontrol.properties 文件中的 hard.goals 属性中的硬目标预先设定:

RackAwareGoal; MinTopicLeadersPerBrokerGoal; ReplicaCapacityGoal; DiskCapacityGoal; NetworkInboundCapacityGoal; NetworkOutboundCapacityGoal; CpuCapacityGoal

要更改硬目标,请使用完全限定域名编辑 hard.goals 属性并指定所需的目标。

增加硬目标数量可降低Cruise控制计算和生成有效优化结果的可能性。

默认优化目标

精简控制 使用默认的优化目标 列表来生成 缓存的优化建议。如需更多信息,请参阅 第 14.6 节 “优化调整概述”

您可以通过设置 用户提供的优化目标,在运行时覆盖默认优化目标

cruisecontrol.properties 文件中按降序顺序在 default.goals 属性中预先设置以下默认优化目标:

RackAwareGoal; MinTopicLeadersPerBrokerGoal; ReplicaCapacityGoal; DiskCapacityGoal; NetworkInboundCapacityGoal; NetworkOutboundCapacityGoal; CpuCapacityGoal; ReplicaDistributionGoal; PotentialNwOutGoal; DiskUsageDistributionGoal; NetworkInboundUsageDistributionGoal; NetworkOutboundUsageDistributionGoal; CpuUsageDistributionGoal; TopicReplicaDistributionGoal; LeaderReplicaDistributionGoal; LeaderBytesInDistributionGoal

您必须至少指定一个默认目标,否则 Cruise Control 将崩溃。

要修改默认优化目标,请在 default.goals 属性中以降序排列为目标列表。默认目标必须是主优化目标的子集;使用完全限定域名。

用户提供的优化目标

用户提供的优化目标 缩小了针对特定优化建议配置的默认目标。您可以根据需要将它们设置为对 /rebalance 端点的 HTTP 请求中的参数。如需更多信息,请参阅 第 14.9 节 “生成优化分析”

用户提供的优化目标可针对不同的情景生成优化。例如,您可能想要在 Kafka 集群间优化领导副本分布,而不考虑磁盘容量或磁盘使用率。因此,您向 /rebalance 端点发送请求,其中包含领导副本分发的单一目标。

用户提供的优化目标必须:

要忽略优化建议中配置的硬目标,请在请求中添加 skip_hard_goals_check=true 参数。

其它资源

14.6. 优化调整概述

优化建议是建议 的更改摘要,如果应用这些更改,则会生成更加均衡的 Kafka 集群,在代理之间更均匀地分配分区工作负载。每个优化建议都基于用于生成 目标的一组优化目标,受代理资源配置 容量限制 的影响。

当您向 /rebalance 端点发出 POST 请求时,会返回一个优化建议。使用提议中的信息,决定是否根据建议启动集群重新平衡。或者,您可以更改优化目标,然后产生另一个建议。

默认情况下,优化优化会生成为空 运行,必须单独启动。对可生成的优化说明数量没有限制。

缓存优化建议

整合控制根据配置 的默认 优化目标维护缓存优化 建议。从工作负载模型生成的缓存优化建议每 15 分钟更新一次,以反映 Kafka 集群的当前状态。

使用以下目标配置时会返回最新的缓存优化建议:

  • 默认优化目标
  • 用户提供的优化目标,可被当前缓存的建议实现

要更改缓存的优化建议刷新间隔,编辑 cruisecontrol.properties 文件中的 proposal.expiration.ms 设置。为快速更改集群考虑一个较短的间隔,尽管这会增加 Cruise Control 服务器上的负载。

优化调整的内容

下表描述了优化建议中包含的属性。

表 14.2. 优化建议中包含的属性
属性描述

n inter-broker replica (y MB) moves

n: 在独立代理之间移动的分区副本数。

重新平衡操作期间的性能影响 :相对高.

y MB:将移动到独立代理的每个分区副本的大小总和。

重新平衡操作期间的性能影响 :变量.MB 数量越多,群集重新平衡将需要的时间就越长。

n intra-broker replica (y MB) moves

n:群集代理磁盘之间传输的分区副本总数。

重新平衡操作过程中的性能影响 :相对较高,但小于 inter-broker replica moves

y MB:在同一代理的磁盘之间移动的每个分区副本的大小总和。

重新平衡操作期间的性能影响 :变量.数量越大,集群重新平衡所需的时间也越长。同一代理的磁盘之间移动大量数据的影响小于不同代理之间的影响(请参阅 inter-broker replica moves)。

n excluded topics

优化建议中分区副本/领导移动计算中排除的主题数量。

您可以通过以下方法之一排除主题:

cruisecontrol.properties 文件中,在 topics.excluded.from.partition.movement 属性中指定一个正则表达式。

在到 /rebalance 端点的 POST 请求中,在 excluded_topics 参数中指定一个正则表达式。

与正则表达式匹配的主题列在响应中,并将从群集重新平衡中排除。

n leadership moves

n: 领导者将切换到不同副本的分区数量。这涉及对 ZooKeeper 配置的更改。

重新平衡操作期间的性能影响 :相对较低的.

n recent windows

n:优化建议所基于的指标窗口数量。

n% of the partitions covered

n%: Kafka 集群中分区的百分比包括在优化建议中。

On-demand Balancedness Score Before (nn.yyy) After (nn.yyy)

测量 Kafka 集群的整体平衡。

整合控制根据多个因素为每个优化目标分配 Balancedness Score,包括优先级(目标在 default.goals 或用户提供的目标列表中的位置)。On-demand Balancedness Score 计算方式是从 100 中减去每个违反的软目标的 Balancedness Score 的总和。

Before 分数基于 Kafka 集群的当前配置。After 分数基于生成的优化建议。

14.7. 重新平衡性能调优概述

您可以为集群重新平衡调整几个性能调整选项。这些选项控制如何执行重新平衡中的副本和领导移动,以及分配给重新平衡操作的带宽。

分区重新分配命令

优化调整 由单独的分区重新分配命令组成。当您发起一个建议时,Cruise Control 服务器将这些命令应用到 Kafka 集群。

分区重新分配命令由以下任一操作类型组成:

  • 分区移动 :将分区副本及其数据传输到新位置。分区移动可采用以下两种形式之一:

    • Broker 移动:分区副本移到不同代理上的日志目录中。
    • Broker 内部移动:分区副本移到同一代理上的不同日志目录中。
  • 领导移动 :切换分区副本的领导机。

批量将控制问题的分区重新分配给 Kafka 集群的命令。集群在重新平衡期间的性能会受到每个批处理中包含的每种移动类型的数量的影响。

要配置分区重新分配命令,请参阅 重新平衡调整选项

副本移动策略

集群重新平衡性能还受到应用于分区重新分配命令 的副本移动策略 的影响。默认情况下,Cruise Control 使用 BaseReplicaMovementStrategy,它按照生成命令的顺序应用命令。但是,如果在建议早期存在一些非常大的分区重新分配,此策略可能会减慢其他重新分配的应用速度。

海军控件提供了三种备选副本移动策略,可用于优化调整:

  • PrioritizeSmallReplicaMovementStrategy:按升序大小重新分配.
  • PrioritizeLargeReplicaMovementStrategy:以降序大小重新分配.
  • PostponeUrpReplicaMovementStrategy:优先分配没有同步副本的分区副本。

这些策略可以配置为序列。第一种策略尝试使用其内部逻辑比较两个分区重新分配。如果重新分配是等效的,那么它会将它们传递给序列中的下一个策略,以确定顺序,以此类推。

要配置副本移动策略,请参阅 重新平衡调优选项

重新平衡调优选项

cruise Control 提供多个配置选项来调优重新平衡参数。这些选项使用以下方法设置:

  • cruisecontrol.properties 文件中作为属性默认 Cruise Control 配置
  • 作为 POST 请求中的 /rebalance 端点的参数

下表总结了这两种方法的相关配置。

表 14.3. 重新平衡性能调优配置
属性和请求参数配置描述默认值

num.concurrent.partition.movements.per.broker

每个分区重新分配批次中broker 分区移动的最大数量

5

concurrent_partition_movements_per_broker

num.concurrent.intra.broker.partition.movements

每个分区重新分配批次中broker 分区移动的最大数量

2

concurrent_intra_broker_partition_movements

num.concurrent.leader.movements

每个分区重新分配批中分区领导更改的最大数量

1000

concurrent_leader_movements

default.replication.throttle

分配给分区重新分配的带宽(以字节/秒为单位)

Null(无限制)

replication_throttle

default.replica.movement.strategies

用于确定执行分区重新分配命令的顺序的策略列表(按优先级顺序排列)。有三种策略: PrioritizeSmallReplicaMovementStrategyPrioritizeLargeReplicaMovementStrategyPostponeUrpReplicaMovementStrategy

对于 属性,使用以逗号分隔的策略类完全限定名称列表(在每个类名称的开头中添加 com.linkedin.kafka.cruisecontrol.executor.strategy. )。

对于 参数,请使用副本移动策略的类名称以逗号分隔的列表。

BaseReplicaMovementStrategy

replica_movement_strategies

更改默认设置会影响重新平衡完成所需的时间,以及重新平衡过程中在 Kafka 集群上放置的负载。使用较低值可以减少负载,但会增加所需时间,反之亦然。

其它资源

  • Cruise Control Wiki 中的 配置.
  • Cruise Control Wiki 中的 REST API.

14.8. 精简控制配置

config/cruisecontrol.properties 文件包含 Cruise Control 的配置。该文件由以下类型之一的属性组成:

  • 字符串
  • 数字
  • 布尔值

您可以指定和配置 Cruise Control Wiki 的 Configurations 部分中列出的所有属性。

容量配置

取胜控制使用 容量限制 来确定某些基于资源的优化目标是否被破坏。如果将一个或多个基于资源的目标设定为困难目标,然后破坏,则尝试进行优化会失败。这可以防止使用优化建议生成优化建议。

您可以在以下三个 .json 文件中为 Kafka 代理资源指定容量限值 cruise-control/config

  • capacityJBOD.json: 用于 JBOD Kafka 部署(默认文件)。
  • capacity.json: 用于非 JBOD Kafka 部署,每个代理都有相同数量的 CPU 内核。
  • capacityCores.json: 用于非 JBOD Kafka 部署,每个代理都有不同数量的 CPU 内核。

cruisecontrol.properties 中的 capacity.config.file 属性中设置文件。所选文件将用于代理容量解析。例如:

capacity.config.file=config/capacityJBOD.json

可以在描述的单元中为以下代理资源设置容量限制:

  • DISK: MB 的磁盘存储
  • CPU: CPU 使用率作为百分比(0-100)或作为内核数
  • NW_IN: 入站网络吞吐量(以 KB/秒为单位)
  • NW_OUT: 出站网络吞吐量(以 KB/秒为单位)

要将相同的容量限制应用到 Cruise Control 监控的每个代理,请为代理 ID -1 设置容量限制。要为各个代理设置不同的容量限值,请指定每个代理 ID 及其容量配置。

容量限制配置示例

{
  "brokerCapacities":[
    {
      "brokerId": "-1",
      "capacity": {
        "DISK": "100000",
        "CPU": "100",
        "NW_IN": "10000",
        "NW_OUT": "10000"
      },
      "doc": "This is the default capacity. Capacity unit used for disk is in MB, cpu is in percentage, network throughput is in KB."
    },
    {
      "brokerId": "0",
      "capacity": {
        "DISK": "500000",
        "CPU": "100",
        "NW_IN": "50000",
        "NW_OUT": "50000"
      },
      "doc": "This overrides the capacity for broker 0."
    }
  ]
}

如需更多信息,请参阅 在 Cruise Control Wiki 中填充容量配置文件

Cruise Control Metrics 主题的日志清理策略

自动创建的 __CruiseControlMetrics 主题(请参阅自动创建 的主题)包含 DELETE 而不是 COMPACT 的日志清理策略非常重要。否则,可能会删除 Cruise Control 所需的记录。

第 14.3 节 “部署 Cruise 控制指标报告器” 所述,在 Kafka 配置文件中设置以下选项可确保正确设置 COMPACT 日志清理策略:

  • cruise.control.metrics.topic.auto.create=true
  • cruise.control.metrics.topic.num.partitions=1
  • cruise.control.metrics.topic.replication.factor=1

如果在 Cruise Control Metrics Reporter(cruise.control.metrics.topic.auto.create=false)中 禁用 了主题自动创建,但在 Kafka 集群中 启用了,则代理仍然会自动创建 __CruiseControlMetrics 主题。在这种情况下,您必须使用 kafka-configs.sh 工具将 __CruiseControlMetrics 主题的日志清理策略改为 DELETE

  1. 获取 __CruiseControlMetrics 主题的当前配置:

    bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --entity-type topics --entity-name __CruiseControlMetrics --describe
  2. 更改主题配置中的日志清理策略:

    bin/kafka-configs.sh --bootstrap-server <BrokerAddress> --entity-type topics --entity-name __CruiseControlMetrics --alter --add-config cleanup.policy=delete

如果在 Cruise Control Metrics Reporter Kafka 集群中 禁用 了主题自动创建,则必须手动创建 __CruiseControlMetrics 主题,然后使用 kafka-configs.sh 工具将其配置为使用 DELETE 日志清理策略。

如需更多信息,请参阅 第 5.9 节 “修改主题配置”

日志记录配置

精简控制对所有服务器日志使用 log4j1。要更改默认配置,编辑 /opt/cruise-control/config/log4j.properties 中的 log4j.properties 文件。

您必须重新启动 Cruise Control 服务器,然后更改才会生效。

14.9. 生成优化分析

当您向 /rebalance 端点发出 POST 请求时,Cruise Control 会根据提供的优化目标生成一个优化建议来重新平衡 Kafka 集群。

优化建议生成为空 运行,除非提供了 dryrun 参数并将其设置为 false。在"死运行模式"中,Cruise Control 生成优化建议和预计的结果,但不通过重新平衡集群来启动建议。

您可以分析优化建议中返回的信息,并决定是否启动它。

以下是对 /rebalance 端点的请求的关键参数。有关所有可用参数的详情,请查看 Cruise Control Wiki 中的 REST API

dryrun

type: boolean, default: true

告知 Cruise Control,您是否只想生成优化建议(true),还是生成优化建议并执行集群重新平衡(false)。

dryrun=true (默认)时,您还可以传递 verbose 参数来返回有关 Kafka 集群状态的更多详细信息。这包括应用优化建议前后每个 Kafka 代理负载的指标,以及之前和之后的值之间的区别。

excluded_topics

类型:regex

与优化建议计算中排除的主题匹配的正则表达式。

goals

type: 字符串列表,默认为:配置的 default.goals 列表

用于准备优化建议的用户提供的优化目标列表。如果没有提供目标,则使用 cruisecontrol.properties 文件中的 default.goals 列表。

skip_hard_goals_check

类型:布尔值,默认: false

默认情况下,Cruise Control 检查用户提供的优化目标(在 goals 参数中)是否包含所有配置的硬目标(在 hard.goals中)。如果您提供不是配置的 hard.goals 子集的目标,请求会失败。

如果要生成带有用户提供的优化目标(不包括所有配置的 hard.goals )的优化建议,请将 skip_hard_goals_check 设置为 true

json

类型:布尔值,默认: false

控制 Cruise 控制服务器返回的响应类型。如果没有提供,或设置为 false,Cruise Control 会返回格式化的文本以显示在命令行中。如果要以编程方式提取返回的信息元素,请设置 json=true。这将返回可传送到 jq 等工具的 JSON 格式文本,或者在脚本和程序中解析。

verbose

类型:布尔值,默认: false

控制 Cruise 控制服务器返回的响应详情级别。可以与 dryrun=true 一起使用。

先决条件

  • kafka 和 ZooKeeper 正在运行
  • 英镑控件正在运行

流程

  1. 要为控制台生成格式化的"dry run"优化建议,请向 /rebalance 端点发送 POST 请求。

    • 使用配置的 default.goals

      curl -v -X POST 'cruise-control-server:9090/kafkacruisecontrol/rebalance'

      缓存优化建议会立即返回。

      注意

      如果返回 NotEnoughValidWindows,Cruise Control 还没有记录足够的指标数据来生成优化建议。等待几分钟,然后重新发送请求。

    • 要指定用户提供的优化目标而不是配置的 default.goals,请在 goals 参数中指定一个或多个目标:

      curl -v -X POST 'cruise-control-server:9090/kafkacruisecontrol/rebalance?goals=RackAwareGoal,ReplicaCapacityGoal'

      如果它满足提供的目标,则立即返回缓存的优化建议。否则,将使用提供的目标生成新的优化建议;计算所需的时间要长。您可以通过在请求中添加 ignore_proposal_cache=true 参数来强制实施此行为。

    • 要指定用户提供的优化目标,请在请求中添加所有配置的硬目标: skip_hard_goal_check=true

      curl -v -X POST 'cruise-control-server:9090/kafkacruisecontrol/rebalance?goals=RackAwareGoal,ReplicaCapacityGoal,ReplicaDistributionGoal&skip_hard_goal_check=true'
  2. 查看响应中包含的优化建议。属性描述待处理的集群重新平衡操作。

    该提议包含建议优化的高级摘要,后跟每个默认优化目标的摘要,以及建议执行后的预期集群状态。

    请特别注意以下信息:

    • Cluster load after rebalance 概述。如果满足您的要求,则应使用高级别摘要评估提议更改的影响。
    • n inter-broker replica (y MB) moves 指明代理之间将在网络间移动多少数据。这个值越大,在重新平衡过程中对 Kafka 集群性能的影响会更大。
    • n intra-broker replica (y MB) moves 指示代理本身(磁盘之间)移动多少数据。这个值越大,对单个代理的潜在性能影响更大(尽管小于 n inter-broker replica (y MB) moves)。
    • 领导力的数量变化。这会在重新平衡过程中对集群性能产生可忽略的影响。
异步响应

Cruise Control REST API 端点默认在 10 秒后超时,但请求生成在服务器上继续进行。如果最新的缓存优化建议未就绪,或者用户使用 ignore_proposal_cache=true 指定用户提供的优化目标,则可能会出现超时。

要允许您稍后检索优化建议,请记下请求的唯一标识符,该标识符在来自 /rebalance 端点的响应标头中给出。

要使用 curl 获取响应,请指定详细(-v)选项:

curl -v -X POST 'cruise-control-server:9090/kafkacruisecontrol/rebalance'

以下是标头示例:

* Connected to cruise-control-server (::1) port 9090 (#0)
> POST /kafkacruisecontrol/rebalance HTTP/1.1
> Host: cc-host:9090
> User-Agent: curl/7.70.0
> Accept: /
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 01 Jun 2020 15:19:26 GMT
< Set-Cookie: JSESSIONID=node01wk6vjzjj12go13m81o7no5p7h9.node0; Path=/
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< User-Task-ID: 274b8095-d739-4840-85b9-f4cfaaf5c201
< Content-Type: text/plain;charset=utf-8
< Cruise-Control-Version: 2.0.103.redhat-00002
< Cruise-Control-Commit_Id: 58975c9d5d0a78dd33cd67d4bcb497c9fd42ae7c
< Content-Length: 12368
< Server: Jetty(9.4.26.v20200117-redhat-00001)

如果优化建议未在超时内就绪,您可以重新提交 POST 请求,这一次在标头中包含原始请求的 User-Task-ID

curl -v -X POST -H 'User-Task-ID: 274b8095-d739-4840-85b9-f4cfaaf5c201' 'cruise-control-server:9090/kafkacruisecontrol/rebalance'

14.10. 启动集群重新平衡

如果您对优化建议满意,可以指示 Cruise Control 启动集群重新平衡并开始重新分配分区,如建议中所述。

在生成优化建议和启动集群重新平衡之间尽量少的时间。如果自您生成原始优化建议后经过一段时间,集群状态可能会改变。因此,启动的集群重新平衡可能与您检查的集群不同。若有疑问,首先生成新的优化建议。

次只能有一个集群重新平衡状态为"活动"的。

流程

  1. 要执行最近生成的优化建议,请使用 dryrun=false 参数向 /rebalance 端点发送 POST 请求:

    curl -X POST 'cruise-control-server:9090/kafkacruisecontrol/rebalance?dryrun=false'

    cruise Control 会启动集群重新平衡并返回优化建议。

  2. 检查优化建议中概述的更改。如果更改不是您预期的,您可以 停止重新平衡
  3. 使用 /user_tasks 端点检查集群重新平衡的进度。正在进行的集群重新平衡状态为"活动"。

    查看在 Cruise Control 服务器中执行的所有集群重新平衡任务:

    curl 'cruise-control-server:9090/kafkacruisecontrol/user_tasks'
    
    USER TASK ID      CLIENT ADDRESS  START TIME     STATUS  REQUEST URL
    c459316f-9eb5-482f-9d2d-97b5a4cd294d  0:0:0:0:0:0:0:1       2020-06-01_16:10:29 UTC  Active      POST /kafkacruisecontrol/rebalance?dryrun=false
    445e2fc3-6531-4243-b0a6-36ef7c5059b4  0:0:0:0:0:0:0:1       2020-06-01_14:21:26 UTC  Completed   GET /kafkacruisecontrol/state?json=true
    05c37737-16d1-4e33-8e2b-800dee9f1b01  0:0:0:0:0:0:0:1       2020-06-01_14:36:11 UTC  Completed   GET /kafkacruisecontrol/state?json=true
    aebae987-985d-4871-8cfb-6134ecd504ab  0:0:0:0:0:0:0:1       2020-06-01_16:10:04 UTC
  4. 要查看特定集群重新平衡任务的状态,请提供 user-task-ids 参数和任务 ID:

    curl 'cruise-control-server:9090/kafkacruisecontrol/user_tasks?user_task_ids=c459316f-9eb5-482f-9d2d-97b5a4cd294d'

14.11. 停止活跃的集群重新平衡

您可以停止当前正在进行的集群重新平衡。

这指示 Cruise Control 完成当前的一组分区重新分配,然后停止重新平衡。重新平衡停止后,已完成的分区重新分配已被应用;因此,与重新平衡操作开始前相比,Kafka 集群的状态会有所不同。如果需要进一步重新平衡,您应该生成一个新的优化建议。

注意

Kafka 集群处于中间(停止)状态的性能可能比初始状态差。

先决条件

  • 集群重新平衡正在进行中(通过"活动"状态表示)。

流程

  • /stop_proposal_execution 端点发送 POST 请求:

    curl -X POST 'cruise-control-server:9090/kafkacruisecontrol/stop_proposal_execution'

第 15 章 分布式追踪

分布式追踪允许您跟踪分布式系统中应用程序之间的事务处理进度。在微服务架构中,跟踪服务之间的事务处理进度。跟踪数据可用于监控应用性能以及调查目标系统和最终用户应用的问题。

在 Red Hat Enterprise Linux 上的 AMQ Streams 中,追踪有助于端到端跟踪信息:从源系统到 Kafka,然后从 Kafka 至目标系统和应用程序。追踪补充了可用的 JMX 指标

AMQ 流如何支持追踪

为以下客户端和组件提供了对追踪的支持:

Kafka 客户端:

  • Kafka 生产者和消费者
  • Kafka Streams API 应用程序

Kafka 组件:

  • Kafka Connect
  • Kafka Bridge
  • MirrorMaker
  • MirrorMaker 2.0

要启用追踪,您需要执行四个高级别任务:

  1. 启用 Jaeger tracer。
  2. 启用 Interceptors:

  3. 设置 追踪环境变量.
  4. 部署客户端或组件。

检测后,客户端会生成 trace 数据。例如,在生成消息或写入偏移到日志中时。

trace 会根据抽样策略进行抽样,然后在 Jaeger 用户界面中视觉化。

注意

Kafka 代理不支持追踪。

为 AMQ Streams 以外的应用和系统设置追踪不在本章的讨论范围之内。要了解有关此主题的更多信息,请在 OpenTracing 文档中的 搜索"注入和提取"。

流程概述

要设置 AMQ Streams 的追踪,请按照以下步骤操作:

先决条件

  • Jaeger 后端组件部署到主机操作系统中。有关部署说明,请参阅 Jaeger 部署文档

15.1. OpenTracing 和 Jaeger 概述

AMQ Streams 使用 OpenTracing 和 Jaeger 项目。

OpenTracing 是一种独立于追踪或监控系统的 API 规范。

  • OpenTracing API 用于 检测 应用程序代码
  • 工具的应用程序为分布式系统的个别交易生成 追踪
  • trace 由定义了特定工作单元的 span 组成

Jaeger 是用于基于微服务的分布式系统的追踪系统。

  • Jaeger 实现 OpenTracing API,并为检测提供客户端库
  • Jaeger 用户界面允许您查询、过滤和分析 trace 数据

A simple query in the Jaeger user interface

其它资源

15.2. 为 Kafka 客户端设置追踪

初始化 Jaeger tracer,以检测客户端应用程序进行分布式追踪。

15.2.1. 为 Kafka 客户端初始化 Jaeger tracer

使用一组 追踪环境变量 配置并初始化 Jaeger 追踪器。

流程

在每个客户端应用程序中:

  1. 将 Jaeger 的 Maven 依赖项添加到客户端应用程序的 pom.xml 文件中:

    <dependency>
        <groupId>