Kafka线上环境部署

Kafka线上环境部署

集群环境规划

操作系统选型

I/O模型。当前主流的5种I/O模型:阻塞I/O、非阻塞I/O、I/O多路复用、信号驱动I/O和异步I/O,每一种I/O模型都有典型的使用场景,比如Socket的阻塞模式和非阻塞模式就对应I/O阻塞、非阻塞I/O,Linux的select函数属于I/O多路复用模型,Windows的IOCP属于异步I/O模型,Linux epoll兼具I/O多路复用、信号驱动I/O

Kafka clients底层网络库采用Java的Selector机制,在Linux上的实现是使用epoll,在Windows平台上,Java NIO的Selector底层是使用select模型而非IOCP实现,只有Java NIO2才使用IOCP,因此使用Linux系统能得到更高效的I/O处理能力

Kafka需要频繁通过网络与磁盘进行数据传输,大部分这样的操作都是通过Java的FileChannel.transferTo方法实现,在Linux平台上该方法底层会调用sendfile系统调用,即使用了Linux的零拷贝技术。直到Java 8u60版本Windows平台才正式让FileChannel的transferTo方法调用TransmitFile函数。

磁盘规划

Kafka的每条消息都必须被持久化到底层的存储中,并且只有被规定数量的broker成功接收后才能通知clients消息发送成功,因此消息越快被保存在磁盘上,处理client请求的延时越低,表现出来的用户体验也越好

机械硬盘(HDD)与固态硬盘(SSD)

  • 机械硬盘成本低容量大,SSD通常有着极低的寻道时间和存取时间,性能好成本高。Kafka使用顺序写磁盘,因此机械硬盘频繁寻道的时间开销是很低的,这使得使用机械硬盘与使用SSD差距并不大。对于预算有限最求高性价比的公司而言,机械硬盘完全可以胜任

JBOD(Just Bunch Of Disks)与RAID(磁盘阵列)

  • 常见的RAID是RAID 10,也称为RAID 1+0,它结合磁盘镜像和磁盘条带化两种技术共同保护数据,即实现了不错的性能也提供了很高的可靠性。但在空间上使用了磁盘镜像,因此整体磁盘使用率只有50%。除了提供数据冗余外,RAID 10

    还可以将数据自动地负载分布到多个磁盘上

    • Kafka在框架层面已经提供了两个特性:通过副本机制提供冗余和高可用性,以及通过分散在各个节点的领导者选举机制来实现负载均衡,因此RAID的优势就显得不那么明显了

    • 对于一般公司或组织而言,选择JBOD方案性价比更高,推荐用户为每个broker都配置多个日志路径,每个路径都独立挂载在不同的磁盘上,这使得多块物理磁盘同时执行物理I/O写操作,可以极大地加速Kafka消息生产速度

    • 尽量不要使用NAS这样的网络存储设备,NAS通常运行在低端的硬件上,这使得性能可能很差,平均延时有很大的不稳定性

    • 追求性价比的公司可以考虑使用JBOD。使用机械硬盘完全可以满足Kafka集群的使用,SSD更好

磁盘容量规划

让我们以一个实际的例子来看下应该如何思考这个问题。假设在业务场景中,clients每天会产生1亿条消息,每条消息保存两份并保存一周时间,平均一条消息的大小是1KB,那么我们需要为Kafka规划的磁盘空间为1亿 * 2 * 1KB / 1000 / 1000 = 200GB的磁盘空间,我们最好再额外预留10%的磁盘空间用于其它数据文件存储,因此这种场景下每天新发送的消息将占用210G左右磁盘空间,还需要保留一周的数据,所以整体磁盘容量规划是210 * 7 = 1.5T,再考虑压缩的情况,如果平均压缩比为0.5,那么整体磁盘容量就是0.75TB

磁盘容量的规划和以下多个因素有关

  • 消息留存时间
  • 平均消息大小
  • 副本数
  • 是否启用压缩

内存规划

Kafka会将消息写入page cache,之后由底层文件系统通过"冲刷"将消息持久化到磁盘,consumer在读取消息时也会首先尝试从该区域中查找,如果命中则直接从页缓存中获取。还需将page cache大小与实际线上环境中设置的日志段大小相比较,假设单个日志段文件大小设置为10GB,那么至少应该给予page cache 10GB以上的内存空间,这样带消费消息大概率会保存在页缓存中,故consumer能直接命中页缓存而无须执行慢的磁盘I/O读写,对于内存规划建议如下

  • 尽量分配多的内存给操作系统的page cache
  • 不要为broker设置过大的堆内存,最好不超过6GB
  • page cache大小至少要大于一个日志段的大小

CPU规划

Kafka并非计算密集型系统,因此追求多核而非高时钟频率。Kafka所在机器有16个CPU核比CPU时钟高达4GHz更重要,因为Kafka可能无法充分利用4GHz的频率,但几乎可以肯定会用满16个CPU核,Kafka broker通常会创建几十个后台线程,再加上多个垃圾回收线程,多核系统显然是最佳配置选择

若client端开启了消息压缩,除了要为clients机器分配足够的CPU资源外,broker端也有可能需要大量的CPU资源,在Kafka 0.10.0及之后的版本中改进消息的处理,免除了解压索消息的负担以节省磁盘占用和网络带宽,但当clients端和broker端配置的消息版本号不匹配,若出现这种情况,用户需要为broker端的机器也配置充裕的CPU资源,因此对于CPU资源

规划的建议如下

  • 使用多核系统,CPU核数最好大于8
  • 如果使用Kafka 0.10.0.0之前的版本或clients端与broker端消息版本不一致,则考虑多配置一些资源以防止消息解压缩操作消耗过多CPU

带宽规划

对于Kafka这种需要在网络间传递大量数据的分布式数据管道而言,带宽至关重要,平时所说的千兆网和万兆网对于大多数Kafka集群来说都是足够的,如何来预估Kafka集群需要的资源,假设网络带宽1Gb/s,假设分配的机器为Kafka专属(通常不建议与其他应用或框架部署在同一台机器上)且为Kafka分配70%的带宽资源(机器上还有其它进程使用网络且网卡通常不能用满),超过一定阀值可能出现网络丢包的情况,因此70%是比较合理的设置,单台broker的带宽为1Gb/s * 0.7 = 710Mb/s,这是Kafka所使用的最高带宽,用户不能期望Kafka集群平时就一直使用如此多的带宽,如果遇到突发流量,极容易把网卡"打满",因此在70%基础上,再截取1/3,即710Mb/s / 3 = 240Mb/s。这里的1/3是一个相对保守的数字,可以根据业务特点酌情增加,如果要在1小时处理1TB的业务数据,即每秒需要处理292MB左右数据,也就是每秒2336Mb数据,那么至少需要2336/240 = 10台broker机器,若副本数是2,那么这个数字还要再翻一倍。尽量避免使用跨机房的网络环境,对带宽资源规划建议如下

  • 尽量使用高速网络
  • 根据网络条件和带宽来评估Kafka集群机器数量
  • 避免使用跨机房网络

多节点环境安装

多节点kafka集群由一套多节点ZooKeeper集群和一套多节点Kafka集群组成。为搭建多节点Kafka集群,我们需要一次执行如下操作

  • 安装Java(略)
  • 安装多节点ZooKeeper集群
  • 安装多节点Kafka集群
    Kafka线上环境部署_第1张图片

安装多节点Zookeeper集群

Kafka强依赖ZooKeeper,因此生产环境中一个高可用、高可靠的ZooKeeper是必不可少的。ZooKeeper集群通常被称作一个ensemble。只要这个ensemble中的大多数节点存活,那么Zookeeper集群就能正常提供服务。显然,既然是大多数,那么最好使用奇数过服务器,即2n + 1个服务器,这样整个ZooKeeper集群最多可以容忍n台服务器宕机而依然提供服务。如果使用偶数个则通常会浪费一台服务器资源。

1.下载Zookeeper安装包

    wget https://downloads.apache.org/zookeeper/zookeeper-3.6.0/apache-zookeeper-3.6.0-bin.tar.gz

2.解压

    tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz

3.创建Zookeeper系统快照目录

    mkdir data_dir1
    mkdir data_dir2
    mkdir data_dir3

4.zoo.cfg配置文件说明

    # 添加一下配置
    tickTime=2000 # ZooKeeper最小时间单位,用于丈量心跳时间和超时时间。通常设置成默认2秒即可
    initLimit=10  # 指定follower节点初始时连接leader节点的最大tick次数。假设5,表示follower必须在5 * tickTime连接上leader,否则将视为超时
    syncLimit=5   # 设定follower节点与leader节点进行同步的最大时间
    dataDir=/home/aim/programe/kafka/zookeeper/data_dir # 非常重要的参数!ZooKeeper会在内存中保存系统快照,并定期写入该路径指定的文件夹
    clientPort=2181 # Zookeeper监听客户端连接的端口
    server.1=zk1:2888:3888 # 格式为server.X=host:port:port X必须是全局唯一的数字,且需与myid文件中的数字相对应。一般设置X值为1~255之间的整数,后面两个端口,第一个用于follower节点连接leader节点,第二个端口则用于leader选举
    server.2=zk2:2888:3888
    server.3=zk3:2888:3888

5.创建三个配置文件添加相应配置

    cd apache-zookeeper-3.6.0-bin/conf
    cp zoo_sample.cfg zoo_sample1.cfg
    cp zoo_sample.cfg zoo_sample2.cfg
    cp zoo_sample.cfg zoo_sample3.cfg

    vim zoo_sample1.cfg

    # 添加以下配置
    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/home/aim/programe/kafka/zookeeper/data_dir1
    clientPort=2181
    server.1=zk1:2888:3888
    server.2=zk2:2889:3889
    server.3=zk3:2890:3890

    vim zoo_sample2.cfg

    # 添加以下配置
    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/home/aim/programe/kafka/zookeeper/data_dir2
    clientPort=2182
    server.1=zk1:2888:3888
    server.2=zk2:2889:3889
    server.3=zk3:2890:3890

    vim zoo_sample2.cfg

    # 添加以下配置
    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/home/aim/programe/kafka/zookeeper/data_dir3
    clientPort=2183
    server.1=zk1:2888:3888
    server.2=zk2:2889:3889
    server.3=zk3:2890:3890

6.创建myid文件,myid文件必须位于配置文件中dataDir中

    echo "1" > ../../data_dir1/myid
    echo "2" > ../../data_dir2/myid
    echo "2" > ../../data_dir3/myid

7.启动ZooKeeper

    cd ../../apache-zookeeper-3.6.0-bin/
    nohup bin/zkServer.sh start conf/zoo_sample1.cfg > ../zookeeper_log1/zookeeper_log.log &
    nohup bin/zkServer.sh start conf/zoo_sample2.cfg > ../zookeeper_log2/zookeeper_log.log &
    nohup bin/zkServer.sh start conf/zoo_sample3.cfg > ../zookeeper_log3/zookeeper_log.log &

8.检查整个集群状态

    bin/zkServer.sh status conf/zoo_sample1.cfg
    bin/zkServer.sh status conf/zoo_sample2.cfg
    bin/zkServer.sh status conf/zoo_sample3.cfg

安装多节点Kafka集群

1.下载Kafka安装包

    wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.5.0/kafka_2.13-2.5.0.tgz

2.解压

    tar -zxvf kafka_2.13-2.5.0.tgz

3.创建日志存储文件

    mkdir -p log/kafka1
    mkdir -p log/kafka2
    mkdir -p log/kafka3

4.复制配置文件

    cd kafka_2.13-2.5.0
    cp config/server.properties config/server1.properties
    cp config/server.properties config/server2.properties
    cp config/server.properties config/server3.properties

5.修改配置文件

    vim config/server1.properties

    # 添加以下配置
    broker.id=0 # 整个集群中唯一
    listeners=PLAINTEXT://192.168.1.9:9092 # 配置listeners最好使用节点的FQDN即全称域名,尽量不要使用IP地址
    log.dirs=/home/aim/programe/kafka/kafka/log/kafka1 #日志
    num.partitions=4 # topic 分区数,根据具体情况给
    offsets.topic.replication.factor=3 # topic 副本数
    zookeeper.connect=192.168.1.9:2181,192.168.1.9:2182,192.168.1.9:2183 # zookeeper地址
    delete.topic.enable=true # 允许删除topic
    unclean.leader.election.enable=false

    vim config/server2.properties

    # 添加以下配置
    broker.id=1 # 整个集群中唯一
    listeners=PLAINTEXT://192.168.1.9:9093 # 配置listeners最好使用节点的FQDN即全称域名,尽量不要使用IP地址
    log.dirs=/home/aim/programe/kafka/kafka/log/kafka2 #日志
    num.partitions=4 # 分区数,根据具体情况给
    offsets.topic.replication.factor=3 # topic 副本数
    zookeeper.connect=192.168.1.9:2181,192.168.1.9:2182,192.168.1.9:2183 # zookeeper地址
    delete.topic.enable=true # 允许删除topic
    unclean.leader.election.enable=false

    vim config/server3.properties

    # 添加以下配置
    broker.id=2 # 整个集群中唯一
    listeners=PLAINTEXT://192.168.1.9:9094 # 配置listeners最好使用节点的FQDN即全称域名,尽量不要使用IP地址
    log.dirs=/home/aim/programe/kafka/kafka/log/kafka3 #日志
    num.partitions=4 # 分区数,根据具体情况给
    offsets.topic.replication.factor=3 # topic 副本数
    zookeeper.connect=192.168.1.9:2181,192.168.1.9:2182,192.168.1.9:2183 # zookeeper地址
    delete.topic.enable=true # 允许删除topic
    unclean.leader.election.enable=false

6.启动kafka

    bin/kafka-server-start.sh se config/server1.properties
    bin/kafka-server-start.sh -daemon config/server2.properties
    bin/kafka-server-start.sh -daemon config/server3.properties

7.检查启动情况

    jps |grep Kafka

验证部署

测试topic创建与删除

测试topic能正确的创建与删除才能说明Kafka集群在正常工作,表明Kafka的控制器已经成功的选举出并履行自身的职责。推荐开始使用Kafka集群前把所需的topic创建出来,并执行对应的命名做验证,这样即测试了整个集群的运行状况,也保证了producer和consumer运行时不会因为topic分区leader的各种问题导致短暂的停顿现象

测试创建topic,并指定分区、副本

    bin/kafka-topic.sh --zookeeper zk1:8001,zk2:8002,zk3:8003 --create --topic test-topic
    --partitions 3 --replication-factor 3

查询topic列表

    bin/kafka-topics.sh --zookeeper zk1:8001,zk2:8002,zk3:8003 -list

查询topic详情

    bin/kafka-topics.sh --zookeeper zk1:8001,zk2:8002,zk3:8003 --describe --topic test-topic

删除topic,当broker端参数delete.topic.enable为false时仅仅标记topic为删除不会真删

    bin/kafka-topics.sh --zookeeper zk1:8001,zk2:8002,zk3:8003 --delete --topic test-topic

测试消息发送与消费

消息发送

    bin/kafka-console-producer.sh --broker-list kafka1:9092,kafka2:9093,kafka3:9094 --topic test-topic

消息接收

    bin/kafka-console-consumer.sh --bootstrap-server kafka1:9092,kafka2:9093,kafka3:9094 --topic test-topic --from-beginning

生产者吞吐量测试

测试当前主机上Kafka的吞吐量,最好让该脚本长时间稳定运行一段时间

    bin/kafka-producer-perf-test.sh --topic test-topic --num-records 500000 --record-size 200 --throughput -1
    --producer-props bootstrap.server=kafka1:9092,kafka2:9092,kafka3:9094 acks=-1

消费者吞吐量测试

测试当前主机上Kafka消费吞吐量

    bin/kafka-consumer-perf-test.sh --broker-list kafka1:9092,kafka2:9093,kafka3:9094 --fetch-size 2000 --messages 500000 --topic test-topic

你可能感兴趣的:(Kafka,java,后端,kafka)