NFsec Logo

Młotkiem w wiele wirtualnych rdzeni – Receive Packet Steering

18/10/2015 w Administracja Brak komentarzy.  (artykuł nr 488, ilość słów: 1099)

S

krótów takich jak: RPS, RFS, XPS nie trzeba przedstawiać chyba nikomu – jeśli tak to warto się z nimi dogłębnie zapoznać. Zostały one wdrożone w wersji jądra 2.6.35 – 2.6.38 przez Toma Herberta z teamu Google i są aplikacyjną implementacją RSS (ang. Receive-Side Scaling). Na dedykowanych serwerach fizycznych do natłoku ruchu sieciowego możemy wykorzystać sprzętowe wsparcie kart sieciowych i mechanizmy do rozładowywania kolejek. Niestety na serwerach wirtualnych (Xen, KVM) cała ta praca spada na przypisany do maszyny procesor(y).

Jeśli przyjrzymy się (watch -n1 cat /proc/softirqs) pracy serwerów umieszczonych na OpenStack lub EC2 zauważymy, że w wierszu NET_RX młotek pakietów uderza tylko w jedną kolumnę (CPU0), nawet jeśli posiadamy przypisane 4 wirtualne rdzenie.

agresor@node2:~$ cat /proc/softirqs
                    CPU0       CPU1       CPU2       CPU3
          HI:          0          0          0          0
       TIMER:  665670260  181208291  187377145  169255593
      NET_TX:      32705       4429       4131       3688
      NET_RX: 1648765575    8770165    8795127    8571483
       BLOCK:    3831691        710       1855        837
BLOCK_IOPOLL:          0          0          0          0
     TASKLET:          0          1          0          0
       SCHED:  101864310  105031918  103907650   96949346
     HRTIMER:     866486     227513     216502     208126
         RCU:  839666530  121126572  124599204  115223059

Szczególnie to widać kiedy maszyna posiada dużą utylizację sieciową – 3 rdzenie “śpią”, a czwarty pracuje za wszystkich – nie służy to wydajności sieciowej oraz opóźnieniom obsługi pakietów. Ponieważ używamy maszyny wirtualnej nie możemy wykorzystać wielu kolejek w celu podzielenia buforów karty sieciowej i przypisania ich do różnych rdzeni CPU. Ale możemy włączyć mechanizm RPS (ang. Receive Packet Steering) i rozładować przerwania na wszystkie dostępne wirtualne rdzenie. Wykonajmy prosty test. W 2 turach będziemy włączać stopniowo mechanizm RPS pomiędzy dwoma maszynami wyposażonymi w 4 vCPU. Pierwszy przebieg oczywiście został wykonany na standardowych ustawieniach:

root@node1:~# iperf -n 8192M -i 10 -c 10.10.10.2
------------------------------------------------------------
Client connecting to 10.10.10.2, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 10.10.10.1 port 59408 connected with 10.10.10.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  3.21 GBytes  2.75 Gbits/sec
[  3] 10.0-20.0 sec  3.51 GBytes  3.02 Gbits/sec
[  3]  0.0-23.5 sec  8.00 GBytes  2.92 Gbits/sec

root@node2:~# sar -n DEV 1 20
Average: IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s
Average:  eth0   8147.58   6737.86 353565.97    434.51
Average:    lo      0.00      0.00      0.00      0.00

Włączmy mechanizm RPS na serwerze node2, który jest “zalewany” pakietami przez maszynę node1:

echo ffff > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
sysctl -w net.core.rps_sock_flow_entries=32768

Ponawiamy test:

root@node1:~# iperf -n 8192M -i 10 -c 10.10.10.2
------------------------------------------------------------
Client connecting to 10.10.10.2, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 10.10.10.1 port 59409 connected with 10.10.10.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  4.04 GBytes  3.47 Gbits/sec
[  3]  0.0-20.0 sec  8.00 GBytes  3.44 Gbits/sec

root@node2:~# sar -n DEV 1 20
Average: IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   
Average:  eth0   9321.28   8726.44 405477.80    562.86
Average:    lo      0.00      0.00      0.00      0.00

Z porównania jasno widać, że ilość pakietów przychodzących wzrosła dla tej samej ilości danych o 1174 pck/s plus znacząco skoczyła przepustowość między serwerami (o 51911.83 kB/s). Z powodu, że node2 musi bardzo szybko odpowiadać na otrzymane pakiety i tym samym “zalewa” również node1 – włączmy również na pierwszym serwerze mechanizm RPS:

root@node1:~# iperf -n 8192M -i 10 -c 10.10.10.2
------------------------------------------------------------
Client connecting to 10.10.10.2, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 10.10.10.1 port 59415 connected with 10.10.10.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  3.64 GBytes  3.13 Gbits/sec
[  3]  0.0-19.8 sec  8.00 GBytes  3.48 Gbits/sec

root@node2:~# sar -n DEV 1 20
Average: IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s
Average:  eth0   9652.91   9395.14 418180.43    606.07
Average:    lo      0.00      0.00      0.00      0.00

Uzysk w porównaniu do poprzedniej wersji: 331.63 pck/s oraz 12702.63 kB/s. Dodatkowym “efektem” ubocznym tego zabiegu jest równe rozłożenie obciążenia systemu na obydwu serwerach przy serwowaniu dużego ruchu sieciowego. Testy zostały przeprowadzone na systemach Ubuntu 12.04 oraz jądrze 3.13.0-65-generic.

Więcej informacji: rps, rfs, xps, Improving network performance, RSS and RPS

Kategorie K a t e g o r i e : Administracja

Tagi T a g i : , , , , , , ,

Komentowanie tego wpisu jest zablokowane.