问题描述
在使用国产化弹性裸金属(包括鲲鹏、海光)的过程中,经常会遇到iperf等网络应用打流性能低的问题。
原因描述
国产化弹性裸金属(包括鲲鹏、海光)CPU主频偏低,单个cpu处理性能没有主频更高的intel x86服务器强。另外,处理器其他方面存在差异,经常出现cpu负载不均衡,部分cpu的负载过重,成为性能的瓶颈。
解决方案
优化配置一下发包和收包相关的配置,使得收发包的负载均衡的更合理一些,尤其接收负载的中断、软中断能均衡到多个cpu上,避免少部分cpu负载重处理不过来,引起性能下降。
下面是配置的内容
1.提高irqbalance服务执行均衡的频率
提高执行的频率到每秒钟一次,能更加及时的把中断过多的cpu上的中断均衡到其他空闲的cpu上去,提高数据包处理性能。
去掉下面参数前面的注释,并添加"-t 1"参数,重启服务加载配置
# vim /etc/sysconfig/irqbalance
IRQBALANCE_ARGS="-t 1"
# systemctl restart irqbalance
2.配置rps和rfs
能够均衡软中断负载,避免软中断负载过于集中到少量cpu上,同时会保证同一条流的数据包分发给同一个cpu处理、网络应用和软中断使用的cpu,避免跨cpu引起的性能下降。
编辑脚本rps-rfs.sh
#!/bin/bash
# FileName: rps-rfs.sh
rps_flow_cnt=4096
rps_start()
{
total_flow_entries=0
# Get all virtio net interfaces
net_interface=`ls /sys/class/net/ -l |grep pci | awk '{print $9}' | tr ":\n" " "`
for em in ${net_interface[@]}
do
# Get current interface's rx queue number
rq_count=`ls /sys/class/net/$em/queues/rx-* -d | wc -l`
for ((i=0; i< $rq_count; i++))
do
echo $rps_flow_cnt > /sys/class/net/$em/queues/rx-$i/rps_flow_cnt
total_flow_entries=$(($total_flow_entries+$rps_flow_cnt))
done
flag=0
while [ -f /sys/class/net/$em/queues/rx-$flag/rps_cpus ]
do
# Set current rps_cpus to 0xffff...
echo `cat /sys/class/net/$em/queues/rx-$flag/rps_cpus | sed 's/0/f/g'` > \
/sys/class/net/$em/queues/rx-$flag/rps_cpus
flag=$(($flag+1))
done
done
echo $total_flow_entries > /proc/sys/net/core/rps_sock_flow_entries
sysctl -p
}
rps_stop() {
net_interface=`ls /sys/class/net/ -l |grep pci | awk '{print $9}' | tr ":\n" " "`
for em in ${net_interface[@]}
do
rq_count=`ls /sys/class/net/$em/queues/rx-* -d | wc -l`
for ((i=0; i< $rq_count; i++))
do
echo 0 > /sys/class/net/$em/queues/rx-$i/rps_flow_cnt
done
flag=0
while [ -f /sys/class/net/$em/queues/rx-$flag/rps_cpus ]
do
echo 0 > /sys/class/net/$em/queues/rx-$flag/rps_cpus
flag=$(($flag+1))
done
done
echo 0 > /proc/sys/net/core/rps_sock_flow_entries
sysctl -p
}
rps_status() {
ni_list=`ls /sys/class/net/ -l |grep pci | awk '{print $9}' | tr ":\n" " "`
for n in $ni_list
do
rx_queues=`ls /sys/class/net/$n/queues/ | grep "rx-[0-9]"`
for q in $rx_queues
do
# Get current interface rps info
rps_cpus=`cat /sys/class/net/$n/queues/$q/rps_cpus`
rps_flow_cnt=`cat /sys/class/net/$n/queues/$q/rps_flow_cnt`
echo "[$n]" $q "--> rps_cpus =" $rps_cpus ", rps_flow_cnt =" $rps_flow_cnt
done
done
rps_sock_flow_entries=`cat /proc/sys/net/core/rps_sock_flow_entries`
echo "rps_sock_flow_entries =" $rps_sock_flow_entries
}
case "$1" in
start)
echo -n "Starting $DESC: "
rps_start
rps_status
;;
stop)
rps_stop
rps_status
;;
restart|reload|force-reload)
rps_stop
rps_start
;;
status)
rps_status
;;
*)
echo "Usage: $0 [start|stop|status]"
;;
esac
exit 0
脚本放到系统可执行目录下,并配置到开机启动
# cp rps-rfs.sh /usr/bin/
# chmod +x /usr/bin/rps-rfs.sh
# echo "rps-rfs.sh start" >> /etc/rc.local
# chmod +x /etc/rc.local
修改热添加设备调用的udev脚本
# vim /usr/local/sbin/generate-interface-config.sh
...
generate_ifcfg() {
...
/usr/bin/rps-rfs.sh start
}
备注:
rps开启后所有软中断负载会均衡到所有cpu上,在网卡满负载打流的情况下会偶现ping包延时偏大(3-4ms)的情况。rps默认开启,有助于提高netperf或iperf等网络应用的整体带宽性能,对个别的ping的icmp包的延时增大这一点,可以忽略。
3.提高网络NAPI收包的budget
能够提高单次NAPI轮询收包的数目,避免一次中断触发的轮询接收的数据包过少,引起收到的数据包在软件缓存中堆积,导致性能下降。
在下面文件末尾追加一行,执行sysctl -p对当前系统生效
# vim /etc/sysctl.conf
...
net.core.netdev_budget=600
# sysctl -p
4.增加传输层缓存大小
在下面文件末尾追加下面内容,执行sysctl -p对当前系统生效
# vim /etc/sysctl.conf
...
net.core.rmem_max=16777216
net.core.rmem_default=16777216
net.core.wmem_max=16777216
net.core.wmem_default=16777216
net.ipv4.tcp_rmem=409600 1638400 419430400
net.ipv4.tcp_wmem=409600 1638400 419430400
net.ipv4.tcp_mem=617474700 823299700 1234949400
net.ipv4.udp_mem=597916800 797222700 11958336
# sysctl -p
5.关闭xps
避免将同一条流的数据包分散到不同cpu发送,引起的发送性能下降。
编辑脚本xps-disable.sh
#!/bin/bash
# FileName: xps-disable.sh
xps_disable()
{
# Get all virtio net interfaces
net_interface=`ls /sys/class/net/ -l |grep pci | awk '{print $9}' | tr ":\n" " "`
for em in ${net_interface[@]}
do
# Get current interface's tx queue number
tq_count=`ls /sys/class/net/$em/queues/tx-* -d | wc -l`
# Disable each tx queue xps
for ((i=0; i< $tq_count; i++))
do
echo 0 > /sys/class/net/$em/queues/tx-$i/xps_cpus
done
done
sysctl -p
}
xps_status() {
ni_list=`ls /sys/class/net/ -l |grep pci | awk '{print $9}' | tr ":\n" " "`
for n in $ni_list
do
tx_queues=`ls /sys/class/net/$n/queues/ | grep "tx-[0-9]"`
for q in $tx_queues
do
xps_cpus=`cat /sys/class/net/$n/queues/$q/xps_cpus`
echo "[$n]" $q "--> xps_cpus =" $xps_cpus
done
done
}
case "$1" in
disable)
xps_disable
xps_status
;;
status)
xps_status
;;
*)
echo "Usage: $0 [disable|status]"
;;
esac
exit 0
脚本放到系统可执行目录下,并配置到开机启动
# cp xps-disable.sh /usr/bin/
# chmod +x /usr/bin/xps-disable.sh
# echo "xps-disable.sh disable" >> /etc/rc.local
# chmod +x /etc/rc.local
修改热添加设备调用的udev脚本
# vim /usr/local/sbin/generate-interface-config.sh
...
generate_ifcfg() {
...
/usr/bin/xps-disable.sh disable
}