服务器网卡大量并发时候,大家肯定遇到过cpu软中断不均衡情况,都压到cpu0上,其他核的cpu闲着没干活。

比如:lvs服务器,高并发的网站服务器,最容易遇到这种问题。


有2种解决方法:

如果网卡不支持多队列,2.6.21后网卡驱动才支持多队列

判断是否支持多队列

lspci -vvv  如果有MSI-X && Enable+ && TabSize > 1,则该网卡是多队列网卡,否则不支持。

cat  enable_rps.sh


其中ffff 是0000-1111 代表cpu个数
  1. #!/bin/bash  

  2. # Enable RPS (Receive Packet Steering)  

  3.       

  4. rfc=4096  

  5. cc=$(grep -c processor /proc/cpuinfo)  

  6. rsfe=$(echo $cc*$rfc | bc)  

  7. sysctl -w net.core.rps_sock_flow_entries=$rsfe  

  8. for fileRps in $(ls /sys/class/net/eth*/queues/rx-*/rps_cpus)  

  9. do

  10.     echo ffff > $fileRps  

  11. done

  12.       

  13. for fileRfc in $(ls /sys/class/net/eth*/queues/rx-*/rps_flow_cnt)  

  14. do

  15.     echo $rfc > $fileRfc  

  16. done

  17.       

  18. tail /sys/class/net/eth*/queues/rx-*/{rps_cpus,rps_flow_cnt}

2.如果网卡支持多队列
#!/bin/bash

# setting up irq affinity according to /proc/interrupts
# 2008-11-25 Robert Olsson
# 2009-02-19 updated by Jesse Brandeburg
#
# > Dave Miller:
# (To get consistent naming in /proc/interrups)
# I would suggest that people use something like:
#       char buf[IFNAMSIZ+6];
#
#       sprintf(buf, "%s-%s-%d",
#               netdev->name,
#               (RX_INTERRUPT ? "rx" : "tx"),
#               queue->index);
#
#  Assuming a device with two RX and TX queues.
#  This script will assign: 
#
#       eth0-rx-0  CPU0
#       eth0-rx-1  CPU1
#       eth0-tx-0  CPU0
#       eth0-tx-1  CPU1
#

set_affinity()
{
        if [ $VEC -ge 32 ]
        then
                MASK_FILL=""
                MASK_ZERO="00000000"
                let "IDX = $VEC / 32"
                for ((i=1; i<=$IDX;i++))
                do
                        MASK_FILL="${MASK_FILL},${MASK_ZERO}"
                done

                let "VEC -= 32 * $IDX"
                MASK_TMP=$((1<<$VEC))
                MASK=`printf "%X%s" $MASK_TMP $MASK_FILL`
        else
                MASK_TMP=$((1<<(`expr $VEC + $CORE`)))
                MASK=`printf "%X" $MASK_TMP`
        fi

    printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ
    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
}

if [ $# -ne 2 ] ; then
        echo "Description:"
        echo "    This script attempts to bind each queue of a multi-queue NIC"
        echo "    to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1"
        echo "usage:"
        echo "    $0 core eth0 [eth1 eth2 eth3]"
        exit
fi

CORE=$1

# check for irqbalance running
IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?`
if [ "$IRQBALANCE_ON" == "0" ] ; then
        echo " WARNING: irqbalance is running and will"
        echo "          likely override this script's affinitization."
        echo "          Please stop the irqbalance service and/or execute"
        echo "          'killall irqbalance'"
fi

#
# Set up the desired devices.
#
shift 1

for DEV in $*
do
  for DIR in rx tx TxRx
  do
     MAX=`grep $DEV-$DIR /proc/interrupts | wc -l`
     if [ "$MAX" == "0" ] ; then
       MAX=`egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l`
     fi
     if [ "$MAX" == "0" ] ; then
       echo no $DIR vectors found on $DEV
       continue
     fi
     for VEC in `seq 0 1 $MAX`
     do
        IRQ=`cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$"  | cut  -d:  -f1 | sed "s/ //g"`
        if [ -n  "$IRQ" ]; then
          set_affinity
        else
           IRQ=`cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$"  | cut  -d:  -f1 | sed "s/ //g"`
           if [ -n  "$IRQ" ]; then
             set_affinity
           fi
        fi
     done
  done
done



转载:https://blog.hackroad.com/operations-engineer/linux_server/6405.html