如果使用CentOS 等 Linux操作系统、X86服务器作为软路由,网络吞吐设置是需要进行一些必需的优化设置,因为系统的默认设置并不是为了这种用途而设计。
笔者:国际认证信息系统审计师、软考系统分析师
本文基于CentOS 7,最终实现的效果是终端数量高峰在350台左右,并发连接数14000条,路由能力仅受限于出口带宽,内网路由无丢包。暂未有条件试验更多的终端数量。
相关设置编写为系统启动后的初始化脚本,通过/etc/rc.d/rc.local来调用。需要说一下的是CentOS 7中,rc.local是通过systemd,作为一个一次性运行对的服务来调用的。因此,需要通过:
# systemctl enable rc-local
# chmod +x /etc/rc.d/rc.local
去启用。
下面介绍优化设置。
1. 常量定义
定义所有的网络界面,比如em1 em2是主板上的端口,而p1p1~p1p4是附加的4端口网卡
INTERFACES="lo em1 em2 p1p1 p1p2 p1p3 p1p4"
定义并发连接数设置。
CONNTRACK 跟踪并且记录连接状态。Linux 核心对网络栈的每一个数据包均通过记录连接项去确定数据包所归属的数据流。
CONNTRACK_MAX="262144"
HASHSIZE="65536"
2. TCP/IP基本设置
这些设置也可能已经是系统的默认设置。重复设置并无问题,反而是确保会被设置。
启用IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
明确地禁止ECN
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
防范SYN Flood攻击
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
某些路由器违反了RFC1122定义,会对ICMP广播帧发送虚假的响应。此类违反情况正常情况下会被作为内核警告而记录下来。通过设置为1(一般是默认值),内核就不会进行记录,从而避免日志文件泛滥。
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
调整ARP超时时间
echo 300 > /proc/sys/net/ipv4/neigh/default/base_reachable_time
echo 600 > /proc/sys/net/ipv4/neigh/default/gc_stale_time
扩大ARP表。存在于ARP高速缓存中的最少层数,如果少于这个数,垃圾收集器将不会运行。缺省值是128。
echo 1024 > /proc/sys/net/ipv4/neigh/default/gc_thresh1
保存在 ARP 高速缓存中的最多的记录软限制。垃圾收集器在开始收集前,允许记录数超过这个数字 5 秒。缺省值是 512。
echo 2048 > /proc/sys/net/ipv4/neigh/default/gc_thresh2
保存在 ARP 高速缓存中的最多记录的硬限制,一旦高速缓存中的数目高于此,垃圾收集器将马上运行。缺省值是1024。
echo 4096 > /proc/sys/net/ipv4/neigh/default/gc_thresh3
设置TCP连接超时。 默认值600秒,太长了。
echo 180 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
echo 180 > /proc/sys/net/netfilter/nf_conntrack_generic_timeout
扩充接收队列
echo 4096 > /proc/sys/net/core/netdev_max_backlog
echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 2048 > /proc/sys/net/core/somaxconn
扩充缓冲区
echo 16777216 > /proc/sys/net/core/rmem_max
echo 16777216 > /proc/sys/net/core/wmem_max
echo "4096 87380 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 65536 16777216" > /proc/sys/net/ipv4/tcp_wmem
3. 增加并发连接处理能力
修改ip_conntrack_max和hashsize的值。
echo $HASHSIZE > /sys/module/nf_conntrack/parameters/hashsize
echo $CONNTRACK_MAX > /proc/sys/net/nf_conntrack_max
以上2句其实可以被/etc/modprobe.d/nf_conntrack.conf的配置取代
要计算Conntrack模块需要占用的内存数量,可以按如下的方法:
size_of_mem_used_by_conntrack = CONNTRACK_MAX * sizeof(struct ip_conntrack) + HASHSIZE * sizeof(struct list_head)
但是,sizeof(struct ip_conntrack) 会因为内核版本、系统架构、编译设置等等因素而不同。如果要准确获得这个值,需要观察内核日志信息中,ip_conntrack初始化时的信息。比如,对于CentOS 5.2 64位版本,sizeof(struct ip_conntrack) 是304字节。然后,sizeof(struct list_head) = 2 * 指针字节数,如果是64位系统,指针占8个字节。因此,conntrack所使用的内存 = CONNTRACK_MAX * 304 + HASHSIZE * 8 (字节),代入本文例子:262144和65536,计算得到即 80216064 字节,76.5M内存。
如果定义的数量太大,比如CONNTRACK_MAX=1048576,会导致操作系统使用vmalloc来分配内存。而vmalloc分配的内存不是核心内存,可能会产生内存交换、物理地址不连续、强制对齐到内存页等问题。从而影响性能。
本文不讨论Linux核心对内存的分配使用机制,有兴趣可以参考:
https://www.kernel.org/doc/html/latest/vm/index.html
https://hammertux.github.io/slab-allocator
4. 对网络界面设置
禁止所有网络界面的spoofing,优化网卡发送接收队列长度。
for x in ${INTERFACES}
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
ethtool -G ${x} rx 2047 tx 511
ip link set dev ${x} txqueuelen 2047
done
或者可以进一步考虑,把这个脚本调整为通过 ethtool -g em1 这样的命令获取可以设置的最大值(即命令参数中的2047、511等值)去设置。不过一般情况下,手工获取一次然后修改设置到这个脚本,也就足够了。
最后汇总一下无注释脚本如下:
#!/bin/sh
INTERFACES="lo em1 em2 p1p1 p1p2 p1p3 p1p4"
CONNTRACK_MAX="262144"
HASHSIZE="65536"
echo 1 > /proc/sys/net/ipv4/ip_forward
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 300 > /proc/sys/net/ipv4/neigh/default/base_reachable_time
echo 600 > /proc/sys/net/ipv4/neigh/default/gc_stale_time
echo 1024 > /proc/sys/net/ipv4/neigh/default/gc_thresh1
echo 2048 > /proc/sys/net/ipv4/neigh/default/gc_thresh2
echo 4096 > /proc/sys/net/ipv4/neigh/default/gc_thresh3
echo 180 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
echo 180 > /proc/sys/net/netfilter/nf_conntrack_generic_timeout
echo 4096 > /proc/sys/net/core/netdev_max_backlog
echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 2048 > /proc/sys/net/core/somaxconn
echo 16777216 > /proc/sys/net/core/rmem_max
echo 16777216 > /proc/sys/net/core/wmem_max
echo "4096 87380 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 65536 16777216" > /proc/sys/net/ipv4/tcp_wmem
echo $HASHSIZE > /sys/module/nf_conntrack/parameters/hashsize
echo $CONNTRACK_MAX > /proc/sys/net/nf_conntrack_max
for x in ${INTERFACES}
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
ethtool -G ${x} rx 2047 tx 511
ip link set dev ${x} txqueuelen 2047
done
带注释脚本如下:
#!/bin/sh
# 1. 常量定义
# 定义所有的网络界面,比如em1 em2是主板上的端口,而p1p1~p1p4是附加的4端口网卡
INTERFACES="lo em1 em2 p1p1 p1p2 p1p3 p1p4"
# 定义并发连接数设置。
# CONNTRACK 跟踪并且记录连接状态。Linux 核心对网络栈的每一个数据包均通过记录连接项去确定数据包所归属的数据流。
CONNTRACK_MAX="262144"
HASHSIZE="65536"
# 2. TCP/IP基本设置
# 这些设置也可能已经是系统的默认设置。重复设置并无问题,反而是确保会被设置。
# 启用IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 显式禁止ECN
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
# 防范SYN Flood攻击
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
# 某些路由器违反了RFC1122定义,会对ICMP广播帧发送虚假的响应。
# 此类违反情况正常情况下会被作为内核警告而记录下来。
# 通过设置为1(一般是默认值),内核就不会进行记录,从而避免日志文件泛滥。
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
# 调整ARP超时时间
echo 300 > /proc/sys/net/ipv4/neigh/default/base_reachable_time
echo 600 > /proc/sys/net/ipv4/neigh/default/gc_stale_time
# 扩大ARP表。这个是第二层的事情。
# 存在于ARP高速缓存中的最少层数,如果少于这个数,垃圾收集器将不会运行。缺省值是128。
echo 1024 > /proc/sys/net/ipv4/neigh/default/gc_thresh1
# 保存在 ARP 高速缓存中的最多的记录软限制。垃圾收集器在开始收集前,允许记录数超过这个数字 5 秒。缺省值是 512。
echo 2048 > /proc/sys/net/ipv4/neigh/default/gc_thresh2
# 保存在 ARP 高速缓存中的最多记录的硬限制,一旦高速缓存中的数目高于此,垃圾收集器将马上运行。缺省值是1024。
echo 4096 > /proc/sys/net/ipv4/neigh/default/gc_thresh3
# 设置TCP连接超时。
echo 180 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
# 默认值600秒,太长
echo 180 > /proc/sys/net/netfilter/nf_conntrack_generic_timeout
# 扩充接收队列
echo 4096 > /proc/sys/net/core/netdev_max_backlog
echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 2048 > /proc/sys/net/core/somaxconn
# 扩充缓冲区
echo 16777216 > /proc/sys/net/core/rmem_max
echo 16777216 > /proc/sys/net/core/wmem_max
echo "4096 87380 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 65536 16777216" > /proc/sys/net/ipv4/tcp_wmem
# 3. 增加并发连接处理能力
# 修改ip_conntrack_max和hashsize的值。
echo $HASHSIZE > /sys/module/nf_conntrack/parameters/hashsize
echo $CONNTRACK_MAX > /proc/sys/net/nf_conntrack_max
# 以上2句其实可以被/etc/modprobe.d/nf_conntrack.conf的配置取代
# 注意:conntrack所使用的内存(字节数)size_of_mem_used_by_conntrack = CONNTRACK_MAX * sizeof(struct ip_conntrack) + HASHSIZE * sizeof(struct list_head)
# 但是,sizeof(struct ip_conntrack) 会因为内核版本、系统架构、编译设置等等因素而不同。
# 如果要准确获得这个值,需要观察内核日志信息中,ip_conntrack初始化时的信息。
# 比如,对于CentOS 5.2 64位版本,sizeof(struct ip_conntrack) 是304字节。
# 然后,sizeof(struct list_head) = 2 * 指针字节数,如果是64位系统,指针占8个字节
# 因此,conntrack所使用的内存 = CONNTRACK_MAX * 304 + HASHSIZE * 8 (字节).
# 按本例子的262144和65536,即 80216064 字节,76.5M内存。
# 如果定义的数量太大,比如1048576,会导致操作系统使用vmalloc来分配内存。而vmalloc分配的内存不是核心内存,可能会产生内存交换、物理地址不连续、强制对齐到内存页等问题。从而影响性能。
# 本文不讨论Linux核心对内存的分配使用机制,有兴趣可以参考:
# https://www.kernel.org/doc/html/latest/vm/index.html
# https://hammertux.github.io/slab-allocator
# 4. 对网络界面设置
for x in ${INTERFACES}
do
# 禁止所有网络界面的spoofing
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
# 优化网卡发送接收队列长度
# 可以进一步考虑,把这个脚本调整为通过 ethtool -g em1 这样的命令获取可以设置的最大值(即命令参数中的2047、511等值)去设置。不过一般情况下,手工获取一次然后修改设置到这个脚本,也就足够了。
ethtool -G ${x} rx 2047 tx 511
ip link set dev ${x} txqueuelen 2047
done
本站微信订阅号:
本页网址二维码: