消息队列 CKafka 跨洋数据同步性能优化

news2024/12/23 17:25:26

导语

本文主要介绍了 CKafka 在跨洋场景中遇到的一个地域间数据同步延时大的问题,跨地域延时问题比较典型,所以详细记录下来做个总结。

一. 背景

为了满足客户跨地域容灾、冷备的诉求,消息队列 CKafka 通过连接器功能,提供了跨地域数据同步的能力,支持跨地域秒级准实时数据同步。

整体的架构图:

如上图所示,CKafka 跨地域数据同步能力,底层基于 Kafka Connect 集群实现,并通过Vpcgw Privatelink 打通云上环境。

数据同步主要流程如下:

1.  Connect 集群初始化 Connect Task,每个 Task 会新建多个 Worker ConsumerClient(具体多少取决于源实例的分区数)从源 CKafka 实例拉取数据。

2.  Connect 集群从源实例拉取数据后,会启动 Producer 发送数据到目标 CKafka 实例。

在某个客户业务场景中,客户希望通过跨地域同步能力,把香港 CKafka 实例的数据同步到美东 CKafka 实例,在使用过程中引发了一个跨地域延时的诡异问题!

二. 问题现象

客户在使用跨地域同步能力的时候,发现数据从香港->美东同步数据的延时非常大,并且能明显的看到 Connect 作为 Consumer 去源实例(香港)消费拉取数据的消息堆积非常大。

消息堆积

根据过往的经验,我们国内地域的同步不会出现这么大的延时,为什么这次的跨地域会有这么大的延时呢?

三. 问题分析

消息堆积常见的原因

Kafka 在生产消费过程中,出现消息堆积常见的原因主要有以下几点:

● Broker 集群负载过高:包括 CPU 高、内存高、磁盘 IO 高导致消费吞吐慢。

● 消费者处理能力不足:如果消费者的处理能力不足,无法及时消费消息,就会导致消息堆积。可以通过增加消费者的数量或者优化消费者的处理逻辑来解决该问题。

● 消费者异常退出:如果消费者异常退出,就会导致消息无法及时消费,从而在 Broker 中积累大量未消费的消息。可以通过监控消费者的状态和健康状况,及时发现并处理异常情况。

● 消费者提交偏移量失败:如果消费者提交偏移量失败,就会导致消息重复消费或者消息丢失,从而在 Broker 中积累大量未消费的消息。可以通过优化消费者的偏移量提交逻辑,或者使用 Kafka 的事务机制来保证偏移量的原子性和一致性。

● 网络故障或者 Broker 故障:如果网络故障或者 Broker 故障,就会导致消息无法及时传输或者存储,从而在 Broker 中积累大量未消费的消息。可以通过优化网络的稳定性和可靠性,或者增加 Broker 的数量和容错能力来解决该问题。

● 生产者发送消息速度过快:如果生产者发送消息速度过快,超过了消费者的处理能力,就会导致消息堆积。可以通过调整生产者的发送速度,或者增加消费者的数量来解决该问题。

基于以上原因,我们首先排查了 Connect 集群所有节点和源目标 CKafka 实例所有节点的负载,发现各项监控指标都很健康、集群负载很低,ConnectConsumer 消费能力也没有出现异常和性能瓶颈。

但是单次拉取消息的速率却很低,平均消费速度325KB/s,这个是不符合预期的。

(注:上图中的 bytes-consumed-rate 指标代表每秒消费的字节数)

既然集群负载没有问题,于是我们进行了更深层的排查分析:

第一阶段分析:排查网络速率

消息延时大,我们首先想到的就是网络问题,所以立刻着手压测网络。通过 Iperf3 、Wget 探测网络速率。

Iperf3 压测,速度在225Mbps 。

Wget 在 Connect 集群直连香港,下载速度在20MB/s。

这两个测试说明:在同样环境下,网络传输速率并不低,可以达到20MB/s。那既然网络带宽没问题,问题又会出在哪呢?

第二阶段分析:内核调参数

网络没有问题,那会不会是 Kafka 网络相关的应用程序参数、以及内核网络相关的参数设置的不合理呢?

1、我们首先进行了内核调参,跟网络相关的内核参数主要有:

系统默认值:
net.core.rmem_max=212992
net.core.wmem_max=212992
net.core.rmem_default=212992
net.core.wmem_default=212992
net.ipv4.tcp_rmem="4096    87380   67108864"
net.ipv4.tcp_wmem="4096    65536   67108864"

---------------------------------------------------------
调整内核参数:
sysctl -w net.core.rmem_max=51200000
sysctl -w net.core.wmem_max=51200000
sysctl -w net.core.rmem_default=2097152
sysctl -w net.core.wmem_default=2097152
sysctl -w net.ipv4.tcp_rmem="40960 873800 671088640"
sysctl -w net.ipv4.tcp_wmem="40960 655360 671088640"

调整TCP的拥塞算法为bbr:
sysctl -w net.ipv4.tcp_congestion_control=bbr

整体内核参数的值我们都调大了(尽管我们认为系统内核默认值也不小),同时我们还调整了TCP 的拥塞算法。

这里解释一下为什么要调整 TCP 的拥塞算法。

(参考资料:[[译] [论文] BBR:基于拥塞(而非丢包)的拥塞控制(ACM, 2017)]([译] [论文] BBR:基于拥塞(而非丢包)的拥塞控制(ACM, 2017)))

因为这个延时发生在跨地域间且跨洋了,使用 BBR,可以获得显著的网络吞吐量的提升和延迟的降低。吞吐量的改善在远距离路径上尤为明显,比如跨太平洋的文件或者大数据的传输,尤其是在有轻微丢包的网络条件下。延迟的改善主要体现在最后一公里的路径上,而这一路径经常受到缓冲膨胀(Bufferbloat)的影响。所谓“缓冲膨胀”指的是网络设备或者系统不必要地设计了过大的缓冲区。当网络链路拥塞时,就会发生缓冲膨胀,从而导致数据包在这些超大缓冲区中长时间排队。在先进先出队列系统中,过大的缓冲区会导致更长的队列和更高的延迟,并且不会提高网络吞吐量。由于 BBR 并不会试图填满缓冲区,所以在避免缓冲区膨胀方面往往会有更好的表现。

经过内核参数调整后,验证发现延时并没有很大的改善。

2、在云产品技术服务专家大佬的提醒下,确认连接的 Receive Buffer 设置过小,调内核参数才没有生效,怀疑是应用层进行了设置。

于是我们调整了 Kafka 应用程序网络参数 Socket.Send.Buffer、Socket.Recevie.Buffer 的参数值:

(1)把源目标 CKafka 实例 Broker 的 Socket.Send.Buffer.Bytes 参数从默认64KB调整为使用系统的 Socket Send Buffer。

Kafka 内核关于 Socket Send Buffer 的代码:

Tips】:

在 Kafka 中,TCP 发送缓冲区的大小由应用程序和操作系统共同决定。应用程序可以通过设置 Socket.Send.Buffer.Bytes 参数来控制 TCP 发送缓冲区的大小,操作系统也可以通过设置 TCP/IP 协议栈的参数来控制 TCP 发送缓冲区的大小。

应用程序设置的 Socket.Send.Buffer.Bytes 参数会影响 TCP 发送缓冲区的大小,但是操作系统也会对 TCP 发送缓冲区的大小进行限制。如果应用程序设置的 Socket.Send.Buffer.Bytes 参数超过了操作系统的限制,那么 TCP 发送缓冲区的大小就会被限制在操作系统的限制范围内。如果应用程序设置的 Socket.Send.Buffer.Bytes=-1 ,那么 TCP 发送缓冲区的大小就会默认使用操作系统的 TCP 发送缓冲区的大小。需要注意的是,TCP 发送缓冲区的大小会影响网络的吞吐量和延迟时间。如果 TCP 发送缓冲区的大小过小,会导致网络的吞吐量和性能下降;如果 TCP 发送缓冲区的大小过大,会导致网络的延迟时间增加。因此,需要根据实际情况进行调整,以达到最优的性能和可靠性。

(2)把客户端 Connect Consumer 的 Receive.Buffer.Bytes 参数从默认64KB调整为使用系统的Socket Receive Buffer。把客户端 Max.Partition.Fetch.Bytes 这个分区最大拉取大小调整到了5MB。

调整后,我们迅速和客户协调时间重启集群,验证这个调参。调整完后的效果明显:单连接的平均速度从300KB/s提升到了2MB/s以上:

可以看到调大 Kafka 的 Socket 接收、发送参数后,效果确实很明显,同步数率上来了。当我们以为延时问题解决了的时候,问题又出现了!

第三阶段分析:深挖根因

上面第二阶段的 Kafka 调参应用到客户集群,观察一天后,客户反馈集群整体延时有所好转,但是部分分区延时还是很大。我们也观测到大概一半分区的同步速率依然很低。

(注:上图中的 Bytes-Consumed-Rate 指标 代表每秒消费的字节数)

(1)为什么部分连接速度还是很低?

我们首先通过运营后台确定了消费速率低的 Partition 对应的 ConsumerGroupID,通过这个ConsumerGroupID 抓包定位对应的慢速 TCP 连接。

定位连接后,进行抓包分析:

从上可以看到 Server 发送一段数据之后,会暂停一段时间,大约一个 RTT 再继续发送。统计每个发送间隔之间的数据包的总大小,大概64KB。这基本能说明 TCP 的发送窗口被限制在64KB。但是,通过抓包其他速度正常的连接发现并没有这种限制。一般来说,TCP 发送窗口的实际大小是跟 Window Scale 有关的,这个只能在连接建立的时候确认。

Tips】:TCP Window Scale, TCP 的窗口缩放因子。(参考资料:How to determine TCP initial window size and scaling option? Which factors affect the determination? - Red Hat Customer Portal)

在传统的 TCP 协议中,TCP 窗口大小的最大值只能达到 64KB,这限制了 TCP 协议的传输速度和效率。为了解决这个问题,TCP Window Scale 机制被引入到 TCP 协议中。

TCP 窗口大小 = (接收端窗口大小) * (2 ^ TCP Window Scale 选项的值)

需要注意的是,TCP Window Scale 机制需要在 TCP 三次握手连接建立时进行协商,以确定 TCP 窗口大小的扩展方式和参数。

为了抓取建连的情况,我们尝试重启单个 Partition 的消费任务,但是发现,只要一重启,消费的速度就能恢复,窗口的大小就不会出现瓶颈。

(2)为什么发送窗口被限制?

为了复现问题,我们模拟构造了客户的使用场景,进行了整体的场景复现。最终确认只有在任务全量重启的时候才会出现这个问题。 在任务重启过程中,我们进行了服务端的整体抓包。定位到了正常连接和异常连接,对比了建连的过程,最终确认了慢速的连接中 Window Scale 确实没有生效!

正常连接建连过程:

慢速连接建连过程:

从上图可以看出,慢速连接中,Server 在返回 Syn/Ack 包的时候,没有"WS=2",说明并没有开启 Window Scale 选项,进而导致整个连接的发送窗口被限制在了64KB,吞吐就上不去了。Client 返回最后一个 Ack 的时候,也明确显示了"no window scaling used"。

(3)为什么Window Scale 概率性不生效?

到这一步,我们就需要解释为什么 Server 端发送 Syn/Ack 的时候会概率性地不开 Window Scale 呢? 这里,计算组大佬给出了一个相似的 Case 提供我们学习:kubernetes - 深度复盘-重启 etcd 引发的异常 - 个人文章 - SegmentFault 思否 从中可以得到一个信息: 看起来是 SYN Cookie 生效的情况下,对方没有传递 Timestamp 选项过来(实际上,按照 SYN Cookie 的原理,发送给对端的回包中,会保存有编码进 Tsval 字段低 6 位的选项信息),就会调用 Tcp_Clear_Options, 清空窗口放大因子等选项。 我们从系统日志里面,我们也能观察到在任务整体重启的时候确实触发了 SYN Flood。

(4)为什么服务端没收到 Tsval (TCP 的 Timestamp Value) 呢?

上面有介绍过我们的数据同步时经过了公司内部的一个 VPCGW,我们分别在 Client 和 Server 上分别抓包,最终确认是 VPCGW 把 Client 发出的 Tsval 吞了。同时也跟 VPCGW 的研发同学确认,在 NAT 环境下,不转发 Timestamp 是预期行为,主要为了解决特殊情况下的丢包问题,NAT环境下tcp_timestamps问题_centos nat tcp_timestamps_清风徐来918的博客-CSDN博客。不过这个问题在新内核中,已经不存在,所以可以排期提供开放 Timestamp 的能力。

根因定位

一路分析深挖下来,至此,问题的根因就清晰了:

Connect Consumer 批量启动,触发了大量新建 TCP 连接,短时间的大量新建连接触发了 SYN Cookie 保护检查逻辑。但是因为客户端没有发送 Timestamp 选项传过来,造成了服务端把窗口放大因子清除,最终造成连接的发送窗口最大64KB,在大延迟的场景下影响了传输性能。

四. 我们的解决方案

问题的根因找到了,解决方案就清晰明朗了。

● 规避方案:我们调整了 Connect Woker 初始化的并发度,降低 TCP 初始化建连的速度,保证不会触发 SYN Cookie, 来保证后续数据同步的性能。

● 最终方案:推动 VPCGW 打开 TCP Timestamp 的能力。

五. 总结

问题表面是跨地域数据同步请求慢的问题,但是一路深挖下来确实一个非常底层的网络问题。

这个问题的发生比较罕见,因为这个问题发生的条件比较复杂,主要是跨地域存在网络延时、同时大量的 TCP 建连、加上 VPCGW 路由传输过程中吃掉了 TCP Timestamp参数, 叠加起来导致了这个问题。

我们面对问题需要保持敬畏之心,深挖到底!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/779398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.4.tensorRT基础(2)-学习第一个插件的编写

目录 前言1. 插件2. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。 本次课程学习 tensorRT 基础-学习第一个插件的编写 课程大…

python sorted函数

python列表排序 简单记一下python中List的sort方法(或者sorted内建函数)的用法。 关键字: python列表排序 python字典排序 sorted List的元素可以是各种东西,字符串,字典,自己定义的类等。 sorted函数用法如…

【项目 进程6】 2.13 匿名管道通信案例 2.14管道的读写特点和管道设置为非阻塞

文章目录 2.13 匿名管道通信案例匿名管道的使用实现 ps aux | grep xxx 父子进程间通信 2.14管道的读写特点和管道设置为非阻塞管道的读写特点:总结设置管道非阻塞 2.13 匿名管道通信案例 匿名管道的使用 一般匿名管道不推荐父进程与子进程交叉读写数据&#xff0c…

nginx 配置 wss加密访问 mqtt

1. 在服务器上部署mqtt服务 2.在宝塔上配置域名证书 3.nginx配置websocket server {listen 80;listen 443 ssl http2;server_name ws-xx.example.com;index index.php index.html index.htm default.php default.htm default.html;root /www/wwwroot/ws-xx.example.com;loca…

金融软件技术:创新与安全并行驶

随着科技的迅速发展,金融行业正经历着一场前所未有的数字化转型。金融机构需要不断创新和提升效率,以满足客户需求,并保持竞争优势。在这个数字时代中,金融软件技术成为了实现这一目标的关键要素。本文将从两个方面探讨金融软件技…

fastadmin采坑之富文本编辑器

整了好久才弄好,后缀为content,类型为text 或者longtext类型,这样做命令行才能成功

Python教程(5)——Python的第一个程序

python的环境以及IDE都准备好之后,我们就可以开始Python之旅了。Python的第一个程序通常是打印输出"Hello, World!",非常简单。以下是一个示例: print("Hello, World!")运行python代码 首先必须明白python是一门动态语…

Asp.net Core配置CORS 跨域无效(记录一下)

问题 学习老杨的英语网站项目,运行项目时,发现出现了跨域的问题。 然后自己建一项目,进行配置,测试,发现配置CORS 跨域时,发现跨域的配置无效,依旧报错。 解决 网上找了一天,然后…

【Uniapp,Vue】阻止父元素事件覆盖子元素事件

有个需求,点击一个元素,让弹出框显示,点击弹出框以外的区域,就关闭弹出框,如下代码所示。 但是这样有个问题,就是当弹出框显示以后,点击弹出框的区域也会触发父元素的点击事件,使得i…

【多模态】17、CORA | 将 CLIP 使用到开集目标检测

文章目录 一、背景二、方法2.1 总体结构2.2 region prompting2.3 anchor pre-matching 三、效果 论文:CORA: Adapting CLIP for Open-Vocabulary Detection with Region Prompting and Anchor Pre-Matching 代码:https://github.com/tgxs002/CORA 出处…

小程序路由跳转页面重复问题

目标:想要某个页面在历史中(页面栈)只显示一次 什么是页面栈: 在小程序开发中,页面栈是指小程序当前打开的页面的层级关系堆栈。每当打开一个新页面时,它会被放置在页面栈的顶部,而当前页面就位…

如何实现外网远程访问路由内部服务器主机端口应用?

路由器是上网常见的设备。在我们开通网络接入带宽时,或需要进行管理路由网络操作时,就需要登录路由后台设置配置相关操作。 我们在涉及路由管理方面经常会遇到一些常见的问题。路由管理入口地址是什么?如何配置路由有线网络或无线网络或分配…

uniapp开启消息通知/提示(使用uniPush)

亲爱的小伙伴们,最近对uniPush有稍许研究,当前研究出一些心得,现在分项给大家,希望对大家的uniapp之路有所帮助。本次的教程是教会你如何使用uniPush自定义消息通知,同时还附带添加消息提示音添加,多的不说…

linux - ping -I 的一种异常场景处理分析

实验 用ping -I 指定一个没有配置ip地址且已经up起来的网卡。 结果 linux会根据路由规则选择一个其他网卡的ip,但,还是会从该指定网卡发送。 iputils 用-I指定网卡对应的bind操作 获取该socket的本地ip,当bind了NIC,且该NIC没有…

网络传输媒体

物理层下面的传输媒体分为两种:导向型传输媒体和非导向型传输媒体。 一、导向型传输媒体 同轴电缆: 图示: 分类: 基带同轴电缆:用于数字传输,在早期局域网中广泛使用宽带同轴电缆:用于模拟传输…

element+vue 之预览pdf组件

1.组件previewPdf <template><el-drawer:title"drawerName":visible.sync"drawerVal":direction"direction":append-to-body"true"size"100%":before-close"drawerClose"><iframe :src"url&…

前端工程化第二章:webpack5基础(中)

文章目录 1. 处理css资源&#xff08;css文件拆分 mini-css-extract-plugin&#xff09;1.1. package.json1.2. webpack.config.js 2. 处理预编译器&#xff08;less/scss&#xff09;2.1. src/index.js2.2. src/index.less2.3. src/index.scss2.4. webpack.config.js 3. 适配&…

【《机器学习和深度学习:原理、算法、实战(使用Python和TensorFlow)》——以机器学习理论为基础并包含其在工业界的实践的一本书】

机器学习和深度学习已经成为从业人员在人工智能时代必备的技术&#xff0c;被广泛应用于图像识别、自然语言理解、推荐系统、语音识别等多个领域&#xff0c;并取得了丰硕的成果。目前&#xff0c;很多高校的人工智能、软件工程、计算机应用等专业均已开设了机器学习和深度学习…

LeetCode55.Jump-Game<跳跃游戏>

题目&#xff1a; 思路&#xff1a; 大神的思路,我是不会... 代码是&#xff1a; //大神的代码code class Solution { public:bool canJump(vector<int>& nums) {int k 0;for (int i 0; i < nums.size(); i) {if (i > k) return false;k max(k, i nums[i…

Mysql群集MHA高可用配置

目录 一、MHA概述 1.简介 2.MHA 的组成 &#xff08;1&#xff09;MHA Node&#xff08;数据节点&#xff09; &#xff08;2&#xff09;MHA Manager&#xff08;管理节点&#xff09; 3.MHA的特点 二、搭建MHA高可用数据库群集 1.主从复制 &#xff08;1&#xff09;…