一小时水一篇文章,不愧是我
0x00.前言
众所周知,压测都是从单机测起的,然后再拓展到集群环境,这也是上一篇文章中提到的「不得不在各个平台上都装一份,以便进行横向对比」
0x01.压测环境
虚拟机从来都不缺,要多少有多少(bushi
Hostname | CPU | RAM | Disk | OS |
---|---|---|---|---|
cn-tx-bj1-r8 | 单核 | 2G | 普通云硬盘 | RHEL 8 |
cn-tx-bj6-u0 | 双核 | 4G | SSD 云硬盘 | Ubuntu Server 20.04 LTS |
cn-py-dl-r8 | 八核 | 16G | 希捷机械硬盘 | RHEL 8 |
0x02.kafka-producer-perf-test.sh
因前辈给了这篇文章kafka性能测试,其中针对生产者的测试点挺详细的,自己也准备抄作业,于是花了两天折腾官方提供的这个脚本,没想到最后得出的结论却是并不适合用它来压测
1.粗测磁盘写入性能
「普通云硬盘」,120
左右
1 | [root@cn-tx-bj1-r8 kafka_2.13-3.2.0]# dd if=/dev/zero of=dd-test bs=1M count=10240 oflag=direct |
SSD
云硬盘,140
左右,对比「普通云硬盘」也并没有快多少
1 | ubuntu@cn-tx-bj6-u0:~/kafka_2.13-3.2.0$ dd if=/dev/zero of=dd-test bs=1M count=10240 oflag=direct |
「希捷机械硬盘」竟然是最快的,200
左右,这可是没想到的
1 | [root@cn-py-dl-r8 kafka_2.13-3.2.0]# dd if=/dev/zero of=dd-test bs=1M count=10240 oflag=direct |
2.创建Kafka
单节点单分区的主题
cn-tx-bj1-r8
1 | [root@cn-tx-bj1-r8 kafka_2.13-3.2.0]# bin/kafka-topics.sh --describe --topic test --bootstrap-server localhost:9092 |
cn-tx-bj6-u0
:#108440595160620768
1 | ubuntu@cn-tx-bj6-u0:~/kafka_2.13-3.2.0$ bin/kafka-topics.sh --describe --topic test --bootstrap-server localhost:9092 |
cn-py-dl-r8
:#108440262738706509
1 | [root@cn-py-dl-r8 kafka_2.13-3.2.0]# bin/kafka-topics.sh --describe --topic test --bootstrap-server localhost:9092 |
3.运行生产者性能测试
参数中指定的config/producer.properties
配置文件保持了默认,其实也尝试过修改其中的linger.ms
和batch.size
等参数,虽然确实可能有效果提升#108441932955929068
但毕竟并不使用Java
版本的生产者,所以就不浪费时间在这里调参了,之后还得去研究实际会用的librdkafka
的调参呢,原始结果见#108446732693126948kafka-producer-perf-test.sh
脚本参数可参考Kafka 性能测试脚本详解
点击此处 ← 查看折叠
1 | [root@cn-py-dl-r8 kafka_2.13-3.2.0]# cat config/producer.properties |
cn-tx-bj1-r8
毕竟是单核,压测时跑爆CPU
,明显只有一个核是不够用的,限制了压测脚本的生产能力
1 | [root@cn-tx-bj1-r8 kafka_2.13-3.2.0]# free -h |
cn-tx-bj6-u0
多了一个核心变成了双核,压测时还是跑爆两个CPU
,65
左右的吞吐量看起来还行,压测脚本的生产能力并没有受到限制
1 | ubuntu@cn-tx-bj6-u0:~/kafka_2.13-3.2.0$ free -h |
cn-py-dl-r8
快进到八核这下性能不成问题了,压测脚本的生产能力更不会受到限制了,不过仍然是60
左右的吞吐量,不得不怀疑这就是单个压测脚本所能打到的上限了
1 | [root@cn-py-dl-r8 kafka_2.13-3.2.0]# free -h |
4.结论
- 个人观点,在吞吐量小于
50~60
的情况下#108434169651624713,可以使用kafka-producer-perf-test.sh
来测试吞吐量,因为看起来还没到单个脚本所能打到的上限
比如这篇文章How to optimize your Kafka producer for throughput,通过修改batch.size
、linger.ms
、compression.type=lz4
和acks=1
把吞吐量从1.03 MB/sec
提高到了5.65 MB/sec
,是可以使用这个脚本来验证的 - 但是如果被压测的机器性能更好(指大于
50
)#108431369549507049,那么只运行这一个脚本显然是不够的,需要同时运行多个脚本才能打到较高的数值(亦或是多进程搞起来 - 查看这个脚本的源码,发现实际调用的是
org.apache.kafka.tools.ProducerPerformance
这个类再查看ProducerPerformance.java源码,节选其关键部分如下1
2
3
4if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export KAFKA_HEAP_OPTS="-Xmx512M"
fi
exec $(dirname $0)/kafka-run-class.sh org.apache.kafka.tools.ProducerPerformance "$@"
里面只定义了一个KafkaProducer<byte[], byte[]> producer = createKafkaProducer(props);
当没达到总数numRecords
时,随机生成每一条记录payload = generateRandomPayload(recordSize, payloadByteList, payload, random);
,然后调用producer.send(record, cb);
压测时也确实看到只有一个核心是打满的状态,这个脚本是单进程的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32KafkaProducer<byte[], byte[]> producer = createKafkaProducer(props);
/* setup perf test */
for (long i = 0; i < numRecords; i++) {
payload = generateRandomPayload(recordSize, payloadByteList, payload, random);
record = new ProducerRecord<>(topicName, payload);
Callback cb = stats.nextCompletion(sendStartMs, payload.length, stats);
producer.send(record, cb);
}
if (!shouldPrintMetrics) {
producer.close();
/* print final results */
stats.printTotal();
} else {
// Make sure all messages are sent before printing out the stats and the metrics
// We need to do this in a different branch for now since tests/kafkatest/sanity_checks/test_performance_services.py
// expects this class to work with older versions of the client jar that don't support flush().
producer.flush();
/* print final results */
stats.printTotal();
/* print out metrics */
ToolsUtils.printMetrics(producer.metrics());
producer.close();
} - 那么问题只剩下#108439423671562473,为什么别人只用这一个脚本就能得到数百的吞吐量?难道是单个
CPU
足够强劲? - 最后,因运行多个脚本还得将所有的结果加和,也没找到能一次性获取所有生产者吞吐量总和的地方,被迫决定不再使用这个脚本进行压测了……
0x03.rdkafka_performance
用不了官方脚本,自然就准备自己动手,丰衣足食了……目光转向了confluent-kafka-python这个Confluent's Python Client for Apache Kafka
虽然看到有关于kafkatests
的Running Apache Kafka’s client system-tests (kafkatests) with the Python client,不过并没有看懂
众所周知,confluent-kafka-python
和PyKafka底层调用的都是librdkafka,于是决定基于librdkafka
重新进行压测
1.安装librdkafka-devel
RHEL 8
需要先导入confluent
的rpm
源,然后才能进行安装
点击此处 ← 查看折叠
1 | [root@cn-py-dl-r8 ~]# dnf install curl which -y |
2.源码编译librdkafka
不过安装完成之后并没有rdkafka_performance
工具,所以还得去编译源码
点击此处 ← 查看折叠
1 | [root@cn-py-dl-r8 ~]# dnf install gcc gcc-c++ -y |
3.rdkafka_performance
压测
点击此处 ← 查看折叠
1 | [root@cn-py-dl-r8 examples]# ./rdkafka_performance |
./rdkafka_performance -P -t test_broker_1_partition_1_replication_1 -s 1024 -c 3000000 -r 200000 -b localhost:9092 -X queue.buffering.max.kbytes=32768 -X queue.buffering.max.messages=100000 -X request.timeout.ms=5000 -u
其中queue.buffering.max.kbytes
和queue.buffering.max.messages
参考自Producer buffer is too small when using librdkafka以避免BufferError: Local: Queue full
- 增大本地队列至
100000
(没有丧心病狂的到最大值10000000
- 增大默认的
producer buffer
自1MiB
至32MiB
,就像kafka-python
和JVM
一样
0x04.后记
- 压测这周前两天时间都花在
kafka-producer-perf-test.sh
上了,因为有看到过别人仅凭默认参数就能打到很高的吞吐量,一度怀疑是自己的参数没调好,一脸黑人问号
还好及时在家里和良心云环境上做了相同的测试,发现结果竟然基本一致,才意识到可能真的是这个脚本的问题,从而没有继续在这个脚本上浪费不必要的时间( - 多看看别人写的文章对于自己的理解会有非常大的帮助,比如
confluent
或者medium
(前者是Kafka
创始仨人开办的公司;后者上总会搜到些质量很高的文章
毕竟是站在巨人的肩上,谷歌搜索还是能找到不少生产环境的实践,看完之后再回到自己的环境,心里也大概能有个预估,至少不至于一点儿底都没有 - 多看英语/日语文章,中文还是一言难尽,除非是知名平台或者个人博客,其他抄来抄去的低质量平台文章还是算了吧,看那些完全是在浪费时间,更何况里面还可能有错误……
尤其是想看些关于某产品新版本的文章,基本上只能在外文资料中找到了
0x05.引用
Apache Kafka® Performance
Benchmarking Kafka Performance Part 1: Write Throughput
消息队列 CKafka-常见参数配置说明
Kafka设计解析(五)- Kafka性能测试方法及Benchmark报告
librdkafka的安装和使用
Kafka文件存储机制
Kafka快速入门(九)——C客户端
数据不撒谎,Flink-Kafka性能压测全记录!
记一次 Kafka Producer 性能调优实战
kafka生产者Producer参数设置及调优