‘壹’ 一文看懂linux 内核网络中 RPS/RFS 原理
Linux内核中的RPS/RFS原理解析
在理解Linux内核网络中RPS(Round Robin Packet Scheling)和RFS(Round Robin Flow Scheling)原理之前,需先认识到基于简单中断负载均衡(如系统自带的irqbalance进程)可能产生的问题。这些负载均衡器识别的是数据包,而不是数据包的元组信息,无法识别网络流。因此,多处理器系统中,数据包需要被分配给特征相似的CPU进行处理,以降低CPU硬件高速缓存的刷新频率。
在多处理器系统中,每个处理器拥有单独的硬件高速缓存。当其中一个CPU修改了自己的硬件高速缓存,它必须通知其他CPU更新缓存,以保证缓存一致性。这样,CPU间的数据一致性问题需要解决,以避免数据乱序导致的重传问题。当Linux主机作为路由器时,进入系统的一个TCP包的不同分段如果被不同的CPU处理并向一个网卡转发,同步问题将变得复杂,这与一个CPU串行处理相比,效果更差。
RPS/RFS旨在解决上述问题,需要解决三个关键问题:数据包如何更高效地分配给CPU、TCP/IP包分段重组同步问题、以及如何确保数据流处理的一致性。
在Linux底层,数据结构隐藏了许多机密信息,包括面向对象的设计。以下是对关键数据结构的解析:
- 网卡的硬件接收队列(netdev_rx_queue):存放解析结果,其中cpus数组记录参与报文分发处理的CPU数组,len成员表示cpus数组的长度。
- CPU负载表(rps_map):存放解析结果的容器,用于管理分配给CPU的数据包。
- 设备流表(rps_dev_flow_table):由mask成员控制流表项的数量,通过配置文件指定。
- 全局数据流表(rps_sock_flow_table):包含处理数据流的CPU信息,通过调用recvmsg、sendmsg等函数更新。
RPS工作流程如下:将数据包加入其他CPU的接收队列,这些CPU在软中断中执行process_backlog,接收队列中的所有数据包并调用__netif_receive_skb进行后续操作。
Linux通过配置文件指定参与报文分发处理的CPU列表,路径为/sys/class/net/(dev)/queues/rx-(n)/rps_cpus。内核根据配置生成用于处理报文的CPU列表,实现基于报文哈希值的负载均衡。RPS不关注处理该流中报文的应用程序所在CPU,但有NAPI接口的驱动中,上半部主要将设备加入到CPU私有数据待轮询列表,下半部从网卡缓冲区获取报文。
函数get_rps_cpu在netif_rcv_skb调用,获取目标CPU,将其加入到CPU私有数据对象的input_pkt_queue队列中。数据对象中的backlog成员类型为struct napi_struct,在enqueue_to_backlog函数中,将backlog加入待轮询列表,触发软中断处理,最后从input_pkt_queue队列中取出报文并上报协议栈。
RFS作为RPS的改进,在RPS的基础上,将同一流的数据包分发给同一个CPU核,但有可能导致处理该数据流的应用程序CPU核和实际执行处理的CPU核不同,导致缓存不命中问题。RFS通过指派应用程序所在CPU在内核态处理报文,增加缓存命中率,主要差别在于选择分发处理报文的目标CPU。
RFS实现通过设备流表和全局socket流表的记录比较,判断处理报文的CPU核是否一致。如果当前CPU表对应表项未设置或CPU核离线,使用期望CPU表对应表项映射的CPU核。如果当前和期望CPU核不同,RFS会使用设备流表和全局流表设置的CPU核。未设置时,使用RPS策略中的CPU流表或返回无效CPU_index。
配置方法:RPS和RFS在Linux kernel 2.6.35及以上版本中默认关闭,可通过/sys/class/net/(dev)/queues/rx-(n)/rps_cpus设置RPS接收队列和CPU列表,/sys/class/net/(dev)/queues/rx-(n)/rps_flow_cnt设置设备流表数量,/proc/sys/net/core/rps_sock_flow_entries设置全局数据流表数量。
‘贰’ Linux 网络调优:内核网络栈参数篇
Linux 网络优化:内核网络参数详解
在 Linux 网络优化中,了解并合理调整内核参数是关键。本文将从网络架构入手,详细解读一些常用的内核网络参数及其作用、注意事项。
Linux 网络架构
Linux 网络优化是高性能服务器中的重要部分,本文主要聚焦于协议栈的配置。关键参数涉及网络帧处理、缓存管理、队列控制等。
关键参数详解
1. **/proc/net/softnet_stat**:该文件记录内核网络状态,包括已处理帧数、丢包数、NAPI 中的预算或时间限制退出次数等。注意,描述中省略了 NAPI 的配置项和 CPU 分配问题。
2. **backlog 队列和缓存**:
- **net.ipv4.tcp_rmem** 和 **net.ipv4.tcp_wmem**:定义了收发缓冲区大小,参数分为最低、默认、最大值。建议根据可用内存动态调整,避免过大影响拥塞控制。
- **net.core.rmem** 和 **net.core.wmem**:为全局收发缓冲区参数,确保缓冲区大小适中,避免 bufferbloat 问题。
- **net.core.netdev_max_backlog**:网络设备接收缓冲队列长度,与中断频率共同影响收包速度和吞吐量。
- **net.ipv4.tcp_max_syn_backlog** 和 **net.ipv4.tcp_syncookies**:控制 SYN 请求队列长度和 SYN 包处理,对于高并发服务至关重要。
3. **TIME_WAIT 相关**:
- **TIME_WAIT**:原为避免连接混淆,持续时间固定为60秒,对于高 QPS 网络中可能影响连接建立。服务端使用 RST 关闭连接有助于缓解此问题。
- **net.ipv4.tcp_max_tw_buckets**:定义系统能同时保持的 TIME_WAIT socket 数量上限。
- **net.ipv4.tcp_tw_reuse** 和 **net.ipv4.tcp_tw_recycle**:与 TCP 时间戳相关,影响 TIME_WAIT socket 复用。4.12 内核后,此配置项被废弃。
4. **流控和拥塞控制**:
- **net.ipv4.tcp_congestion_control**:用于调整拥塞控制算法,bbr 算法适合长胖管道,但不适用于所有网络环境。
- **net.core.default_qdisc**:队列控制,选择适合终端用户或转发设备的 qdisc,如 fq、codel 等。
- **net.ipv4.tcp_window_scaling**:启用窗口扩展,允许在长延迟网络中实现更大窗口大小。
5. **TCP keepalive**:
- **net.ipv4.tcp_keepalive_time**、**net.ipv4.tcp_keepalive_intvl** 和 **net.ipv4.tcp_keepalive_probes**:配置 keepalive 功能,避免长时间空闲的连接干扰网络。
总结与建议
合理配置上述内核网络参数,结合具体应用场景和硬件配置,能显着优化网络性能。确保参数调整时充分考虑系统的负载平衡和资源使用效率,避免引入不必要的延迟和瓶颈。
‘叁’ Linux查看网卡队列信息指南linux查看网卡队列
Linux是一个爱好者和程式文件和性能的热门运行系统,因此,查看有关网卡的信息是一个很常见的任务。在Linux操作系统中可以使用各种指令来查看网卡队列信息。
要查看每个网卡队列的信息,可以使用ethtool来检查:
$ ethtool -l eth0
该指令将显示每个网卡队列的信息,包括队列ID,类型,数据流模式,等待模式,顺序模式,工作者队列数量和工作者队列每次事件最大数量。
此外,可以使用以下指令查看每个 NIC 队列的设置:
$ ethtool –g eth0
该指令显示每个网卡队列的突发和常见的参数,Sunyan Linux中的文件系统在不同的状态下提供不同的封装大小以满足具体的应用需要以及更高的突发性能。
此外,还可以使用以下指令查看每个网卡队列的”累计活动”或突发数据总量:
$ ethtool -S eth0
该指令将显示每个网卡队列的累计活动点数,如发送,接收,碎片,丢失碎片和重发比特率,One way用户保护系统采用时间和频宽控制以允许合理的网络资源分享,从而提高网络效率。可以使用它们来监控网络的性能,此外,还可以查看每个网卡队列的总装箱数量:
$ ethtool -c eth0
提供的讯息将包括总接收装箱数量,总发送装箱数量和每个工作者网卡队列装箱数量。
通过使用以上指令,Linux用户可以轻松查看网卡队列信息,用于控制网络流量和解决网络问题。这些指令非常容易学习,用于观测网络性能,并对其性能做出适当的调节。