当前位置: 首页 > 科技观察

从微服务角度比较Kafka和Chronicle

时间:2023-03-13 16:01:56 科技观察

目前,ApacheKafka已经成为应用服务间通信的普遍选择。Kafka不仅可以通过消息并行处理聚合日志,还可以满足低延迟和高吞吐的需求。但是,对于很多微服务应用来说,Kafka的处理速度不一定够快。最近异军突起的开源ChronicleQueue可以用来开发一些只有微秒级延迟的消息框架。下面,我将在微服务应用的吞吐量和可扩展性方面与大家深入对比Kafka和ChronicleQueue。延迟与距离的类比为了说明延迟,我们打个比方:通常情况下,光在真空光纤和铜线中的传播速度约为光速的三分之二,由此产生的瞬时延迟可以理解为信号的距离这段时间出差。使用Chronicle的微服务延迟ChronicleQueue的企业版(Enterprise)在500kmsg/s的低吞吐量下,具有99%ile(正态分布中的平均值)的单个微服务的端到端延迟为3.69微秒。这相当于信号传播了750米的距离,或普通人在伦敦市中心步行10分钟的直线距离(见下图)。使用Kafka的微服务延迟如果使用Kafka执行相同的测试,在100k消息/秒(msg/s)的低吞吐量下,单个微服务在99%ile的端到端延迟约为2633微秒(如果如果它是150kmsg/s,延迟会显着增加)。这相当于信号行进了526公里,普通人从伦敦步行到苏格兰的邓弗里斯需要100多个小时。日志聚合为了满足日志聚合的需求,Kafka在最初的设计中可以提供多个连接器。因此,在典型的系统中,使用Kafka而不是写入日志文件可以提高性能并显着提高可管理性。测试场景我正在Ryzen95950X服务器上部署和运行Ubuntu21.04。为了保持一致性,所有测试都将使用相同的MP600PROXT2TBM.2NVMe驱动器。您可以通过链接获取基准测试的源代码-https://github.com/OpenHFT/Microservice-Benchmark。开源的ChronicleQueuev5.22ea14将使用ChronicleWire进行序列化,写入速度为500kmsg/s。可以配置单个生产者(Producer)和单个下游消费者(Consumer),如下:-Dworkload=500kps.yamlchronicle.yamlChronicleQueueEnterpriseEditionv2.22ea72同样使用ChronicleWire进行序列化,使用500kmsg/s速度写入.可以配置单producer异步buffer模式,单downstreamconsumer,如下:-Dworkload=500kps.yamlchronicle-async.yamlandKafka3.0.0withJacksoninhighthroughputlatency配置下(主要指linger.ms=1),可以100kmsg/s的速度写入。可以配置4个分区8个消费者的JSON如下:-Dworkload=100kps.yamlKafka.yaml配合Jackson的Kafka3.0.0配置高吞吐延迟(主要指linger.ms=1),写入速度可以为250k消息/秒。您可以配置JSON4个分区和8个消费者,如下所示:-Dworkload=250kps.yamlKafka.yaml比较分区和消费者的数量会在一定程度上影响延迟。对于ChronicleQueue,100kmsg/s和500kmsg/s下的性能大致相同。也就是说,ChronicleQueue的一个重要特点就是性能基本不受发布者和消费者数量的影响。因此,我们针对500kmsg/s的需求采用一个发布者、一个消费者和一个微服务。如果您以500kmsg/s的速度对Kafka进行基准测试,它将导致消息排队。基准测试运行的时间越长,延迟就越明显。例如,一旦出现2分钟的突发流量高峰,就会造成接近1分钟的延迟。如果你想让Kafka以250kmsg/s的速度运行,你至少需要4个消费者。当然,如果设置8个消费者的基准,效果会更好,毕竟会调用Kafka的扩展技术。ReleaseLatency上图比较了两者的发布延迟。只看图表,差异可能很明显,但在真实测试用例中,它们之间的延迟不会超过2.6微秒。就测试用例而言,其代码如下。它在不同情况下发布的事件都是512字节的JSON消息。当消息发送时,我们添加两个字段来跟踪它。微服务消息传输虽然我们上面讨论了发布时间和发送和接收预序列化消息的时间,但它很好地比较了Kafka和Chronicle的两种消息解决方案。但这只是延迟难题的一部分。对于微服务,你需要知道从描述未决事件的DTO(数据传输对象)到下游消费者从原始微服务读取结果DTO的时间。对此,我们需要使用微服务的benchmark测试来了解发送同一个事件的每个端到端阶段所花费的时间如下:添加高精度时间戳(System.nanoTime())序列化第一个消息发布第一条消息消费第一条消息反序列化第一条消息调用微服务添加第二条高精度时间戳在另一个主题/队列上序列化第二条消息发布第二条消息消费第二条消息反序列化注意:每条消息在生成时都会创建第二条消息作为响应,因此数量与单跳消息传递基准时间相比,实际消息的数量翻了一番。Kafka在其发布的基准测试中表现如何?虽然在Kafka上发布事件通常需要几微秒,但端到端传输可扩展到毫秒。根据Confluent发布的关于单跳复制消息基准的报告,99%的传输具有5毫秒的端到端延迟。而在我们的基准测试中,一台主机上有2个跃点、序列化和反序列化。在100kmsg/s输出和100kmsg/s返回的情况下,单跳报文传输的延迟基本和200kmsg/s差不多。端到端延迟为了进一步了解Kafka和Chronicle在延迟方面的差距,我们需要通过下面的图表进一步分析。为了便于比较,后一张图放大了前一张图的10倍。在与之前相同的规模下,即使跨越2跳(包括序列化),我们仍然可以看到:ChronicleQueueenterprise保持延迟一致性;而开源的ChronicleQueue虽然大部分时间执行相同的操作,但是它有更高的延迟。这是因为ChronicleQueue企业版在开源的基础上包含了一些特定的功能,可以更好的控制异常值。当然,下图中看不到Kafka的相关曲线,因为延迟很高。对于高达1000微秒的延迟,该图被放大了10倍。如您所见,虽然ChronicleQueue具有较高的异常值,但它们在99.99分位数上非常一致。同样的,Kafka的曲线依然无法显示。对于高达10,000微秒的延迟,该图放大了10倍。在这种规模下,我们无法从Chronicle基准测试中看到太多细节,但两种Kafka配置的典型延迟都出现了。特别是在100kmsg/s(总共200kmsg/s中),99%的延迟约为2,630微秒。这与Confluent的5毫秒基准非常相似。对延迟使用对数刻度对于较大范围的值,使用对数刻度通常很有用。正如您在下图中看到的,它具有一定的可读性,但由于大多数人不习惯阅读对数刻度图,因此他们很难理解延迟到底有多大差异。究竟有多少延迟?另一种可视化Kafka延迟的方法是绘制Kafka和Chronicle之间的延迟比率。下图是Kafka在100kmsg/s(最好的结果之一)和ChronicleQueueEnterpriseEdition在500kmsg/s(即负载是Kafka的5倍)之间的延迟比图。在此基准测试中,Kafka始终至少慢680倍,尽管其吞吐量仅为ChronicleQueue的五分之一。而且,为了让Kafka以100kmsg/s的吞吐量实现最低延迟,我们使用了4个分区和8个微服务。作为比较,ChronicleQueue在所有情况下只需要1个。ChronicleQueue堆(Heap)的使用我们让ChronicleQueue以500kmsg/s的速度写入消息,通过使用G1收集器和默认GC参数,产生了40MB的峰值堆大小,并持续运行5分钟(总计3亿条消息)基准测试。结果如下图所示。当然,ChronicleQueue并没有使用标准的Java序列化功能。Kafka内存使用我们让Kafka以250k/s的速度写入消息,使用2.87GB的峰值堆进行10分钟的基准测试(总共3亿条消息)。启动后触发暂停回收2410次,并发循环回收182次。下图显示,当以128MB堆大小运行时,测试产生了超过139k次GC。总结虽然Kafka是日志聚合的不错选择,但由于其相对较高的端到端延迟,对于涉及微服务的许多用例,其延迟可能会很明显。开源ChronicleQueue可以在超过99.99%的时间内实现小于100微秒的一致延迟。而且即使Kafka的吞吐量只有Chronicle的五分之一,也会出现7毫秒的异常值。译者简介JulianChen,社区编辑,拥有十余年IT项目实施经验,擅长管控内外部资源和风险,专注传播网络与信息安全方面的知识和经验;以多种形式分享前沿技术和新知识;经常在线上和线下开展信息安全培训和讲座。原标题:KafkavsChronicleforMicroservices,作者:PeterLawrey