Linux-optimalisatie om 1.2 miljoen JSON-verzoeken per seconde te verwerken

Er is een gedetailleerde handleiding gepubliceerd over het afstemmen van de Linux-omgeving om maximale prestaties te bereiken bij het verwerken van HTTP-verzoeken. De voorgestelde methoden maakten het mogelijk om de prestaties van de JSON-processor op basis van de libreactor-bibliotheek in de Amazon EC2-omgeving (4 vCPU) te verhogen van 224 duizend API-verzoeken per seconde met standaardinstellingen van Amazon Linux 2 met kernel 4.14 naar 1.2 miljoen verzoeken per seconde. tweede na optimalisatie (een stijging van 436%), en leidde ook tot een vermindering van de vertragingen bij de verwerking van verzoeken met 79%. De voorgestelde methoden zijn niet specifiek voor libreactor en werken bij gebruik van andere http-servers, waaronder nginx, Actix, Netty en Node.js (libreactor werd in tests gebruikt omdat de daarop gebaseerde oplossing betere prestaties liet zien).

Linux-optimalisatie om 1.2 miljoen JSON-verzoeken per seconde te verwerken

Basisoptimalisaties:

  • Libreactor-code optimaliseren. De R18-optie uit de Techempower-kit werd als basis gebruikt, die werd verbeterd door code te verwijderen om het aantal gebruikte CPU-kernen te beperken (optimalisatie maakte het mogelijk het werk met 25-27%) te versnellen, assembleren in GCC met de “-O3” -opties (een stijging van 5-10%) en "-march-native" (5-10%), waarbij lees-/schrijfaanroepen worden vervangen door recv/send (5-10%) en de overhead wordt verminderd bij het gebruik van pthreads (2-3%) . De algehele prestatieverbetering na code-optimalisatie was 55% en de doorvoer steeg van 224k req/s naar 347k req/s.
  • Schakel de bescherming tegen kwetsbaarheden bij speculatieve uitvoering uit. Door de parameters “nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” te gebruiken bij het laden van de kernel konden de prestaties met 28% worden verhoogd, en de doorvoer nam toe van 347k req/s naar 446k req/s. Afzonderlijk was de toename ten opzichte van de parameter “nospectre_v1” (bescherming tegen Spectre v1 + SWAPGS) 1-2%, “nospectre_v2” (bescherming tegen Spectre v2) – 15-20%, “pti=off” (Spectre v3/Meltdown) – 6%, "mds=off tsx_async_abort=off" (MDS/Zombieload en TSX asynchroon afbreken) - 6%. De instellingen voor bescherming tegen L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass en SRBDS-aanvallen bleven ongewijzigd, wat geen invloed had op de prestaties omdat ze niet kruisten met de geteste configuratie (bijvoorbeeld specifiek voor KVM, geneste virtualisatie en andere CPU-modellen).
  • Het uitschakelen van auditing en mechanismen voor het blokkeren van systeemoproepen met behulp van de opdracht "auditctl -a never,task" en het opgeven van de optie "--security-opt seccomp=unconfined" bij het starten van de docker-container. De algehele prestatieverbetering bedroeg 11% en de doorvoer steeg van 446 vereist/s naar 495 vereist/s.
  • Schakel iptables/netfilter uit door de bijbehorende kernelmodules te verwijderen. Het idee om de firewall uit te schakelen, die niet werd gebruikt in een specifieke serveroplossing, werd ingegeven door profileringsresultaten, waaruit bleek dat de uitvoering van de functie nf_hook_slow 18% van de tijd in beslag nam. Opgemerkt wordt dat nftables efficiënter werkt dan iptables, maar Amazon Linux blijft iptables gebruiken. Na het uitschakelen van iptables bedroeg de prestatieverbetering 22% en nam de doorvoer toe van 495k req/s naar 603k req/s.
  • Verminderde migratie van handlers tussen verschillende CPU-kernen om de efficiëntie van het cachegebruik van de processor te verbeteren. De optimalisatie werd uitgevoerd zowel op het niveau van het binden van libreactor-processen aan CPU-kernen (CPU Pinning) als door het vastzetten van kernelnetwerkhandlers (Receive Side Scaling). Irqbalance is bijvoorbeeld uitgeschakeld en de wachtrijaffiniteit voor de CPU is expliciet ingesteld in /proc/irq/$IRQ/smp_affinity_list. Om dezelfde CPU-kern te gebruiken om het libreactor-proces en de netwerkwachtrij van inkomende pakketten te verwerken, wordt een aangepaste BPF-handler gebruikt, verbonden door het instellen van de vlag SO_ATTACH_REUSEPORT_CBPF bij het maken van de socket. Om wachtrijen van uitgaande pakketten aan de CPU te binden, zijn de instellingen /sys/class/net/eth0/queues/tx-/xps_cpus gewijzigd. De algehele prestatieverbetering bedroeg 38% en de doorvoer steeg van 603 vereist/s naar 834 vereist/s.
  • Optimalisatie van interruptafhandeling en gebruik van polling. Het inschakelen van de adaptive-rx-modus in het ENA-stuurprogramma en het manipuleren van sysctl net.core.busy_read verhoogde de prestaties met 28% (doorvoer steeg van 834k req/s naar 1.06M req/s, en latentie daalde van 361μs naar 292μs).
  • Het uitschakelen van systeemservices die leiden tot onnodige blokkering in de netwerkstack. Het uitschakelen van dhclient en het handmatig instellen van het IP-adres resulteerde in een prestatieverbetering van 6% en de doorvoer steeg van 1.06 miljoen vereiste/s naar 1.12 miljoen vereiste/s. De reden dat dhclient de prestaties beïnvloedt, is de verkeersanalyse met behulp van een onbewerkte socket.
  • Vechten tegen Spin Lock. Het overschakelen van de netwerkstack naar de “noqueue”-modus via sysctl “net.core.default_qdisc=noqueue” en “tc qdisc Replace dev eth0 root mq” leidde tot een prestatieverbetering van 2% en de doorvoer steeg van 1.12 miljoen req/s naar 1.15 miljoen verzoek/s.
  • Laatste kleine optimalisaties, zoals het uitschakelen van GRO (Generic Receiver Offload) met het commando “ethtool -K eth0 gro off” en het vervangen van het kubieke congestiecontrole-algoritme door reno met behulp van sysctl “net.ipv4.tcp_congestion_control=reno”. De totale productiviteitsstijging bedroeg 4%. De doorvoer steeg van 1.15 miljoen vereist/s naar 1.2 miljoen vereist/s.

Naast de optimalisaties die werkten, bespreekt het artikel ook methoden die niet tot de verwachte prestatieverbetering leidden. Het volgende bleek bijvoorbeeld niet effectief:

  • Het afzonderlijk uitvoeren van libreactor verschilde qua prestaties niet van het uitvoeren ervan in een container. Het vervangen van writev door send, het verhogen van maxevents in epoll_wait en het experimenteren met GCC-versies en vlaggen hadden geen effect (het effect was alleen merkbaar voor de vlaggen “-O3” en “-march-native”).
  • Het upgraden van de Linux-kernel naar versies 4.19 en 5.4, met behulp van de SCHED_FIFO- en SCHED_RR-planners, het manipuleren van sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparante_hugepages=never, skew_tick=1 en clocksource=tsc had geen invloed op de prestaties.
  • In het ENA-stuurprogramma hadden het inschakelen van de Offload-modi (segmentatie, scatter-gather, rx/tx checksum), het bouwen met de vlag "-O3" en het gebruik van de parameters ena.rx_queue_size en ena.force_large_llq_header geen effect.
  • Veranderingen in de netwerkstack verbeterden de prestaties niet:
    • Schakel IPv6 uit: ipv6.disable=1
    • Schakel VLAN uit: modprobe -rv 8021q
    • Schakel pakketbroncontrole uit
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negatief effect)
    • net.ipv4.tcp_sack = 0
    • net.ipv4.tcp_dsack=0
    • net.ipv4.tcp_mem/tcp_wmem/tcp_rmem
    • net.core.netdev_budget
    • net.core.dev_weight
    • net.core.netdev_max_backlog
    • net.ipv4.tcp_slow_start_after_idle=0
    • net.ipv4.tcp_moderate_rcvbuf=0
    • net.ipv4.tcp_timestamps=0
    • net.ipv4.tcp_low_latency = 1
    • ZO_PRIORITEIT
    • TCP_NODELAY

    Bron: opennet.ru

Voeg een reactie