简单聊聊国庆吃的屎吧
首先明确下需求,我们要监控哪几个指标
1. RTO:TCP 连接的 RTO ,TCP 的超时重传的阈值,具体可以参见[RFC 0793](https://tools.ietf.org/html/rfc793) 和 [RFC 6298](https://tools.ietf.org/html/rfc6298)
2. 发送队列和接收队列长度
3. TCP 慢启动等指标
而且一个很核心的需求还是在于说,我们需要以 进程 为粒度去做 Metric 的 Group By,细化下来的可以有这样的效果
1. 单个进程的所有连接平均的 RTO 等指标
2. 单个进程Source-Target连接的 RTO 等指标
这个需求看起来可能会很无从下手,但是内核实际上是已经暴露出 metric 来供 Agent 采集了的
1. 对于 IPv4 连接,内核将 Metric 输出到
2. 对于 IPv6 连接,内核将 Metric 输出到
不过这里要注意的是,官方已经不推荐利用
在目前输出的 metrics 中,已经包含了一些关键的指标
1. 连接状态
2. 本地端口,地址
3. 远程端口,地址
4. 接收队列长度
5. 发送队列长度
6. 慢启动阈值
7. RTO 值
8. 连接所属的 socket 的 inode id
9. uid
10. delay ack 软时钟
具体可以参见 [proc_net_tcp.txt](https://github.com/torvalds/linux/blob/v4.10/Documentation/networking/proc_net_tcp.txt)
所以根据目前的一些指标,我们通过 inode→process 这一样一个路径便可以实现根据进程为粒度来对内核输出的 metric 进行二次聚合
但是这样做的弊端也很明显
1. 内核直接提供的 metric 信息还是太少,一些关于 RTT,SRTT 这样的指标还是没法获取,也没法获取 SACK 等一些特定事件(虽然走 netlink+tcp_diag) 能获取到一些信息,但是还是相对有限
2. 根据内核输出的 metric 无论是读文件,还是 netlink 轮询,都存在的问题是实时性和精度的问题,换句话说,我们在不考虑精度的情况下可以去做这方面的尝试
3. 如果是读文件,因为全局同一个 network namespaces 下都会写同一个文件,如果我们要强行去通过 [inotify](https://man7.org/linux/man-pages/man7/inotify.7.html) 来监听文件变化来做实时处理得话,首先能否实时处理还是一个问题,其次 inotify 给整个系统带来的开销还是不小的(在频繁变动的情况下)
所以如果有高精度的监控需求,可能还是优先考虑需要在协议层做一些手脚,在有包传输/连接变动的时候,触发特定的事件回调来做
目前一些能监控进程级别连接状态的工具,如 [nethogs](https://github.com/raboof/nethogs) 是依赖 [libpcap](https://github.com/the-tcpdump-group/libpcap)(这货也是 tcpdump 的核心)来根据包传输,连接建立等事件发生地时候触发特定的处理逻辑。而 libpcap 是基于 BPF (应该是没扩展之前的 cBPF)来在内核中打点做协议栈监控
所以考虑后续其余的一些自定义的监控的话,估计还是会考虑基于 eBPF 来做。不过估计不会像 Cilium 那种直接做一套全家桶。可能更类似于头条落地的 Sysprobe 那种专注于系统监控的东西。
首先明确下需求,我们要监控哪几个指标
1. RTO:TCP 连接的 RTO ,TCP 的超时重传的阈值,具体可以参见[RFC 0793](https://tools.ietf.org/html/rfc793) 和 [RFC 6298](https://tools.ietf.org/html/rfc6298)
2. 发送队列和接收队列长度
3. TCP 慢启动等指标
而且一个很核心的需求还是在于说,我们需要以 进程 为粒度去做 Metric 的 Group By,细化下来的可以有这样的效果
1. 单个进程的所有连接平均的 RTO 等指标
2. 单个进程Source-Target连接的 RTO 等指标
这个需求看起来可能会很无从下手,但是内核实际上是已经暴露出 metric 来供 Agent 采集了的
1. 对于 IPv4 连接,内核将 Metric 输出到
/proc/net/tcp2. 对于 IPv6 连接,内核将 Metric 输出到
/proc/net/tcp6不过这里要注意的是,官方已经不推荐利用
/proc/net/tcp 来获取连接级别的 metrics ,建议使用 [netlink](https://man7.org/linux/man-pages/man7/netlink.7.html) 来获取对应连接的 metrics在目前输出的 metrics 中,已经包含了一些关键的指标
1. 连接状态
2. 本地端口,地址
3. 远程端口,地址
4. 接收队列长度
5. 发送队列长度
6. 慢启动阈值
7. RTO 值
8. 连接所属的 socket 的 inode id
9. uid
10. delay ack 软时钟
具体可以参见 [proc_net_tcp.txt](https://github.com/torvalds/linux/blob/v4.10/Documentation/networking/proc_net_tcp.txt)
所以根据目前的一些指标,我们通过 inode→process 这一样一个路径便可以实现根据进程为粒度来对内核输出的 metric 进行二次聚合
但是这样做的弊端也很明显
1. 内核直接提供的 metric 信息还是太少,一些关于 RTT,SRTT 这样的指标还是没法获取,也没法获取 SACK 等一些特定事件(虽然走 netlink+tcp_diag) 能获取到一些信息,但是还是相对有限
2. 根据内核输出的 metric 无论是读文件,还是 netlink 轮询,都存在的问题是实时性和精度的问题,换句话说,我们在不考虑精度的情况下可以去做这方面的尝试
3. 如果是读文件,因为全局同一个 network namespaces 下都会写同一个文件,如果我们要强行去通过 [inotify](https://man7.org/linux/man-pages/man7/inotify.7.html) 来监听文件变化来做实时处理得话,首先能否实时处理还是一个问题,其次 inotify 给整个系统带来的开销还是不小的(在频繁变动的情况下)
所以如果有高精度的监控需求,可能还是优先考虑需要在协议层做一些手脚,在有包传输/连接变动的时候,触发特定的事件回调来做
目前一些能监控进程级别连接状态的工具,如 [nethogs](https://github.com/raboof/nethogs) 是依赖 [libpcap](https://github.com/the-tcpdump-group/libpcap)(这货也是 tcpdump 的核心)来根据包传输,连接建立等事件发生地时候触发特定的处理逻辑。而 libpcap 是基于 BPF (应该是没扩展之前的 cBPF)来在内核中打点做协议栈监控
所以考虑后续其余的一些自定义的监控的话,估计还是会考虑基于 eBPF 来做。不过估计不会像 Cilium 那种直接做一套全家桶。可能更类似于头条落地的 Sysprobe 那种专注于系统监控的东西。