03 | Kafka集群部署

  1.  Kafka基础

Kafka借鉴了JMS规范的思想,但是却并没有完全遵循JMS规范,因此从设计原理上,Kafka的内部也会有很多用于数据传输的组件对象,这些组件对象之间会形成关联,组合在一起实现高效的数据传输。所以接下来,我们就按照数据流转的过程详细讲一讲Kafka中的基础概念以及核心组件。

2.1 集群部署

生产环境都是采用linux系统搭建服务器集群,但是我们的重点是在于学习kafka的基础概念和核心组件,所以这里我们搭建一个简单易用的windows集群方便大家的学习和练习。Linux集群的搭建会在第3章给大家进行讲解。

2.1.1 解压文件

  1. 在磁盘根目录创建文件夹cluster,文件夹名称不要太长

  1. 将kafka安装包kafka-3.6.1-src.tgz解压缩到kafka文件夹

2.1.2 安装ZooKeeper

  1. 修改文件夹名为kafka-zookeeper

因为kafka内置了ZooKeeper软件,所以此处将解压缩的文件作为ZooKeeper软件使用。

  1. 修改config/zookeeper.properties文件

# Licensed to the Apache Software Foundation (ASF) under one or more

# contributor license agreements.  See the NOTICE file distributed with

# this work for additional information regarding copyright ownership.

# The ASF licenses this file to You under the Apache License, Version 2.0

# (the "License"); you may not use this file except in compliance with

# the License.  You may obtain a copy of the License at

#

#    http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

# the directory where the snapshot is stored.

# 此处注意,如果文件目录不存在,会自动创建

dataDir=E:/cluster/kafka-zookeeper/data

# the port at which the clients will connect

# ZooKeeper默认端口为2181

clientPort=2181

# disable the per-ip limit on the number of connections since this is a non-production config

maxClientCnxns=0

# Disable the adminserver by default to avoid port conflicts.

# Set the port to something non-conflicting if choosing to enable this

admin.enableServer=false

# admin.serverPort=8080

2.1.3 安装Kafka

  1. 将上面解压缩的文件复制一份,改名为kafka-node-1

  1. 修改config/server.properties配置文件

# Licensed to the Apache Software Foundation (ASF) under one or more

# contributor license agreements.  See the NOTICE file distributed with

# this work for additional information regarding copyright ownership.

# The ASF licenses this file to You under the Apache License, Version 2.0

# (the "License"); you may not use this file except in compliance with

# the License.  You may obtain a copy of the License at

#

#    http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#

# This configuration file is intended for use in ZK-based mode, where Apache ZooKeeper is required.

# See kafka.server.KafkaConfig for additional details and defaults

#

############################# Server Basics #############################

# The id of the broker. This must be set to a unique integer for each broker.

# kafka节点数字标识,集群内具有唯一性

broker.id=1

############################# Socket Server Settings #############################

# The address the socket server listens on. If not configured, the host name will be equal to the value of

# java.net.InetAddress.getCanonicalHostName(), with PLAINTEXT listener name, and port 9092.

#   FORMAT:

#     listeners = listener_name://host_name:port

#   EXAMPLE:

#     listeners = PLAINTEXT://your.host.name:9092

# 监听器 9091为本地端口,如果冲突,请重新指定

listeners=PLAINTEXT://:9091

# Listener name, hostname and port the broker will advertise to clients.

# If not set, it uses the value for "listeners".

#advertised.listeners=PLAINTEXT://:9091

# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details

#listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL

# The number of threads that the server uses for receiving requests from the network and sending responses to the network

num.network.threads=3

# The number of threads that the server uses for processing requests, which may include disk I/O

num.io.threads=8

# The send buffer (SO_SNDBUF) used by the socket server

socket.send.buffer.bytes=102400

# The receive buffer (SO_RCVBUF) used by the socket server

socket.receive.buffer.bytes=102400

# The maximum size of a request that the socket server will accept (protection against OOM)

socket.request.max.bytes=104857600

############################# Log Basics #############################

# A comma separated list of directories under which to store log files

# 数据文件路径,如果不存在,会自动创建

log.dirs=E:/cluster/kafka-node-1/data

# The default number of log partitions per topic. More partitions allow greater

# parallelism for consumption, but this will also result in more files across

# the brokers.

num.partitions=1

# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.

# This value is recommended to be increased for installations with data dirs located in RAID array.

num.recovery.threads.per.data.dir=1

############################# Internal Topic Settings  #############################

# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state"

# For anything other than development testing, a value greater than 1 is recommended to ensure availability such as 3.

offsets.topic.replication.factor=1

transaction.state.log.replication.factor=1

transaction.state.log.min.isr=1

############################# Log Flush Policy #############################

# Messages are immediately written to the filesystem but by default we only fsync() to sync

# the OS cache lazily. The following configurations control the flush of data to disk.

# There are a few important trade-offs here:

#    1. Durability: Unflushed data may be lost if you are not using replication.

#    2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.

#    3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks.

# The settings below allow one to configure the flush policy to flush data after a period of time or

# every N messages (or both). This can be done globally and overridden on a per-topic basis.

# The number of messages to accept before forcing a flush of data to disk

#log.flush.interval.messages=10000

# The maximum amount of time a message can sit in a log before we force a flush

#log.flush.interval.ms=1000

############################# Log Retention Policy #############################

# The following configurations control the disposal of log segments. The policy can

# be set to delete segments after a period of time, or after a given size has accumulated.

# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens

# from the end of the log.

# The minimum age of a log file to be eligible for deletion due to age

log.retention.hours=168

# A size-based retention policy for logs. Segments are pruned from the log unless the remaining

# segments drop below log.retention.bytes. Functions independently of log.retention.hours.

#log.retention.bytes=1073741824

# The maximum size of a log segment file. When this size is reached a new log segment will be created.

#log.segment.bytes=1073741824

log.segment.bytes=190

log.flush.interval.messages=2

log.index.interval.bytes=17

# The interval at which log segments are checked to see if they can be deleted according

# to the retention policies

log.retention.check.interval.ms=300000

############################# Zookeeper #############################

# Zookeeper connection string (see zookeeper docs for details).

# This is a comma separated host:port pairs, each corresponding to a zk

# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".

# You can also append an optional chroot string to the urls to specify the

# root directory for all kafka znodes.

# ZooKeeper软件连接地址,2181为默认的ZK端口号 /kafka ZK的管理节点

zookeeper.connect=localhost:2181/kafka

# Timeout in ms for connecting to zookeeper

zookeeper.connection.timeout.ms=18000

############################# Group Coordinator Settings #############################

# The following configuration specifies the time, in milliseconds, that the GroupCoordinator will delay the initial consumer rebalance.

# The rebalance will be further delayed by the value of group.initial.rebalance.delay.ms as new members join the group, up to a maximum of max.poll.interval.ms.

# The default value for this is 3 seconds.

# We override this to 0 here as it makes for a better out-of-the-box experience for development and testing.

# However, in production environments the default value of 3 seconds is more suitable as this will help to avoid unnecessary, and potentially expensive, rebalances during application startup.

group.initial.rebalance.delay.ms=0

  1. 将kafka-node-1文件夹复制两份,改名为kafka-node-2,kafka-node-3

  1. 分别修改kafka-node-2,kafka-node-3文件夹中的配置文件server.properties
  • 将文件内容中的broker.id=1分别改为broker.id=2broker.id=3
  • 将文件内容中的9091分别改为90929093(如果端口冲突,请重新设置)
  • 将文件内容中的kafka-node-1分别改为kafka-node-2kafka-node-3

2.1.4 封装启动脚本

因为Kafka启动前,必须先启动ZooKeeper,并且Kafka集群中有多个节点需要启动,所以启动过程比较繁琐,这里我们将启动的指令进行封装。

  1. 在kafka-zookeeper文件夹下创建zk.cmd批处理文件

  1. 在zk.cmd文件中添加内容

# 添加启动命令

call bin/windows/zookeeper-server-start.bat config/zookeeper.properties

  1. 在kafka-node-1,kafka-node-2,kafka-node-3文件夹下分别创建kfk.cmd批处理文件

  1. 在kfk.bat文件中添加内容

# 添加启动命令

call bin/windows/kafka-server-start.bat config/server.properties

  1. 在cluster文件夹下创建cluster.cmd批处理文件,用于启动kafka集群

  1. 在cluster.cmd文件中添加内容

cd kafka-zookeeper

start zk.cmd

ping 127.0.0.1 -n 10 >nul

cd ../kafka-node-1

start kfk.cmd

cd ../kafka-node-2

start kfk.cmd

cd ../kafka-node-3

start kfk.cmd

  1. 在cluster文件夹下创建cluster-clear.cmd批处理文件,用于清理和重置kafka数据

  1. 在cluster-clear.cmd文件中添加内容

cd kafka-zookeeper

rd /s /q data

cd ../kafka-node-1

rd /s /q data

cd ../kafka-node-2

rd /s /q data

cd ../kafka-node-3

rd /s /q data

  1. 双击执行cluster.cmd文件,启动Kafka集群

集群启动命令后,会打开多个黑窗口,每一个窗口都是一个kafka服务,请不要关闭,一旦关闭,对应的kafka服务就停止了。如果启动过程报错,主要是因为zookeeper和kafka的同步问题,请先执行cluster-clear.cmd文件,再执行cluster.cmd文件即可。

2.2 集群启动

2.2.1 相关概念

2.2.1.1 代理:Broker

使用Kafka前,我们都会启动Kafka服务进程,这里的Kafka服务进程我们一般会称之为Kafka Broker或Kafka Server。因为Kafka是分布式消息系统,所以在实际的生产环境中,是需要多个服务进程形成集群提供消息服务的。所以每一个服务节点都是一个broker,而且在Kafka集群中,为了区分不同的服务节点,每一个broker都应该有一个不重复的全局ID,称之为broker.id,这个ID可以在kafka软件的配置文件server.properties中进行配置

############################# Server Basics #############################

# The id of the broker. This must be set to a unique integer for each broker

# 集群ID

broker.id=0

咱们的Kafka集群中每一个节点都有自己的ID,整数且唯一。

主机

kafka-broker1

kafka-broker2

kafka-broker3

broker.id

1

2

3

2.2.1.2 控制器:Controller

Kafka是分布式消息传输系统,所以存在多个Broker服务节点,但是它的软件架构采用的是分布式系统中比较常见的主从(Master - Slave)架构,也就是说需要从多个Broker中找到一个用于管理整个Kafka集群的Master节点,这个节点,我们就称之为Controller。它是Apache Kafka的核心组件非常重要。它的主要作用是在Apache Zookeeper的帮助下管理和协调控制整个Kafka集群。

如果在运行过程中,Controller节点出现了故障,那么Kafka会依托于ZooKeeper软件选举其他的节点作为新的Controller,让Kafka集群实现高可用。

Kafka集群中Controller的基本功能:

  • Broker管理

监听 /brokers/ids节点相关的变化:

    1. Broker数量增加或减少的变化
    2. Broker对应的数据变化
  • Topic管理
    1. 新增:监听 /brokers/topics节点相关的变化
    2. 修改:监听 /brokers/topics节点相关的变化
    3. 删除:监听 /admin/delete_topics节点相关的变化
  • Partation管理
    1. 监听 /admin/reassign_partitions节点相关的变化
    2. 监听 /isr_change_notification节点相关的变化
    3. 监听 /preferred_replica_election节点相关的变化
  • 数据服务
  • 启动分区状态机和副本状态机

2.2.2 启动ZooKeeper

Kafka集群中含有多个服务节点,而分布式系统中经典的主从(Master - Slave)架构就要求从多个服务节点中找一个节点作为集群管理Master,Kafka集群中的这个Master,我们称之为集群控制器Controller

如果此时Controller节点出现故障,它就不能再管理集群功能,那么其他的Slave节点该如何是好呢?

如果从剩余的2个Slave节点中选一个节点出来作为新的集群控制器是不是一个不错的方案,我们将这个选择的过程称之为:选举(elect)。方案是不错,但是问题就在于选哪一个Slave节点呢?不同的软件实现类似的选举功能都会有一些选举算法,而Kafka是依赖于ZooKeeper软件实现Broker节点选举功能。

ZooKeeper如何实现Kafka的节点选举呢?这就要说到我们用到ZooKeeper的3个功能:

  • 一个是在ZooKeeper软件中创建节点Node,创建一个Node时,我们会设定这个节点是持久化创建,还是临时创建。所谓的持久化创建,就是Node一旦创建后会一直存在,而临时创建,是根据当前的客户端连接创建的临时节点Node,一旦客户端连接断开,那么这个临时节点Node也会被自动删除,所以这样的节点称之为临时节点。
  • ZooKeeper节点是不允许有重复的,所以多个客户端创建同一个节点,只能有一个创建成功。
  • 另外一个是客户端可以在ZooKeeper的节点上增加监听器,用于监听节点的状态变化,一旦监听的节点状态发生变化,那么监听器就会触发响应,实现特定监听功能。

有了上面的三个知识点,我们这里就介绍一下Kafka是如何利用ZooKeeper实现Controller节点的选举的:

  1. 第一次启动Kafka集群时,会同时启动多个Broker节点,每一个Broker节点就会连接ZooKeeper,并尝试创建一个临时节点 /controller
  2. 因为ZooKeeper中一个节点不允许重复创建,所以多个Broker节点,最终只能有一个Broker节点可以创建成功,那么这个创建成功的Broker节点就会自动作为Kafka集群控制器节点,用于管理整个Kafka集群。
  3. 没有选举成功的其他Slave节点会创建Node监听器,用于监听 /controller节点的状态变化。
  4. 一旦Controller节点出现故障或挂掉了,那么对应的ZooKeeper客户端连接就会中断。ZooKeeper中的 /controller 节点就会自动被删除,而其他的那些Slave节点因为增加了监听器,所以当监听到 /controller 节点被删除后,就会马上向ZooKeeper发出创建 /controller 节点的请求,一旦创建成功,那么该Broker就变成了新的Controller节点了。

现在我们能明白启动Kafka集群之前,为什么要先启动ZooKeeper集群了吧。就是因为ZooKeeper可以协助Kafka进行集群管理。

2.2.3 启动Kafka

ZooKeeper已经启动好了,那我们现在可以启动多个Kafka Broker节点构建Kafka集群了。构建的过程中,每一个Broker节点就是一个Java进程,而在这个进程中,有很多需要提前准备好,并进行初始化的内部组件对象。

2.2.3.1初始化ZooKeeper

Kafka Broker启动时,首先会先创建ZooKeeper客户端(KafkaZkClient),用于和ZooKeeper进行交互。客户端对象创建完成后,会通过该客户端对象向ZooKeeper发送创建Node的请求,注意,这里创建的Node都是持久化Node。

节点

类型

说明

/admin/delete_topics

持久化节点

配置需要删除的topic,因为删除过程中,可能broker下线,或执行失败,那么就需要在broker重新上线后,根据当前节点继续删除操作,一旦topic所有的分区数据全部删除,那么当前节点的数据才会进行清理

/brokers/ids

持久化节点

服务节点ID标识,只要broker启动,那么就会在当前节点中增加子节点,brokerID不能重复

/brokers/topics

持久化节点

服务节点中的主题详细信息,包括分区,副本

/brokers/seqid

持久化节点

seqid主要用于自动生产brokerId

/config/changes

持久化节点

kafka的元数据发生变化时,会向该节点下创建子节点。并写入对应信息

/config/clients

持久化节点

客户端配置,默认为空

/config/brokers

持久化节点

服务节点相关配置,默认为空

/config/ips

持久化节点

IP配置,默认为空

/config/topics

持久化节点

主题配置,默认为空

/config/users

持久化节点

用户配置,默认为空

/consumers

持久化节点

消费者节点,用于记录消费者相关信息

/isr_change_notification

持久化节点

ISR列表发生变更时候的通知,在kafka当中由于存在ISR列表变更的情况发生,为了保证ISR列表更新的及时性,定义了isr_change_notification这个节点,主要用于通知Controller来及时将ISR列表进行变更。

/latest_producer_id_block

持久化节点

保存PID块,主要用于能够保证生产者的任意写入请求都能够得到响应。

/log_dir_event_notification

持久化节点

主要用于保存当broker当中某些数据路径出现异常时候,例如磁盘损坏,文件读写失败等异常时候,向ZooKeeper当中增加一个通知序号,Controller节点监听到这个节点的变化之后,就会做出对应的处理操作

/cluster/id

持久化节点

主要用于保存kafka集群的唯一id信息,每个kafka集群都会给分配要给唯一id,以及对应的版本号

2.2.3.2初始化服务

Kafka Broker中有很多的服务对象,用于实现内部管理和外部通信操作。

2.2.3.2.1 启动任务调度器

每一个Broker在启动时都会创建内部调度器(KafkaScheduler)并启动,用于完成节点内部的工作任务。底层就是Java中的定时任务线程池ScheduledThreadPoolExecutor

2.2.3.2.2 创建数据管理器

每一个Broker在启动时都会创建数据管理器(LogManager),用于接收到消息后,完成后续的数据创建,查询,清理等处理。

2.2.3.2.3 创建远程数据管理器

每一个Broker在启动时都会创建远程数据管理器(RemoteLogManager),用于和其他Broker节点进行数据状态同步。

2.2.3.2.4 创建副本管理器

每一个Broker在启动时都会创建副本管理器(ReplicaManager),用于对主题的副本进行处理。

2.2.3.2.5 创建ZK元数据缓存

每一个Broker在启动时会将ZK的关于Kafka的元数据进行缓存,创建元数据对象(ZkMetadataCache

2.2.3.2.6 创建Broker通信对象

每一个Broker在启动时会创建Broker之间的通道管理器对象(BrokerToControllerChannelManager),用于管理Broker和Controller之间的通信。

2.2.3.2.7 创建网络通信对象

每一个Broker在启动时会创建自己的网络通信对象(SocketServer),用于和其他Broker之间的进行通信,其中包含了Java用于NIO通信的Channel、Selector对象。

2.2.3.2.8 注册Broker节点

Broker启动时,会通过ZK客户端对象向ZK注册当前的Broker 节点ID,注册后创捷的ZK节点为临时节点。如果当前Broker的ZK客户端断开和ZK的连接,注册的节点会被删除。

2.2.3.3启动控制器

控制器(KafkaController)是每一个Broker启动时都会创建的核心对象,用于和ZK之间建立连接并申请自己为整个Kafka集群的Master管理者。如果申请成功,那么会完成管理者的初始化操作,并建立和其他Broker之间的数据通道接收各种事件,进行封装后交给事件管理器,并定义了process方法,用于真正处理各类事件。

2.2.3.3.1 初始化通道管理器

创建通道管理器(ControllerChannelManager),该管理器维护了Controller和集群所有Broker节点之间的网络连接,并向Broker发送控制类请求及接收响应。

2.2.3.3.2 初始化事件管理器

创建事件管理器(ControllerEventManager)维护了Controller和集群所有Broker节点之间的网络连接,并向Broker发送控制类请求及接收响应。

2.2.3.3.3 初始化状态管理器

创建状态管理器(ControllerChangeHandler)可以监听 /controller 节点的操作,一旦节点创建(ControllerChange),删除(Reelect),数据发生变化(ControllerChange),那么监听后执行相应的处理。

2.2.3.3.4 启动控制器

控制器对象启动后,会向事件管理器发送Startup事件,事件处理线程接收到事件后会通过ZK客户端向ZK申请 /controller 节点,申请成功后,执行当前节点成为Controller的一些列操作。主要是注册各类 ZooKeeper 监听器、删除日志路径变更和 ISR 副本变更通知事件、启动 Controller 通道管理器,以及启动副本状态机和分区状态机。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走过冬季

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值