Optimering af Linux til at håndtere 1.2 millioner JSON-anmodninger i sekundet

Der er udgivet en detaljeret vejledning om tuning af Linux-miljøet for at opnå maksimal ydeevne til behandling af HTTP-anmodninger. De foreslåede metoder gjorde det muligt at øge ydeevnen af ​​JSON-processoren baseret på libreactor-biblioteket i Amazon EC2-miljøet (4 vCPU) fra 224 tusind API-anmodninger pr. sekund med standardindstillinger for Amazon Linux 2 med kerne 4.14 til 1.2 millioner anmodninger pr. sekund efter optimering (en stigning på 436 %) og førte også til en reduktion af forsinkelser i behandlingen af ​​anmodninger med 79 %. De foreslåede metoder er ikke specifikke for libreactor og virker ved brug af andre http-servere, herunder nginx, Actix, Netty og Node.js (libreactor blev brugt i test, fordi løsningen baseret på den viste bedre ydeevne).

Optimering af Linux til at håndtere 1.2 millioner JSON-anmodninger i sekundet

Grundlæggende optimeringer:

  • Optimering af libreactor-kode. R18-muligheden fra Techempower-sættet blev brugt som grundlag, som blev forbedret ved at fjerne kode for at begrænse antallet af anvendte CPU-kerner (optimering gjorde det muligt at fremskynde arbejdet med 25-27%), samle i GCC med "-O3"-mulighederne (en stigning på 5-10%) og "-march-native" (5-10%), erstatter læse/skrive-opkald med recv/send (5-10%) og reducere overhead ved brug af pthreads (2-3%) . Den samlede ydelsesforøgelse efter kodeoptimering var 55 %, og gennemløbet steg fra 224k req/s til 347k req/s.
  • Deaktiver beskyttelse mod spekulative udførelsessårbarheder. Brug af parametrene "nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off" ved indlæsning af kernen tillod at øge ydeevnen med 28%, og gennemløbet steg fra 347k req/s til 446k req/s. Separat var stigningen fra parameteren "nospectre_v1" (beskyttelse fra Spectre v1 + SWAPGS) 1-2%, "nospectre_v2" (beskyttelse fra Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload og TSX Asynchronous Abort) - 6%. Indstillingerne for beskyttelse mod L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass og SRBDS-angreb blev forladt uændrede, hvilket ikke påvirkede ydeevnen, da de ikke krydsede den testede konfiguration (f.eks. specifik for KVM, indlejret virtualisering og andre CPU-modeller).
  • Deaktivering af revision og systemopkaldsblokeringsmekanismer ved hjælp af kommandoen "auditctl -a never,task" og angivelse af "--security-opt seccomp=unconfined"-indstillingen, når docker-containeren startes. Den samlede præstationsstigning var 11 %, og gennemløbet steg fra 446 req/s til 495 req/s.
  • Deaktivering af iptables/netfilter ved at fjerne de tilknyttede kernemoduler. Ideen til at deaktivere firewall'en, som ikke blev brugt i en specifik serverløsning, blev foranlediget af profileringsresultater, idet funktionen nf_hook_slow tog 18 % af tiden at udføre. Det bemærkes, at nftables fungerer mere effektivt end iptables, men Amazon Linux fortsætter med at bruge iptables. Efter deaktivering af iptables var ydeevneforøgelsen 22 %, og gennemstrømningen steg fra 495k req/s til 603k req/s.
  • Reduceret migrering af handlere mellem forskellige CPU-kerner for at forbedre effektiviteten af ​​processorcachebrug. Optimering blev udført både på niveau med binding af libreactor-processer til CPU-kerner (CPU Pinning) og gennem pinning af kernenetværksbehandlere (Receive Side Scaling). For eksempel blev irqbalance deaktiveret, og køaffinitet til CPU'en blev eksplicit sat i /proc/irq/$IRQ/smp_affinity_list. For at bruge den samme CPU-kerne til at behandle libreactor-processen og netværkskøen af ​​indgående pakker, bruges en brugerdefineret BPF-handler, forbundet ved at indstille SO_ATTACH_REUSEPORT_CBPF-flaget, når soklen oprettes. For at binde køer af udgående pakker til CPU'en er indstillingerne /sys/class/net/eth0/queues/tx- blevet ændret /xps_cpus. Den samlede ydelsesforøgelse var 38 %, og gennemløbet steg fra 603 req/s til 834 req/s.
  • Optimering af afbrydelseshåndtering og brug af polling. Aktivering af den adaptive-rx-tilstand i ENA-driveren og manipulation af sysctl net.core.busy_read øgede ydeevnen med 28 % (gennemstrømningen steg fra 834k req/s til 1.06M req/s, og latensen faldt fra 361μs til 292μs).
  • Deaktivering af systemtjenester, der fører til unødvendig blokering i netværksstakken. Deaktivering af dhclient og manuel indstilling af IP-adressen resulterede i en ydelsesforøgelse på 6 %, og gennemstrømningen steg fra 1.06M req/s til 1.12M req/s. Grunden til, at dhclient påvirker ydeevnen, er i trafikanalyse ved hjælp af en rå socket.
  • Fighting Spin Lock. Skift af netværksstakken til "noqueue"-tilstand via sysctl "net.core.default_qdisc=noqueue" og "tc qdisc replace dev eth0 root mq" førte til en ydelsesforøgelse på 2 %, og gennemstrømningen steg fra 1.12M req/s til 1.15M req/s.
  • Afsluttende mindre optimeringer, såsom at deaktivere GRO (Generic Receive Offload) med kommandoen "ethtool -K eth0 gro off" og erstatte den kubiske overbelastningskontrolalgoritme med reno ved hjælp af sysctl "net.ipv4.tcp_congestion_control=reno". Den samlede produktivitetsstigning var 4 %. Gennemstrømningen steg fra 1.15 M req/s til 1.2 M req/s.

Ud over de optimeringer, der virkede, diskuterer artiklen også metoder, der ikke førte til den forventede præstationsstigning. For eksempel viste følgende sig at være ineffektivt:

  • At køre libreactor separat adskilte sig ikke i ydeevne fra at køre den i en container. At erstatte writev med send, øge maxevents i epoll_wait og eksperimentere med GCC-versioner og flag havde ingen effekt (effekten var kun mærkbar for "-O3" og "-march-native" flag).
  • Opgradering af Linux-kernen til version 4.19 og 5.4 ved hjælp af SCHED_FIFO og SCHED_RR planlæggere, manipulation af sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 og clock påvirkede ikke ydeevnen.
  • I ENA-driveren havde aktivering af Offload-tilstande (segmentering, scatter-gather, rx/tx checksum), bygning med "-O3"-flaget og brug af parametrene ena.rx_queue_size og ena.force_large_llq_header ingen effekt.
  • Ændringer i netværksstakken forbedrede ikke ydeevnen:
    • Deaktiver IPv6: ipv6.disable=1
    • Deaktiver VLAN: modprobe -rv 8021q
    • Deaktiver pakkekildekontrol
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negativ effekt)
    • 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
    • SO_PRIORITY
    • TCP_NODELAY

    Kilde: opennet.ru

Tilføj en kommentar