Kafka性能优化–JVM参数配置优化

Posted by Yancy on 2017-07-04

img-w650

Kafka集群稳定

GC调优
  调GC是门手艺活,幸亏Java 7引进了G1 垃圾回收,使得GC调优变的没那么难。G1主要有两个配置选项来调优:MaxGCPauseMillis 和 InitiatingHeapOccupancyPercent,具体参数设置可以参考Google,这里不赘述。

  Kafka broker能够有效的利用堆内存和对象回收,所以这些值可以调小点。对于 64Gb内存,Kafka运行堆内存5Gb,MaxGCPauseMillis 和 InitiatingHeapOccupancyPercent 分别设置为 20毫秒和 35。Kafka的启动脚本使用的不是 G1回收,需要在环境变量中加入。

Kafka Broker个数决定因素

  磁盘容量:首先考虑的是所需保存的消息所占用的总磁盘容量和每个broker所能提供的磁盘空间。如果Kafka集群需要保留 10 TB数据,单个broker能存储 2 TB,那么我们需要的最小Kafka集群大小5个broker。此外,如果启用副本参数,则对应的存储空间需至少增加一倍(取决于副本参数)。这意味着对应的Kafka集群至少需要 10 个broker。

  请求量:另外一个要考虑的是Kafka集群处理请求的能力。这主要取决于对Kafka client请求的网络处理能力,特别是,有多个consumer或者网路流量不稳定。如果,高峰时刻,单个broker的网络流量达到80%,这时是撑不住两个consumer的,除非有两个broker。再者,如果启用了副本参数,则需要考虑副本这个额外的consumer。也可以扩展多个broker来减少磁盘的吞吐量和系统内存。

主要是启动脚本和log4j基本参数的设置和优化,这些参数藏的比较深。

1、JVM参数配置优化

如果使用的CMS GC算法,建议JVM Heap不要太大,在4GB以内就可以。JVM太大,导致Major GC或者Full GC产生的“stop the world”时间过长,导致broker和zk之间的session超时,比如重新选举controller节点和提升follow replica为leader replica。
JVM也不能过小,否则会导致频繁地触发gc操作,也影响Kafka的吞吐量。另外,需要避免CMS GC过程中的发生promotion failure和concurrent failure问题。CMSInitiatingOccupancyFraction=70可以预防concurrent failure问题,提前出发Major GC。
Kafka JVM参数可以直接修改启动脚本bin/kafka-server-start.sh
中的变量值。下面是一些基本参数,也可以根据实际的gc状况和调试GC需要增加一些相关的参数。

1
export KAFKA_HEAP_OPTS="-Xmx8G -Xms8G -Xmn4G -XX:PermSize=64m -XX:MaxPermSize=128m -XX:SurvivorRatio=6 -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"

需要关注gc日志中的YGC时间以及CMS GC里面的CMS-initial-mark和CMS-remark两个阶段的时间,这些GC过程是“stop the world”方式完成的。

jdk1.8 优化的话会提示MaxPermSize=128m,PermSize=64m 字面意思是MaxPermSize不需要我们配置了,jdk1.8 版本功能其实已不需要这个优化参数:

1
2
3
4
5
6
7
8
[jollybi@kafka3 kafka_2.10-0.8.2.1]$ /data/tools/kafka_2.10-0.8.2.1/bin/kafka-server-start.sh /data/tools/kafka_2.10-0.8.2.1/config/server.properties &
[1] 10312
[jollybi@kafka3 kafka_2.10-0.8.2.1]$ Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=64m; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
优化参数:
export KAFKA_HEAP_OPTS="-Xmx4G -Xms4G -Xmn2G -XX:SurvivorRatio=6 -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
export JMX_PORT="9999" ### Kafka Manager监控监听jmx端口,如果没有可不设置。

2、打开JMX端口

1
2
主要是为了通过JMX端口监控Kafka Broker信息。可以在bin/kafka-server-start.sh中打开JMX端口变量。
export JMX_PORT=9999

3、调整log4j的日志级别

如果集群中topic和partition数量较大时,因为log4j的日志级别太低,导致进程持续很长的时间在打印日志。日志量巨大,导致很多额外的性能开销。特别是contoller日志级别为trace级别,这点比较坑。
Tips 通过JMX端口设置log4j日志级别,不用重启broker节点

1
2
3
4
5
6
7
设置日志级别:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:9999 kafka:type=kafka.Log4jController setLogLevel=kafka.controller,INFO
java -jar cmdline-jmxclient-0.10.3.jar - localhost:9999 kafka:type=kafka.Log4jController setLogLevel=state.change.logger,INFO
检查日志级别:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:9999 kafka:type=kafka.Log4jController getLogLevel=kafka.controller
java -jar cmdline-jmxclient-0.10.3.jar - localhost:9999 kafka:type=kafka.Log4jController getLogLevel=state.change.logger

4、性能优化技巧

4.1、配置合适的partitons数量。

这似乎是kafka新手必问得问题。首先,我们必须理解,partiton是kafka的并行单元。从producer和broker的视角看,向不同的partition写入是完全并行的;而对于consumer,并发数完全取决于partition的数量,即,如果consumer数量大于partition数量,则必有consumer闲置。所以,我们可以认为kafka的吞吐与partition时线性关系。partition的数量要根据吞吐来推断,假定p代表生产者写入单个partition的最大吞吐,c代表消费者从单个partition消费的最大吞吐,我们的目标吞吐是t,那么partition的数量应该是t/p和t/c中较大的那一个。实际情况中,p的影响因素有批处理的规模,压缩算法,确认机制和副本数等,然而,多次benchmark的结果表明,单个partition的最大写入吞吐在10MB/sec左右;c的影响因素是逻辑算法,需要在不同场景下实测得出。

这个结论似乎太书生气和不实用。我们通常建议partition的数量一定要大于等于消费者的数量来实现最大并发。官方曾测试过1万个partition的情况,所以不需要太担心partition过多的问题。下面的知识会有助于读者在生产环境做出最佳的选择:

1
2
3
4
5
6
7
8
9
10
a、一个partition就是一个存储kafka-log的目录。
b、一个partition只能寄宿在一个broker上。
c、单个partition是可以实现消息的顺序写入的。
d、单个partition只能被单个消费者进程消费,与该消费者所属于的消费组无关。这样做,有助于实现顺序消费。
e、单个消费者进程可同时消费多个partition,即partition限制了消费端的并发能力。
f、partition越多则file和memory消耗越大,要在服务器承受服务器设置。
g、每个partition信息都存在所有的zk节点中。
h、partition越多则失败选举耗时越长。
k、offset是对每个partition而言的,partition越多,查询offset就越耗时。
i、partition的数量是可以动态增加的(只能加不能减)。

我们建议的做法是,如果是3个broker的集群,有5个消费者,那么建议partition的数量是15,也就是broker和consumer数量的最小公倍数。当然,也可以是一个大于消费者的broker数量的倍数,比如6或者9,还请读者自行根据实际环境裁定。

Communicative learning:

🐧 Linux shell_ senior operation and maintenance faction: QQ group 459096184 circle (system operation and maintenance - application operation and maintenance - automation operation and maintenance - virtualization technology research, welcome to join)
🐧 BigData-Exchange School:QQ group 521621407 circles (big data Yun Wei) (Hadoop developer) (big data research enthusiasts) welcome to join

Bidata have internal WeChat exchange group, learn from each other, join QQ group has links.