一、Kafka线上集群部署方案
既然是集群,那必然就要有多个Kafka节点机器,因为只有单台机器构成的kafka伪集群只能用于日常测试之用,根本无法满足实际的线上生产需求。
操作系统:
kafka由Scals语言和Java语言编写而成,编译之后的源代码就是普通的.class文件,文本部署到哪个操作系统应该都是一样的,但是不同操作系统的差异还是给Kafka集群带来了相当大影响。
目前常见的操作系统有3种:Linux、Windows和macOS。考虑操作系统与kafka的适配性,Linux系统更加适合部署,主要体现在下面三个方面:
I/O模型使用
你可以近似地认为I/O模型就是操作系统执行I/O指令的方法。主流的I/O模型有5种类型:阻塞式I/O、非阻塞式I/O、I/O多路复用、信号驱动I/O和异步I/O。每种模型都有各自典型使用场景,比如Java中Socket对象的阻塞模式和非阻塞模式就对应前两种类型;Linux中的系统调用select函数就属于I/O多路复用模型;epoll系统调 用则介于第三种和第四种模型之间;至于第五种模型,其实很少有Linux系统支持,反而Windows系统提供了一个叫IOCP线程模型属于这一种。我们只需要了解认为后一种模型会比前一种模型要高级,比如epoll就比select要好。
实际上kafka客户端底层使用了java的selector,selector在Linux上的实现机制是epoll,而在Windows上实现机制是select。因此在这一点上将kafka部署在Linux上是有优势的,因为能够获得更高效的I/O性能。
数据网络传输效率
kafka生产和消费的消息都是通过网络传输的,而消息是保存在磁盘上,故需要在磁盘和网络间进行大量数据传输。零拷贝技术就是当数据在磁盘和网络进行传输时避免昂贵的内核态数据拷贝从而实现快速地数据传输,Linux平台实现了这样的零拷贝机制,所以在Linux部署kafka能够享受到零拷贝技术所带来的快速数据传输特性
社区支持度
社区目前对Windows平台上发现的kafka Bug不做任何承诺,一般是不会修复的。因此,Windows部署kafka只适合于个人测试或用于功能验证,千万不要应用于生产环境。
磁盘:
磁盘无疑是对kafka性能最重要的资源之一。在对集群进行磁盘规划时,应该选择普通的机械磁盘还是固态硬盘,我的建议是使用普通机械硬盘即可。
kafka大量使用磁盘不假,可它使用的方式多是顺序读写操作,一定程度上规避了机械硬盘的最大劣势随机读写操作慢。从这一点上,使用SSD似乎没有太大的性能优势。而机械硬盘因易损坏而造成的可靠性差等缺陷,kafka在软件层面提供机制来保证。因此考虑性价比和使用性能上,使用机械硬盘即可。
是否使用磁盘阵列(RAID):
RAID的两个主要优势:
但是对于kafka而言,自己已经实现了冗余机制来提供高可靠性;通过分区自行实现负载均衡。因此RAID的优势没有那么明显了,实际上依然有很多大厂是把kafka底层的存储交由RAID,只是目前kafka在存储方面提供了越来越多便捷的高可靠性方案,因此在线上环境使用RAID似乎变得不是那么重要。
磁盘容量:
假设有个业务每天需要向kafka集群发送1亿条消息,每条消息保存两份以防数据丢失,另外消息默认保存两周时间。现在假设消息的平均大小是1KB,计算出kafka集群需要为这个业务预留多少磁盘空间?
计算:
1、每天1亿条、1KB大小、两份的总空间大小:1亿 * 1KB * 2 / 1000 / 1000 = 200GB。
2、除了消息数据还有其他类型的数据,比如索引数据等,这些数据的空间大小:预留出10%的磁盘空间,因此总的存储容量=220GB
3、保存两周整体容量:220GB * 14大约3TB左右。
4、kafka支持数据的压缩,假设压缩比是0.75,那么最后容量为:0.75 * 3 = 2.25TB。
规划磁盘容量时需要考虑的元素:
带宽:
对于kafka这种通过网络大量进行传输的框架而言,带宽特别容易成为瓶颈。
普通的以太网络,带宽也主要有两种:1Gbps的千兆网络和10Gbps的万兆网络,特别是千兆网络应该是一般公司网络的标准配置了。
与其说是带宽资源规划,其真正要规划的是所需的kafka服务器的数量。假设是公司机房环境是千兆网络1Gbps,有个业务需要在1小时内处理1TB的业务数据,计算出需要多少台kafka服务器来完成这个业务?
1、由于带宽是1Gbps,即每秒处理1Gb的数据。每台kafka服务器会使用到70%的带宽资源,为其他应用或进程流一些资源,如果超过70%就有网络丢包可能性。也就是单台kafka服务器最多能使用大约700Mb的带宽资源。但是这只是kafka能使用的最大带宽资源,实际使用上通常要再预留2/3的资源,即单台服务器使用带宽:700Mb / 3 ≈ 240Mbps。这里的2/3是相当保守的,可结合自己机器的使用情况酌情减少此值。
2、每秒需要处理的数据:1TB * 1024 * 1024 = 1048576MB * 8 = 8388608Mb / 60 / 60 ≈ 2330Mb,这里提个小知识:这里带宽使用的单位Mbps中的b是小写b,表示的是Bit(比特),而容量单位的TB中的B是大写B,表示的是Byte(字节),而1B=8b。
3、所需服务器数:2330 / 240 ≈ 10台服务器。如果消息还需要额外复制两份,那么总服务器台数还要乘以3,即30台。
总结:
二、集群参数配置
Broker端配置:目前Kafka Broker提供了近200个参数,这其中绝大部分参数都不用你亲自过问。
1、配置存储信息:即Broker使用哪些磁盘
log.dirs:非常重要的参数,指定了Broker需要使用的若干个文件目录路径,没有默认值,必须自己指定。
log.dir:注意这是dir,结尾没有s,说明它只能表示单个路径,它是补充上一个参数用的。
只要设置log.dirs,不要设置log.dir。在线上生产环境中一定要为log.dirs配置多个路径,具体格式是一个CSV格式,比如/home/kafka1,/home/kafka2,/home/kafka3。
如果有条件的话最好保证这些目录挂载到不同的物理磁盘上,这样有两个好处:
(1)提升读写性能:比起单块磁盘,多块物理磁盘同时读写数据有更高的吞吐量。
(2)能够实现故障转移:即Failover。这是kafka1.1版本新引入的强大功能。以前只要kafka Broker使用的任何一块磁盘挂掉了,整个Broker进程都会关闭。自1.1开始,坏掉的磁盘上的数据会自动地转移到其他正常的磁盘上,而且Broker还能正常工作。
2、ZooKeeper相关的配置:
ZooKeeper是一个分布式协调框架,负责协调管理并保存kafka集群的所有元数据信息,比如集群都有哪些Broker在运行、创建了哪些Topic,每个Topic都有多少分区以及这些分区的Leader副本都在哪些机器上等信息。
kafka与ZooKeeper最重要的参数当属zookeeper.connect,是一个CSV格式参数,比如zk1:2181,zk2:2181,zk3:2181,2181是ZooKeeper的默认端口。
设置让多个kafka集群使用同一套ZooKeeper集群:假设两套kafka集群叫kafka1和kafka2,那么两套集群的zookeeper.connect参数可以这样指定:zk1:2181,zk2:2181,zk3:2181/kafka1和zk1:2181,zk2:2181,zk3:2181/kafka2。切记chroot只需写一次,而且是加到最后。错误的格式,比如:zk1:2181/kafka1,zk2:2181/kafka2,zk3:2181/kafka3。
3、Broker连接相关的参数:即客户端程序或其他Broker如何与该Broker进行通信的设置
listeners:监听器,告诉外部连接者要通过什么协议访问指定主机名和端口开放的kafka服务。
advertised.listeners:这组监听器是Broker用于对外发布的。
host.name/port:已经是过期的参数,压根不要配置它
监听器从构成来说,它是若干个逗号分隔的三元组,每个三元组的格式为<协议名称, 主机名, 端口号>。这里的协议名称可能是标准名字,比如PLAINTEXT表示明文传输、SSL表示使用SSL或TLS加密传输等;也可能是自定义的协议名,比如CONTROLLER://localhost:9092。一旦指定了自定义协议名称,必须还要指定listener.security.protoclo.map参数告诉这个协议底层使用了哪种安全协议,比如指定listener.security.protoclo.map=CONTROLLER:PLAINTEXT表示CONTROLLER这个自定义协议底层使用明文不加密传输数据。
主机名这个设置使用IP地址还是主机名,建议最好全部使用主机名,即Broker端和Client端应用配置中全部填写主机名。因为Broker源代码中也使用的是主机名,如果在某些地方使用了IP地址进行连接,可能会发生无法连接的问题。
4、Topic管理参数:
5、数据留存方面参数:
总结:以上的所有参数都是那些需要修改默认值的参数,因为它们的默认值不适合一般的生产环境。
Topic 级别参数:
除了Broker端参数外,其实kafka也支持为不同的Topic设置不同的参数值。Topic级别参数会覆盖全局Broker参数的值,而每个Topic都能设置自己的参数值,这就是所谓的Topic级别参数。
比如:在实际的生产环境中,如果为所有Topic的数据都保存相当长的时间,既不高效也无必要。更适当的做法是允许不同部门的Topic根据自身业务需要,设置自己的留存时间。
设置Topic级别参数的方法:
创建Topic时进行设置:通过kafka-topics命令创建
bin/kafka-topics.sh--bootstrap-serverlocalhost:9092--create--topictransaction--partitions1--replication-factor1--configretention.ms=15552000000--configmax.message.bytes=5242880
修改Topic时设置:通过kafka-configs命令修改Topic级别参数
# 修改发送最大值是10MB的消息
bin/kafka-configs.sh--zookeeperlocalhost:2181--entity-typetopics--entity-nametransaction--alter--add-configmax.message.bytes=10485760
总结:建议坚持使用第二种方式来设置,在未来,kafka社区有可能统一使用kafka-configs脚本来调整Topic级别参数。
JVM 参数:
kafka服务器端代码是用Scala语言编写,但终归还是编译成Class文件在JVM上运行,因此JVM参数设置对kafka集群有重要性。不推荐将kafka运行在java 6 或java 7的环境上,6版本太过陈旧,而7版本kafka自2.0.0版本开始已经摒弃对7版本的支持。所以至少使用java 8。
设置JVM参数的方法:只需设置下面两个环境变量
KAFKA_HEAP_OPTS:指定堆大小。
KAFKA_JVM_PERFORMANCE_OPTS:指定GC参数。
# 比如你可以这样启动 Kafka Broker,即在启动 Kafka Broker 之前,先设置上这两个环境变量
$> export KAFKA_HEAP_OPTS=--Xms6g --Xmx6g
$> export KAFKA_JVM_PERFORMANCE_OPTS= -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -Djava.awt.headless=true
$> bin/kafka-server-start.sh config/server.properties
操作系统参数:
总结:配置因环境而已,一定要结合自身业务需要以及具体的测试来验证它们的有效性。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章