You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python、MongoDB、Redis集成测试与TCP乒乓阈值相关的Linux内核性能问题问询

Python、MongoDB、Redis集成测试与TCP乒乓阈值相关的Linux内核性能问题问询

大家好,最近我碰到了个挺折腾的性能问题,排查了好一阵还是有点困惑,想在这里问问有没有朋友遇到过类似情况,或者能给我点思路。

先说说我的场景:我维护着一个Python 3.12的应用,用PyTest写的集成测试链,涉及MongoDB(依赖PyMongo和Motor)和Redis。所有组件——测试代码、应用本身、Mongo、Redis——都跑在本地Docker Compose环境里,完全没有跨物理主机的网络通信。而且我确认过,PyMongo客户端默认就开启了TCP_NODELAY和SO_KEEPALIVE:

sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)

奇怪的性能差异

这套测试在Ubuntu 20.04(内核5.4)上能跑出3倍的性能提升,但换到Ubuntu 22.04+,或者内核版本在5.10.135及之后的Linux系统上,这个性能优势就彻底消失了。

内核提交的排查过程

我对Linux内核做了二分查找,终于定位到了关键的内核提交:

  • 最初是5.1版本里的tcp: change pingpong threshold to 3这个提交带来了性能提升
  • 但在5.10.135版本,这个提交被官方回滚了
  • 到了2023年的6.7内核,官方又引入了net.ipv4.tcp_pingpong_thresh这个sysctl参数,默认值设为1,允许用户手动配置这个阈值

尝试解决但遇到的问题

我本来以为把net.ipv4.tcp_pingpong_thresh改成3就能恢复之前的性能,但试了之后发现完全没用。反复测试后才发现,问题出在引入这个sysctl参数的提交上:如果我先回滚5.10.135的那个回滚提交,再应用这个sysctl参数的提交,就能重新获得预期的3倍性能提升。

于是我自己写了个小补丁,确实把性能拉回来了,补丁内容如下:

From: Oleg Neumyvakin <oneumyvakin@gmail.com>
Date: Sun, 27 Jul 2025 20:40:47 +0700
Subject: [PATCH] Fix tcp pingpong threshold

---
 net/ipv4/tcp_ipv4.c | 2 +-
 net/ipv4/tcp_output.c | 13 ++++++++-----
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f603ad9307af..fe5b1545c499 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -3288,7 +3288,7 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.sysctl_tcp_syn_linear_timeouts = 4;
        net->ipv4.sysctl_tcp_shrink_window = 0;

-       net->ipv4.sysctl_tcp_pingpong_thresh = 1;
+       net->ipv4.sysctl_tcp_pingpong_thresh = 3;
        return 0;
 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 8e6ebf35ed58..912080d8d80a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -167,13 +167,16 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
        if (tcp_packets_in_flight(tp) == 0)
                tcp_ca_event(sk, CA_EVENT_TX_START);

-       tp->lsndtime = now;
-
        /* If it is a reply for ato after last received
-        * packet, increase pingpong count.
+        * packet, increase pingpong count.
+        * If this is the first data packet sent in response to the
+        * previous received data,
         */
-       if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
+       if (before(tp->lsndtime, icsk->icsk_ack.lrcvtime) &&
+           (u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
                inet_csk_inc_pingpong_cnt(sk);
+
+       tp->lsndtime = now;
 }

 /* Account for an ACK we sent. */
-- 
2.43.0

困惑的点

不过有个奇怪的地方:我用Python或者YCSB做了Mongo和Redis的合成测试,却完全测不出性能差异,只有在实际的集成测试场景下才会出现这个问题。

所以最后想问问大家:有没有人在使用Python、MongoDB、Redis的组合时,碰到过和TCP乒乓阈值相关的性能问题?或者对我这个补丁的思路有什么看法?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:25:29