用 ebpf 可以定位到服务器这边会偶尔丢掉 syn 包,如何进一步定位具体是什么原因丢包的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
xing393939
V2EX    Linux

用 ebpf 可以定位到服务器这边会偶尔丢掉 syn 包,如何进一步定位具体是什么原因丢包的?

  •  
  •   xing393939
    xing393939 2023-05-14 17:00:54 +08:00 2526 次点击
    这是一个创建于 885 天前的主题,其中的信息可能已经有所发展或是发生改变。

    机器 A 向机器 B 建立 TCP 连接,当建立了 20 万的连接后,想建立新的连接就很慢。

    此时在机器 A 上用 tcpdump 抓包可以看到:有的连接可以正常三次握手,有的连接需要发多个 syn 包,有的连续发 6 次 syn 包无响应后应用层就报错了。

    在机器 B 上用 ebpf 来捕获 kfree_skb 的调用,可以发现内核的确是丢包了,但是如何知道为什么会丢包呢?不知道谁能解答。此时内核日志无异常,cpu 和内存也很充足。我是用的 bpftrace 定位的,bpftrace 的执行脚本如下:

    kprobe:kfree_skb { $skb = (struct sk_buff*) arg0; $ip_header = ((struct iphdr *) ($skb->head + $skb->network_header)); // 这里只捕获 daddr 是 192.168.2.120 的包 if ($ip_header->daddr == 0x7802a8c0) { $tcp_header= ((struct tcphdr *) ($skb->head + $skb->network_header + ($ip_header->ihl << 2))); $sport = $tcp_header->source; $dport = $tcp_header->dest; $dport = ($dport >> 8) | (($dport << 8) & 0xff00); $sport = ($sport >> 8) | (($sport << 8) & 0xff00); // 这里只捕获 dport 是 8100 的包 if ($dport == 8100) { time("%H:%M:%S "); printf("%s:%d > %s:%d\n", ntop($ip_header->saddr), $sport, ntop($ip_header->daddr), $dport); } } } 
    18 条回复    2023-05-16 19:03:55 +08:00
    sky96111
        1
    sky96111  
       2023-05-14 17:50:54 +08:00
    USAToday
        2
    USAToday  
       2023-05-14 17:51:36 +08:00
    syn 包丢的话,可以考虑半连接、全连接丢包。我记得有个丢包情况是内核直接丢弃,不会有任何日志
    tomychen
        3
    tomychen  
       2023-05-14 18:10:10 +08:00
    这时候不是应该贴一下最大连接数的配置吗?
    xing393939
        4
    xing393939  
    OP
       2023-05-14 18:18:09 +08:00
    @sky96111 打印 kfree_skb 的上游和下游调用链,bpftrace 也能实现的,问题是接下来怎么继续排查呢
    xing393939
        5
    xing393939  
    OP
       2023-05-14 18:27:55 +08:00
    @tomychen
    ```
    net.core.somaxcOnn= 40960
    net.ipv4.tcp_max_syn_backlog = 40960
    net.ipv4.tcp_syncookies = 1
    ```
    是说三个吗?
    leonshaw
        6
    leonshaw  
       2023-05-14 19:19:41 +08:00
    看一下 nstat 统计
    LGA1150
        7
    LGA1150  
       2023-05-14 22:08:14 +08:00
    nf_conntrack_max 配置了多少?
    jackgoudan
        8
    jackgoudan  
       2023-05-14 23:28:01 +08:00
    猜测是一些队列满了? 最近我们的业务高并发压测遇到过丢包,同事排查过这些问题,好像总体原因就是链接队列放不下了。这会不在公司,看不到排查文档。
    liuxu
        9
    liuxu  
       2023-05-15 01:23:59 +08:00
    /proc/sys/net/ipv4/tcp_abort_on_overflow ,默认 0 是 drop 包,置 1 为 rst ,你置 1 看看会不会 rst ,那就是队列满了
    当然这是个直接却冒进的做法,正确的方法还是 ss -n state syn-recv 看看收了多少 syn

    https://www.alibabacloud.com/blog/tcp-syn-queue-and-accept-queue-overflow-explained_599203
    xing393939
        10
    xing393939  
    OP
       2023-05-15 08:19:44 +08:00
    @LGA1150
    net.netfilter.nf_conntrack_max = 6553600
    net.nf_conntrack_max = 6553600
    xing393939
        11
    xing393939  
    OP
       2023-05-15 08:22:03 +08:00
    @jackgoudan
    很想参考一下你们的排查文档
    xing393939
        12
    xing393939  
    OP
       2023-05-15 08:25:02 +08:00
    @liuxu
    跑了 ss -n state syn-recv ,没有处于这个状态的连接。
    机器 B 配置了 net.ipv4.tcp_abort_on_overflow=1 后,机器 A 上并没有抓包到 rst 包
    salmon5
        13
    salmon5  
       2023-05-15 10:09:34 +08:00
    换硬件试试
    Panic
        14
    Panic  
       2023-05-15 10:39:43 +08:00
    防火墙 selinux 都关了吧,不是队列的话 不贴点内核调用链不好分析了
    tomychen
        15
    tomychen  
       2023-05-15 15:17:40 +08:00
    从你的描述上,感觉像两个东西,一个是#8 说的内核队列打满了,另一个就是 fd 满了,我没法确定你的场景。
    但“机器 A 向机器 B 建立 TCP 连接,当建立了 20 万的连接后,想建立新的连接就很慢。”
    这个描述就很像 fd 满了或者说队列满了,需要等待释放。

    具体排查的情况,我一下子说不上来,可能也得模拟场景。
    lysS
        16
    lysS  
       2023-05-15 17:21:29 +08:00
    20 万的连接,有丢包不是很正常吗?可以试试提升硬件能不能缓解?
    liuxu
        17
    liuxu  
       2023-05-16 00:52:47 +08:00
    @xing393939 #12 不是队列满那这个事情就很麻烦了,我之前抓 k8s 的 dns 数据包丢包,查内核 conntrack ,查了大半天才查出原因, 你可以再检查检查 conntrack ,不一定是这个问题,要收集整个内核调用链的数据包了

    https://www.liuquanhao.com/posts/%E8%AE%B0%E4%B8%80%E6%AC%A1k3s%E7%9A%84dns%E9%97%AE%E9%A2%98%E8%B0%83%E6%9F%A5%E8%A7%A3%E5%86%B3%E8%BF%87%E7%A8%8B/
    jackgoudan
        18
    jackgoudan  
       2023-05-16 19:03:55 +08:00
    @xing393939 内网资料,也不好外传。可以用 skbtracer ,打印出 kfree_skb 的调用栈,看看丢包的函数调用链。我们的情况是丢包位于容器内的 eth0 ,调整 net.core.netdev_max_backlog 参数。具体可能不适用,先从函数调用链入手。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5004 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 05:41 PVG 13:41 LAX 22:41 JFK 01:41
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86