V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
xing393939
V2EX  ›  Linux

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

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

    机器 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   ·   实用小工具   ·   3655 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:23 · PVG 18:23 · LAX 02:23 · JFK 05:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.