oldme 博客

未来是一张全然透明,字迹难辨的信笺

Docker 部署 Kafka 单/多节点

oldme create: 2023-07-03

Kafka 是很成功的一个消息队列,今天和大家分享如何使用 dokcer-compose 部署单节点/多节点 Kafka,并安装 Kafka-manager 可视化工具来管理 Kafka 集群。

今天是奥地利-匈牙利帝国的作家弗朗茨·卡夫卡诞生的 140 周年。Kafka 消息队列的名字正是源自于这位伟大的作家。

生命之所以有意义,是因为它会停止 —— 弗朗茨·卡夫卡

舞台布置

在下的舞台环境如下:

  • Ubuntu 22.04.2-Server
  • Docker 24.0.2
  • Docker-compose 2.18.1
  • Kafka 镜像 wurstmeister/kafka:latest (2.13-2.81)
  • Zookeeper 镜像 wurstmeister/zookeeper:latest (3.4.6)
  • Kafka-manager 镜像 sheepkiller/kafka-manager

安装 docker 和 dokcer-compose 不必多说,网上有大把教程。kafka 必须依赖 zookeeper 才能正常运行,所以安装 zookeeper 必不可少,Kafka-manager 是一个可视化的 Kafka 管理工具,可装可不装。

配置 Docker 代理

如果拉取速度还可以,可以略过此步。配置代理地址:编辑 /etc/docker/daemon.json,如果该文件不存在,需要先创建。daemon.json 内容如下:

{
    "registry-mirrors": [
        "https://ung2thfc.mirror.aliyuncs.com",
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com",
        "https://docker.mirrors.ustc.edu.cn"
    ]
}

重启 docker 使配置生效:

systemctl restart docker

输入命令查看代理是否配置成功:

docker info

出现红框内容则代表配置成功。

部署单节点

创建一个 docker-compose.yml 文件,存放位置无特殊要求,笔者这里存放在 /home/docker 下,最终的效果如下:

编辑 docker-compose.yml,键入以下内容:

version: "3.7"
services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
    container_name: "zookeeper"
    environment:
      # 设置时区
      TZ: CST-8
    restart: always

  kafka1:
    image: wurstmeister/kafka
    container_name: "kafka1"
    ports:
      - "9092:9092"
    environment:
      # 设置时区
      TZ: CST-8
      # 设置zookeeper地址,同网段的容器之间可以通过容器名访问
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      # kafka 服务对客户端的监听地址,192.168.10.43是宿主机IP
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.10.43:9092
      # broker 监听地址 
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      # 关闭自动创建topic,这个配置也可以不要
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: false
    restart: always

这里简单的说一下环境变量 KAFKA_ADVERTISED_LISTENERSKAFKA_LISTENERS,前者是 Kafka 服务对客户端提供的访问地址,后者是 Kafka 内部通讯用的。KAFKA_AUTO_CREATE_TOPICS_ENABLE 配置 topic 是否自动创建,当关闭时,生产者对未创建的 topic 发布信息会抛出错误,反之会自动创建。

docker-compose.yml 编辑成功后,进入其所在目录,执行命令:

docker-compose up -d

此时 Docker 就会自动拉取镜像并创建容器,如果拉取镜像速度慢,请参考上文配置 Docker 代理。容器创建完成后的效果:

查看服务注册

进入 Zookeeper 容器内部,查看 Kafka 的注册节点:

# 进入容器
docker exec -it zookeeper bash
# 执行 ZkCli.sh
/opt/zookeeper-3.4.13/bin/zkCli.sh
# 输入 zookeeper 命令查看注册节点
ls /brokers/ids

效果如图:

这个 1001 就是 breker id。

创建 Topic

进入 kafka 容器创建一个 topic:

docker exec -it kafka1 bash
# 进入命令行工具目录
cd /opt/kafka/bin
# 使用命令行工具创建一个名为 mytopic 的 topic
kafka-topics.sh --create --topic mytopic --bootstrap-server 192.168.10.43:9092

生产/消费信息

kafka-console-producer.sh --broker-list 192.168.10.43:9092 --topic mytopic

之后会弹出一个输入框,就可以在此向 mytopic 生成信息辣。

消费信息:

# 打开一个新的窗口,用来获取消费信息
kafka-console-consumer.sh --bootstrap-server 192.168.10.43:9092 --topic mytopic

效果图:

A窗口:

B窗口:

在 A 窗口输入的值都会在 B 窗口中显示。

UI 页面管理 Kafka

单节点部署完成后我们先不着急部署多节点,先来安装一个可视化工具来管理kafka,在 docker-compose.yml 中键入以下配置:

version: "3.7"
services:
  zookeeper:
    ...

  kafka-manager:
    image: sheepkiller/kafka-manager
    container_name: "kafka-manager"
    ports:
      - "9000:9000"
    environment:
      TZ: CST-8
      # 指定zookeeper地址
      ZK_HOSTS: zookeeper:2181

  kafka1:
    ...

然后执行命令更新容器:

docker-compose up -d

执行完成后可以看到我们有三个容器:

容器正常运行后在浏览器输入宿主机 IP:9000,即可看到访问页面:

添加一个集群:

填写集群配置信息,zookeeper 的地址要写对,格式是 IP:Port,这里的 IP 是 zookeeper,是因为容器之间可以使用别名访问。

保存之后就可以看到集群的信息了:

部署多节点

继续编辑 docker-compose.yml 文件,加入新的 Kafka 节点,最终的 docker-compose.yml 如下:

version: "3.7"
services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
    container_name: "zookeeper"
    environment:
      TZ: CST-8
    restart: always

  kafka-manager:
    image: sheepkiller/kafka-manager
    container_name: "kafka-manager"
    ports:
      - "9000:9000"
    environment:
      TZ: CST-8
      ZK_HOSTS: zookeeper:2181

  kafka1:
    image: wurstmeister/kafka
    container_name: "kafka1"
    ports:
      - "9092:9092"
    environment:
      TZ: CST-8
      KAFKA_NUM_PARTITIONS: 5
      KAFKA_DEFAULT_REPLICATION_FACTOR: 3
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.10.43:9092
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: false
    restart: always

  kafka2:
    image: wurstmeister/kafka
    container_name: "kafka2"
    ports:
      - "9093:9093"
    environment:
      TZ: CST-8
      KAFKA_NUM_PARTITIONS: 5
      KAFKA_DEFAULT_REPLICATION_FACTOR: 3
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.10.43:9093
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9093
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: false
    restart: always
    
  kafka3:
    image: wurstmeister/kafka
    container_name: "kafka3"
    ports:
      - "9094:9094"
    environment:
      TZ: CST-8
      KAFKA_NUM_PARTITIONS: 5
      KAFKA_DEFAULT_REPLICATION_FACTOR: 3
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.10.43:9094
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9094
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: false
    restart: always

这里我们需要注意到 Kafka 中新增了两个环境变量:KAFKA_NUM_PARTITIONSKAFKA_DEFAULT_REPLICATION_FACTOR,前者配置了创建 Topic 时的默认分区数量,后者配置默认分区副本数,也可以在创建 Topic 时手动指定这两个参数。

Kafka 的每个 Topic 是有分区概念的,一个 Topic 的数据会分散在不同的分区中,而分区又可能落在了不同的 Broker 中。那思考一个问题:假使说某个 Broker 故障了,这个 Broker 上保存的分区也就不能访问了,数据也就丢失了。那么 Kafka 是怎么应对这个问题的呢?答案是分区副本,每一个分区都有着好几个分区副本,其中一个是领导者副本,其他是追随者副本。追随者不对外提供服务,所有的请求都由领导者副本所在的 Broker 来处理,追随者副本的唯一任务就是从领导者异步拉取消息,并写入到自己的提交日志中,以实现与领导者数据同步。当领导者副本故障后,就会重新在所有的追随者中选举一个当领导者,即使老的领导者重新上线,也只能做为追随者重新加入。分区副本数不能超出 Broker 数,否则在创建 Topic 的时候会报错。分区副本如果设置的过多会加大同步延迟,浪费储存空间,过少会降低可用性。一般认为分区副本数为 3 具有不错的可靠性和容忍性。

一个 Topic 的分布示意图:

最终效果

把上文编辑好的 docker-compose.yml 运行起来,最终的容器列表:

在浏览器打开管理页面,可以看到集群信息:

至此,我们就完成了 Kafka 多节点部署。

评论

欢迎您的回复 取消回复

您的邮箱不会显示出来,*必填

本文目录