Disk 1
dd if=/dev/zero of=/mnt/data-1/test bs=1M count=65536 oflag=direct
65536+0 records in
65536+0 records out
68719476736 bytes (69 GB) copied, 210.278 s, 327 MB/s
Disk 2
dd if=/dev/zero of=/mnt/data-2/test bs=1M count=65536 oflag=direct
65536+0 records in
65536+0 records out
68719476736 bytes (69 GB) copied, 209.594 s, 328 MB/s
OS 调优
此外,对于所比较的三个系统,为了获得更好的延迟性能,我们使用 tune -adm 的延迟性能配置文件对操作系统进行了调优,它会禁用磁盘和网络调度器的任何动态调优机制,并使用性能调控器进行 CPU 频率调优。它将每个内核的 p-state 固定在可能的最高频率上,并将 I/O 调度器设置为 deadline,从而提供一个可预测的磁盘请求延迟上限。最后,它还优化内核中的电源管理服务质量(QoS),这是为了提高性能,而不是省电。
内存
与 OMB 中的默认实例相比,i3en.2xlarge
测试实例物理内存几乎是前者的一半(64 GB vs. 122 GB)。优化 Kafka 和 RabbitMQ 使其与测试实例兼容非常简单。两者都主要依赖于操作系统的页面缓存,随着新实例的出现,页面缓存会自动缩小。
然而,Pulsar 代理以及 BookKeeper bookie 都依赖于堆外 / 直接内存缓存,为了使这两个独立进程可以在i3en.2xlarge
实例上良好地运行,我们调整了 JVM 堆 / 最大直接内存大小。具体来说,我们将堆大小从每个 24 GB(原始的 OMB 配置)减半为每个 12 GB,在两个进程和操作系统之间按比例划分了可用物理内存。
在测试中,当目标吞吐量比较高时,我们遇到了java.lang.OutOfMemoryError: Direct buffer memory
错误,如果堆大小再低一点,就会导致 bookie 完全崩溃。这是使用堆外内存的系统所面临的典型的内存调优问题。虽然直接字节缓冲区是避免 Java GC 的一个有吸引力的选项,但是大规模使用是一个颇具挑战性的做法。
5、吞吐量测试
我们开始测量的第一件事是,在网络、磁盘、CPU 和内存资源数量相同的情况下,每个系统可以实现的峰值稳定吞吐量。我们将稳定峰值吞吐量定义为消费者在不增加积压的情况下可以跟得上的最高平均生产者吞吐量。
fsync 的效果
如前所述,Apache Kafka 的默认建议配置是使用底层操作系统指定的页面缓存刷新策略(而不是同步地 fsync 每个消息)flush/fsync 到磁盘,并依赖复制来实现持久性。从根本上说,这提供了一种简单而有效的方法来分摊 Kafka 生产者所使用的不同批次大小的成本,在各种情况下都可以实现最大可能的吞吐量。如果 Kafka 被配置为每次写时 fsync,那么我们就会因强制进行 fsync 系统调用而人为地妨碍了性能,并且没有获得任何额外的好处。
也就是说,考虑到我们将要讨论这两种情况的结果,我们仍然有必要了解在 Kafka 中每次写时 fsync 的影响。各种生产者批次大小对 Kafka 吞吐量的影响如下所示。吞吐量随着批次大小的增加而增加,直到到达“最佳点”,即批次大小足以让底层磁盘完全饱和。在批次大小较大时,将 Kafka 上的每条消息 fsync 到磁盘(图 2 中的橙色条)可以产生类似的结果。注意,这些结果仅在所述实验平台的 SSD 上得到了验证。Kafka 确实在所有批次大小上都充分利用了底层磁盘,在批次大小较小时最大化 IOPS,在批次大小较大时最大化磁盘吞吐量,甚至在强