软件测试程序员

腾讯云CKafka压测踩坑记录

2020-04-24  本文已影响0人  Fox_Nick

由于最近项目要上腾讯云,不得不对腾讯云CKafka进行压测,评估kafka的处理性能是否满足项目需求。(项目期望Kafka能够处理上千万级别的MQ)

一、 明确测试目的

本次性能测试在UAT环境下腾讯云服务器上CKafka处理MQ消息能力进行压力测试。测试包括对Kafka写入MQ消息和消费MQ消息进行压力测试,根据100w、500w和1000w级别的消息处理结果,评估Kafka的处理性能极限值。

二、 Kafka测试前期准备

2.1  Kafka的性能测试主要测试kafka的吞吐量,kafka吞性能为生产者在向kafka传入消息时的写入量,kafka的吐性能为消费者在kafka集群中消费的能力,也就是读取量。

2.2 Borker相关

        Kafka的borker是kafka集群的缓存代理,消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。具体可参考kafka官方文档。

2.3 Cousumer相关

       Consumer为kafka的消费者,同一个topic消费者越多越快,但是需要注意的是,消费者的数量不能超过topic的分区数量,因为每个topic的每个分区只能被一个消费者消费,多出来的消费者会无信息可消费。导致资源浪费。具体可参考腾讯云Ckafka指南。

三、Kafka常用参数配置

3.1 生产端常用参数配置如下:

# 生产者会尝试将业务发送到相同的 Partition 的消息合包发送到 Broker,batch.size 设置合包的大小上限。默认为 16KB。batch.size 设太小会导致吞吐下降,设太大会导致内存使用过多。

batch.size=16384

# Kafka producer 的 ack 有 3 种机制,分别说明如下:

# -1 或 all:Broker 在 leader 收到数据并同步给所有 ISR 中的 follower 后,才应答给 Producer 继续发送下一条(批)消息。 这种配置提供了最高的数据可靠性,只要有一个已同步的副本存活就不会有消息丢失。注意:这种配置不能确保所有的副本读写入该数据才返回,可以配合 Topic 级别参数 min.insync.replicas 使用。

# 0:生产者不等待来自 broker 同步完成的确认,继续发送下一条(批)消息。这种配置生产性能最高,但数据可靠性最低(当服务器故障时可能会有数据丢失,如果 leader 已死但是 producer 不知情,则 broker 收不到消息)

# 1:生产者在 leader 已成功收到的数据并得到确认后再发送下一条(批)消息。这种配置是在生产吞吐和数据可靠性之间的权衡(如果leader已死但是尚未复制,则消息可能丢失)

# 用户不显示配置时,默认值为1。用户根据自己的业务情况进行设置

acks=1

# 控制生产请求在 Broker 等待副本同步满足 acks 设置的条件所等待的最大时间

timeout.ms=30000

# 配置生产者用来缓存消息等待发送到 Broker 的内存。用户要根据生产者所在进程的内存总大小调节

buffer.memory=33554432

# 当生产消息的速度比 Sender 线程发送到 Broker 速度快,导致 buffer.memory 配置的内存用完时会阻塞生产者 send 操作,该参数设置最大的阻塞时间

max.block.ms=60000

# 设置消息延迟发送的时间,这样可以等待更多的消息组成 batch 发送。默认为0表示立即发送。当待发送的消息达到 batch.size 设置的大小时,不管是否达到 linger.ms 设置的时间,请求也会立即发送

linger.ms=0

# 生产者能够发送的请求包大小上限,默认为1MB。在修改该值时注意不能超过 Broker 配置的包大小上限16MB

max.request.size=1048576

# 压缩格式配置,目前 0.9(包含)以下版本不允许使用压缩,0.10(包含)以上不允许使用 GZip 压缩

compression.type=[none, snappy, lz4]

# 客户端发送给 Broker 的请求的超时时间,不能小于 Broker 配置的 replica.lag.time.max.ms,目前该值为10000ms

request.timeout.ms=30000

# 客户端在每个连接上最多可发送的最大的未确认请求数,该参数大于1且 retries 大于0时可能导致数据乱序。 希望消息严格有序时,建议客户将该值设置1

max.in.flight.requests.per.connection=5

# 请求发生错误时重试次数,建议将该值设置为大于0,失败重试最大程度保证消息不丢失

retries=0

# 发送请求失败时到下一次重试请求之间的时间

retry.backoff.ms=100

消费者参数配置如下:

# 是否在消费消息后将 offset 同步到 Broker,当 Consumer 失败后就能从 Broker 获取最新的 offset

auto.commit.enable=true

# 当 auto.commit.enable=true 时,自动提交 Offset 的时间间隔,建议设置至少1000

auto.commit.interval.ms=5000

# 当 Broker 端没有 offset(如第一次消费或 offset 超过7天过期)时如何初始化 offset,当收到 OFFSET_OUT_OF_RANGE 错误时,如何重置 Offset

# earliest:表示自动重置到 partition 的最小 offset

# latest:默认为 latest,表示自动重置到 partition 的最大 offset

# none:不自动进行 offset 重置,抛出 OffsetOutOfRangeException 异常

auto.offset.reset=latest

# 标识消费者所属的消费分组

group.id=""

# 使用 Kafka 消费分组机制时,消费者超时时间。当 Broker 在该时间内没有收到消费者的心跳时,认为该消费者故障失败,Broker 发起重新 Rebalance 过程。目前该值的配置必须在 Broker 配置group.min.session.timeout.ms=6000和group.max.session.timeout.ms=300000 之间

session.timeout.ms=10000

# 使用 Kafka 消费分组机制时,消费者发送心跳的间隔。这个值必须小于 session.timeout.ms,一般小于它的三分之一

heartbeat.interval.ms=3000

# 使用 Kafka 消费分组机制时,再次调用 poll 允许的最大间隔。如果在该时间内没有再次调用 poll,则认为该消费者已经失败,Broker 会重新发起 Rebalance 把分配给它的 partition 分配给其他消费者

max.poll.interval.ms=300000

# Fecth 请求最少返回的数据大小。默认设置为 1B,表示请求能够尽快返回。增大该值会增加吞吐,同时也会增加延迟

fetch.min.bytes=1

# Fetch 请求最多返回的数据大小,默认设置为 50MB

fetch.max.bytes=52428800

# Fetch 请求等待时间

fetch.max.wait.ms=500

# Fetch 请求每个 partition 返回的最大数据大小,默认为10MB

max.partition.fetch.bytes=1048576

# 在一次 poll 调用中返回的记录数

max.poll.records=500

# 客户端请求超时时间,如果超过这个时间没有收到应答,则请求超时失败

request.timeout.ms=305000

Broker 配置参数说明如下:

# 消息体的最大大小,单位是字节

message.max.bytes=1000012

# 是否允许自动创建 Topic, 默认是 false,当前可以通过控制台或云 API 创建

auto.create.topics.enable=false

# 是否允许调用接口删除 Topic

delete.topic.enable=true

# Broker 允许的最大请求大小为16MB

socket.request.max.bytes=16777216

# 每个 IP 与 Broker 最多建立5000个连接

max.connections.per.ip=5000

# offset 保留时间,默认为7天

offsets.retention.minutes=10080

# 没有 ACL 设置时,允许任何人访问

allow.everyone.if.no.acl.found=true

# 日志分片大小为1GB

log.segment.bytes=1073741824

# 日志滚动检查间隔5分钟,当设置保留时间小于5分钟时,也可能需要等待5分钟才会清空日志

log.retention.check.interval.ms=300000

四、场景设计

4.1 Kafka写入消息压力测试

写入场景设置

4.2 Kafka消费压测测试

消费场景设置

五、测试方法

5.1 在服务器上使用Kafka自带的测试脚本,分别模拟100w、500w和1000w的消息写入请求,查看Kafka处理不同数量级的消息数时的处理能力,包括每秒生成消息数、吞吐量、消息延迟时间。Kafka消息吸入创建的topic命名为test-2,使用命令发起消费该topic的请求,查看Kafka消费不同数量级别的消息时的处理能力。

5.2 压测命令(脚本执行目录:bin/)

脚本模板

            zookeeper脚本:./kafka-consumer-perf-test.sh --zookeeper IP:port --topic forbid_resources_topic --fetch-size 1048576 --messages 10000 --threads 1

 写入脚本命令的参数解析:

--topic topic名称,本例为test-2

--num-records 总共需要发送的消息数,本例为100000

--record-size 每个记录的字节数,本例为1200

--throughput 每秒钟发送的记录数,本例为5000

--producer-props bootstrap.servers=localhost:9092 (发送端的配置信息,本次测试取集群服务器中的一台作为发送端,可在kafka的bin目录,查看server.properties中配置的zookeeper.connect的值,默认端口:9092)

消费脚本参数解析:

--consumer指定consumer的链接信息,本例为localhost:2181 ;

--topic 指定topic的名称,本例为test-2;

--fetch-size 指定每次fetch的数据的大小,本例为1048576,也就是1M

--messages 总共要消费的消息个数,本例为1000000,100w

六、测试结果

写入100W结果:

100W写入结果

消费100W结果:

100W消费

注意:这里的坑就来了实际消费数量与脚本设置的消费数量不一致,在这里的这个问题查了很多资料发现两个问题,一会下面慢慢解释,先来看每个字段的意思。

我们先来看看消费的每个数据字段的含义,如下图:

字段含义

上图我们可以看出,data.consumed.in.nMsg(总消费消息数)与脚本中messages设置的值不一致;设置消费100W,实际消费121431条消息。

坑就在这里,由于是买的腾讯云的PASS服务,很多东西都没办法获取权限查看,只能一步步和客服沟通,挨个排查。

腾讯售后客服也给发了案例和教程,发现教程里也是实际消费和设置消费数不一致;,此处省略一万字。。。

最终在无意之间更改了Topic分区数之后再次运行脚本发现问题消失了,测试环境的Topic分区设置为1,后续增加分区数发现能实际消费和设置消费消息数一致。最后经过多次测试最终Topic分区数设置为3。这次之后发现忽略了腾讯云提供的压测指南中的底部有几句话;

测试建议:

为了提高吞吐量,建议创建分区时数量 ≥ 3 (因后端 CKafka 集群节点数量最少是3,如只创建1个分区则分区会分布在一个 Broker 上面,影响性能)。

由于 CKafka 是分区级别消息有序的,因此过多的分区也会影响生产性能,根据实际压测,建议分区数不超过6。

为了保证压力测试的效果,需要多客户端模拟一定的并发,建议采用多台机器作为压测客户端(生产端),每台启动多个压测程序,提高并发。此外建议每1s启动一个生产者,避免同时启动所有生产者导致测试机器高负载。

在多次和腾讯售后客服沟通和交流,后续也有和腾讯相关后端开发沟通,发现竟然连开发都解释不清楚出现这个问题的原因,只要深入了解,就会含糊解释说:“我们卖了这么多产品,Kafka肯定不会有问题的”,其内部也没有关于Kafka相关的压测分析案例。可能是我寡闻,在此记录,也是分享出此次压测的踩坑经历。

上一篇下一篇

猜你喜欢

热点阅读