Kbase #6: Aliyun Linux 2 ss 输出 Send-Q 字段为0-阿里云开发者社区

开发者社区> 开发与运维> 正文

Kbase #6: Aliyun Linux 2 ss 输出 Send-Q 字段为0

简介: 问题解决状态:[ 已解决 ] 1. 问题所处环境 / Environment 镜像: aliyun-2.1903-x64-20G-alibase-20190507.vhd 及之前版本 内核: kernel-4.19.43-13.al7.x86_64 及之前版本 2. 问题描述 / Issue ss -lnt 命令输出的 listening TCP socket 的 Send-Q 字段为0。

问题解决状态:[ 已解决 ]

1. 问题所处环境 / Environment

  • 镜像: aliyun-2.1903-x64-20G-alibase-20190507.vhd 及之前版本
  • 内核: kernel-4.19.43-13.al7.x86_64 及之前版本

2. 问题描述 / Issue

ss -lnt 命令输出的 listening TCP socket 的 Send-Q 字段为0。

# ss -lnt
State       Recv-Q Send-Q                            Local Address:Port                                           Peer Address:Port
LISTEN      0      0                                             *:35107                                                     *:*
LISTEN      0      0                                             *:38727                                                     *:*
LISTEN      0      0                                             *:5355                                                      *:*
LISTEN      0      0                                             *:111                                                       *:*

根据 manual page:

Send-Q
       Established:  The  count  of bytes not acknowledged by the remote host.  
       Listening: Since Kernel 2.6.18 this column contains the maximum
       size of the syn backlog.

对于 listening TCP socket,Send-Q 字段应该描述该 socket 的 syn backlog 的最大值;
在 Linux 下,该字段实际输出该 listening socket 的全连接队列的最大容量,其值不应该为 0。

3. 解决手段 / Resolution

3.1 临时解决方案 / Workaround

暂无

3.2 根本解决方案 / Final Solution

升级内核版本,将内核版本升级到  kernel-4.19.43-13.1.al7.x86_64及之后版本。

4. 根因分析 / Root Cause

ss -lnt 命令输出的 Send-Q 字段描述 listening TCP socket 全连接队列的最大容量。

用户态 network 相关的工具套件有 net-tools 与 iproute2 两种,其中 net-tools 已经自 2001 年停止维护,而取代 net-tools 的则是 iproute2,而 ss 正是 iproute2 套件的一部分,net-tools 中与 ss 实现类似功能的则是 netstat。

  • netstat 是通过 /proc/net/tcp 获取 TCP socket 的相关统计信息;
  • ss 默认使用 socket 接口与 tcp_diag 内核模块通讯获取TCP socket 的相关统计信息,当内核不支持  tcp_diag 内核模块时,会回退到 /proc/net/tcp 模式。

由于kernel-4.19.43-13.al7.x86_64 及之前版本未集成 tcp_diag 模块,因而 ss 回退/proc/net/tcp 模式,而/proc/net/tcp 接口目前已经 deprecated,该接口输出的 listening TCP socket 的 tx_queue 字段均为0,从而导致 ss -lnt 输出的 Send-Q 字段也为 0。

This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
Note that these interfaces are deprecated in favor of tcp_diag.

以上摘自 Documentation/networking/proc_net_tcp.txt 

因而在新版本内核中打开 tcp_diag 支持,之后ss -lnt 命令即可输出正确值。

CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_INET_UDP_DIAG=m

5. 分析步骤 / Diagnostic Steps

5.1 Send-Q 的含义

在 Linux 下,对于 listening TCP socket,Send-Q 字段应该描述该 socket 全连接队列的最大容量。

listening TCP socket 的全连接队列的最大容量为 min(somaxconn, backlog),其中

  • backlog 即为用户调用 listen() syscall 时传入的 backlog 参数;
  • somaxconn 为系统参数,描述 listen() syscall 时传入的 backlog 参数的最大值,其默认值为128,用户可以通过 /proc/sys/net/core/somaxconn 设置该参数。

因而 ss -lnt 命令输出的 Send-Q 字段不应该为 0。

5.2 ss 处理逻辑

ss 工具可以从两种途径获取 socket 的状态

  1. 传统的方式是通过 /proc/net/tcp , /proc/net/tcp 输出的 tx_queue 字段来自 (tp->write_seq - tp->snd_una),目前从测试结果来看 /proc/net/tcp 输出的 listening socket 的 tx_queue 字段总是0。
  2. 新的方式是通过 tcp_diag 模块,tcp_diag 模块依赖于 netlink 模块,用户态通过创建一个 AF_NETLINK 类型的 socket 与内核进行交互,获取 socket 的统计信息,tcp_diag 模块返回的 listening socket 的 tx_queue 字段即为 sk->sk_max_ack_backlog ,即全连接队列的最大容量。

ss 会首先尝试方式2获取 socket 的统计信息,若系统不支持 tcp_diag 则回退到传统的方式1。

kernel-4.19.43-13.al7.x86_64 及之前版本没有编译 tcp_diag 模块,因而 ss 回退解析 /proc/net/tcp,这个时候 listening tcp socket 输出的 Send-Q 字段就都是0。

 /proc/net/tcp接口已经被标记为 deprecated,因而需要在新版本内核中打开 tcp_diag 支持。

CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_INET_UDP_DIAG=m

6. 外部链接 / Reference Links

N/A

版权声明:本文中所有内容均属于阿里云开发者社区所有,任何媒体、网站或个人未经阿里云开发者社区协议授权不得转载、链接、转贴或以其他方式复制发布/发表。申请授权请邮件developerteam@list.alibaba-inc.com,已获得阿里云开发者社区协议授权的媒体、网站,在转载使用时必须注明"稿件来源:阿里云开发者社区,原文作者姓名",违者本社区将依法追究责任。 如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:developer2020@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章