Обработка больших потоков трафика в Linux
В этой заметке я опишу методы увеличения производительности линуксового маршрутизатора. Для меня эта тема стала актуальна, когда проходящий сетевой трафик через один линуксовый маршрутизатор стал достаточно высоким (>150 Мбит/с, > 50 Kpps). Маршрутизатор помимо роутинга еще занимается шейпированием и выступает в качестве файрволла.
Для высоких нагрузок стоит использовать сетевые карты Intel, на базе чипсетов 82575/82576 (Gigabit), 82598/82599 (10 Gigabit), или им подобные. Их прелесть в том, что они создают восемь очередей обработки прерываний на один интерфейс – четыре на rx и четыре на tx (возможно технологии RPS/RFS, появившиеся в ядре 2.6.35 сделают то же самое и для обычных сетевых карт). Также эти чипы неплохо ускоряют обработку трафика на аппаратном уровне.
Для начала посмотрите содержимое
Еще одним весьма важным параметром является задержка между прерываниями. Посмотреть текущее значение можно при помощи
При подготовке в эксплуатацию сервера с Intel Xeon E5520 (8 ядер, каждое с HyperThreading) я выбрал такую схему распределения прерываний:
Для высоких нагрузок стоит использовать сетевые карты Intel, на базе чипсетов 82575/82576 (Gigabit), 82598/82599 (10 Gigabit), или им подобные. Их прелесть в том, что они создают восемь очередей обработки прерываний на один интерфейс – четыре на rx и четыре на tx (возможно технологии RPS/RFS, появившиеся в ядре 2.6.35 сделают то же самое и для обычных сетевых карт). Также эти чипы неплохо ускоряют обработку трафика на аппаратном уровне.
Для начала посмотрите содержимое
/proc/interrupts
, в этом файле можно увидеть что вызывает прерывания и какие ядра занимаются их обработкой.# cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 0: 53 1 9 336 IO-APIC-edge timer 1: 0 0 0 2 IO-APIC-edge i8042 7: 1 0 0 0 IO-APIC-edge 8: 0 0 0 75 IO-APIC-edge rtc0 9: 0 0 0 0 IO-APIC-fasteoi acpi 12: 0 0 0 4 IO-APIC-edge i8042 14: 0 0 0 127 IO-APIC-edge pata_amd 15: 0 0 0 0 IO-APIC-edge pata_amd 18: 150 1497 12301 473020 IO-APIC-fasteoi ioc0 21: 0 0 0 0 IO-APIC-fasteoi sata_nv 22: 0 0 15 2613 IO-APIC-fasteoi sata_nv, ohci_hcd:usb2 23: 0 0 0 2 IO-APIC-fasteoi sata_nv, ehci_hcd:usb1 45: 0 0 0 1 PCI-MSI-edge eth0 46: 138902469 21349 251748 4223124 PCI-MSI-edge eth0-rx-0 47: 137306753 19896 260291 4741413 PCI-MSI-edge eth0-rx-1 48: 2916 137767992 248035 4559088 PCI-MSI-edge eth0-rx-2 49: 2860 138565213 244363 4627970 PCI-MSI-edge eth0-rx-3 50: 2584 14822 118410604 3576451 PCI-MSI-edge eth0-tx-0 51: 2175 15115 118588846 3440065 PCI-MSI-edge eth0-tx-1 52: 2197 14343 166912 121908883 PCI-MSI-edge eth0-tx-2 53: 1976 13245 157108 120248855 PCI-MSI-edge eth0-tx-3 54: 0 0 0 1 PCI-MSI-edge eth1 55: 3127 19377 122741196 3641483 PCI-MSI-edge eth1-rx-0 56: 2581 18447 123601063 3865515 PCI-MSI-edge eth1-rx-1 57: 2470 17277 183535 126715932 PCI-MSI-edge eth1-rx-2 58: 2543 16913 173988 126962081 PCI-MSI-edge eth1-rx-3 59: 128433517 11953 148762 4230122 PCI-MSI-edge eth1-tx-0 60: 127590592 12028 142929 4160472 PCI-MSI-edge eth1-tx-1 61: 1713 129757168 136431 4134936 PCI-MSI-edge eth1-tx-2 62: 1854 126685399 122532 3785799 PCI-MSI-edge eth1-tx-3 NMI: 0 0 0 0 Non-maskable interrupts LOC: 418232812 425024243 572346635 662126626 Local timer interrupts SPU: 0 0 0 0 Spurious interrupts PMI: 0 0 0 0 Performance monitoring interrupts PND: 0 0 0 0 Performance pending work RES: 94005109 96169918 19305366 4460077 Rescheduling interrupts CAL: 49 34 39 29 Function call interrupts TLB: 66588 144427 131671 91212 TLB shootdowns TRM: 0 0 0 0 Thermal event interrupts THR: 0 0 0 0 Threshold APIC interrupts MCE: 0 0 0 0 Machine check exceptions MCP: 199 199 199 199 Machine check polls ERR: 1 MIS: 0В данном примере используются сетевые карты Intel 82576. Здесь видно, что сетевые прерывания распределены по ядрам равномерно. Однако, по умолчанию так не будет. Нужно раскидать прерывания по процессорам. Чтобы это сделать нужно выполнить команду echo N > /proc/irq/X/smp_affinity, где N это маска процессора (определяет какому процессору достанется прерывание), а X — номер прерывания, виден в первом столбце вывода /proc/interrupts. Чтобы определить маску процессора, нужно возвести 2 в степень cpu_N (номер процессора) и перевести в шестнадцатиричную систему. При помощи bc вычисляется так: echo «obase=16; $[2 ** $cpu_N]» | bc. В данном примере распределение прерываний было произведено следующим образом:
#CPU0 echo 1 > /proc/irq/45/smp_affinity echo 1 > /proc/irq/54/smp_affinity echo 1 > /proc/irq/46/smp_affinity echo 1 > /proc/irq/59/smp_affinity echo 1 > /proc/irq/47/smp_affinity echo 1 > /proc/irq/60/smp_affinity #CPU1 echo 2 > /proc/irq/48/smp_affinity echo 2 > /proc/irq/61/smp_affinity echo 2 > /proc/irq/49/smp_affinity echo 2 > /proc/irq/62/smp_affinity #CPU2 echo 4 > /proc/irq/50/smp_affinity echo 4 > /proc/irq/55/smp_affinity echo 4 > /proc/irq/51/smp_affinity echo 4 > /proc/irq/56/smp_affinity #CPU3 echo 8 > /proc/irq/52/smp_affinity echo 8 > /proc/irq/57/smp_affinity echo 8 > /proc/irq/53/smp_affinity echo 8 > /proc/irq/58/smp_affinityТакже, если маршрутизатор имеет два интерфейса, один на вход, другой на выход (классическая схема), то rx с одного интерфейса следует группировать с tx другого интерфейса на одном ядре процессора. Например, в данном случае прерывания 46 (eth0-rx-0) и 59 (eth1-tx-0) были определены на одно ядро.
Еще одним весьма важным параметром является задержка между прерываниями. Посмотреть текущее значение можно при помощи
ethtool -c ethN
, параметры rx-usecs и tx-usecs. Чем больше значение, тем выше задержка, но тем меньше нагрузка на процессор. Пробуйте уменьшать это значение в часы пик вплоть до ноля.При подготовке в эксплуатацию сервера с Intel Xeon E5520 (8 ядер, каждое с HyperThreading) я выбрал такую схему распределения прерываний:
#CPU6 echo 40 > /proc/irq/71/smp_affinity echo 40 > /proc/irq/84/smp_affinity #CPU7 echo 80 > /proc/irq/72/smp_affinity echo 80 > /proc/irq/85/smp_affinity #CPU8 echo 100 > /proc/irq/73/smp_affinity echo 100 > /proc/irq/86/smp_affinity #CPU9 echo 200 > /proc/irq/74/smp_affinity echo 200 > /proc/irq/87/smp_affinity #CPU10 echo 400 > /proc/irq/75/smp_affinity echo 400 > /proc/irq/80/smp_affinity #CPU11 echo 800 > /proc/irq/76/smp_affinity echo 800 > /proc/irq/81/smp_affinity #CPU12 echo 1000 > /proc/irq/77/smp_affinity echo 1000 > /proc/irq/82/smp_affinity #CPU13 echo 2000 > /proc/irq/78/smp_affinity echo 2000 > /proc/irq/83/smp_affinity #CPU14 echo 4000 > /proc/irq/70/smp_affinity #CPU15 echo 8000 > /proc/irq/79/smp_affinity
cat /proc/interrupts
с этого сервера без нагрузки можно посмотреть тут.
0 комментариев