Optimalizace Linuxu pro zpracování 1.2 milionu požadavků JSON za sekundu

Byl publikován podrobný návod na vyladění prostředí Linuxu pro dosažení maximálního výkonu pro zpracování HTTP požadavků. Navržené metody umožnily zvýšit výkon JSON procesoru založeného na knihovně libreactor v prostředí Amazon EC2 (4 vCPU) z 224 tisíc API požadavků za sekundu při standardním nastavení Amazon Linux 2 s jádrem 4.14 na 1.2 milionu požadavků za sekundu. druhá po optimalizaci (nárůst o 436 %) a také vedla ke snížení zpoždění při zpracování požadavků o 79 %. Navržené metody nejsou specifické pro libreactor a fungují při použití jiných http serverů, včetně nginx, Actix, Netty a Node.js (v testech byl použit libreactor, protože řešení na něm založené vykazovalo lepší výkon).

Optimalizace Linuxu pro zpracování 1.2 milionu požadavků JSON za sekundu

Základní optimalizace:

  • Optimalizace kódu libreactor. Jako základ byla použita volba R18 ze sady Techempower, která byla vylepšena odstraněním kódu pro omezení počtu použitých jader CPU (optimalizace umožnila zrychlení práce o 25-27 %), sestavení v GCC s volbami „-O3“ (nárůst o 5–10 % ) a „-march-native“ (5–10 %), nahrazení volání pro čtení/zápis voláním recv/send (5–10 %) a snížení režie při použití pthreads (2–3 %) . Celkový nárůst výkonu po optimalizaci kódu byl 55 % a propustnost se zvýšila z 224 347 req/s na XNUMX XNUMX req/s.
  • Zakázat ochranu proti zranitelnostem spekulativního spuštění. Použití parametrů „nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off“ při načítání jádra umožnilo zvýšit výkon o 28 % a propustnost se zvýšila z 347k req/s na 446k req/s. Samostatně, nárůst od parametru „nospectre_v1“ (ochrana před Spectre v1 + SWAPGS) byl 1-2 %, „nospectre_v2“ (ochrana před Spectre v2) - 15-20 %, „pti=off“ (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload a TSX Asynchronous Abort) - 6%. Nastavení ochrany proti L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass a SRBDS útokům zůstalo nezměněno, což neovlivnilo výkon, protože se neprolínalo s testovanou konfigurací (například specifické pro KVM, vnořené virtualizace a další modely CPU).
  • Zakázání mechanismů auditování a blokování systémových volání pomocí příkazu „auditctl -a never,task“ a zadáním možnosti „--security-opt seccomp=unconfined“ při spouštění kontejneru dockeru. Celkový výkon vzrostl o 11 % a propustnost se zvýšila z 446 495 req/s na XNUMX XNUMX req/s.
  • Zakázání iptables/netfilter uvolněním souvisejících modulů jádra. Myšlenka deaktivovat firewall, který nebyl použit v konkrétním serverovém řešení, byla vyvolána výsledky profilování, podle kterých se funkce nf_hook_slow spouštěla ​​za 18 % času. Je známo, že nftables je efektivnější než iptables, ale Amazon Linux nadále používá iptables. Po deaktivaci iptables byl nárůst výkonu o 22 % a propustnost se zvýšila z 495 603 req/s na XNUMX XNUMX req/s.
  • Snížená migrace obslužných rutin mezi různými jádry CPU pro zlepšení efektivity využití mezipaměti procesoru. Optimalizace byla provedena jak na úrovni navázání procesů libreactoru na jádra CPU (CPU Pinning), tak prostřednictvím pinningových kernel network handlerů (Receive Side Scaling). Například irqbalance bylo zakázáno a afinita fronty k CPU byla explicitně nastavena v /proc/irq/$IRQ/smp_affinity_list. Chcete-li použít stejné jádro CPU ke zpracování procesu libreactor a síťové fronty příchozích paketů, použije se vlastní BPF handler, připojený nastavením příznaku SO_ATTACH_REUSEPORT_CBPF při vytváření soketu. Aby bylo možné svázat fronty odchozích paketů s CPU, bylo změněno nastavení /sys/class/net/eth0/queues/tx-/xps_cpus. Celkový nárůst výkonu byl 38 % a propustnost se zvýšila z 603 834 req/s na XNUMX XNUMX req/s.
  • Optimalizace obsluhy přerušení a využití dotazování. Povolení režimu adaptive-rx v ovladači ENA a manipulace se systémem sysctl net.core.busy_read zvýšily výkon o 28 % (propustnost vzrostla z 834k req/s na 1.06M req/s a latence se snížila z 361μs na 292μs).
  • Zakázání systémových služeb, které vedou ke zbytečnému blokování v síťovém zásobníku. Deaktivace dhclient a ruční nastavení IP adresy vedlo k 6% nárůstu výkonu a propustnosti se zvýšila z 1.06 M req/s na 1.12 M req/s. Důvod, proč dhclient ovlivňuje výkon, je v analýze provozu pomocí raw socketu.
  • Boj proti Spin Lock. Přepnutí síťového zásobníku do režimu „noqueue“ pomocí sysctl „net.core.default_qdisc=noqueue“ a „tc qdisc nahradit dev eth0 root mq“ vedlo ke zvýšení výkonu o 2 % a propustnost se zvýšila z 1.12 milionu req/s na 1.15 milionu požadavek/s.
  • Poslední drobné optimalizace, jako je deaktivace GRO (Generic Receive Offload) pomocí příkazu „ethtool -K eth0 gro off“ a nahrazení algoritmu řízení kubického přetížení reno pomocí sysctl „net.ipv4.tcp_congestion_control=reno“. Celkový nárůst produktivity byl 4 %. Propustnost se zvýšila z 1.15 mil. req/s na 1.2 mil. req/s.

Kromě optimalizací, které se osvědčily, se článek zabývá také metodami, které nevedly k očekávanému zvýšení výkonu. Například následující se ukázalo jako neúčinné:

  • Samostatně spuštěný libreactor se výkonem nelišil od spuštění v kontejneru. Nahrazení writev send, zvýšení maxevents v epoll_wait a experimentování s verzemi a příznaky GCC nemělo žádný účinek (účinek byl patrný pouze u příznaků „-O3“ a „-march-native“).
  • Upgrade linuxového jádra na verze 4.19 a 5.4 pomocí plánovačů SCHED_FIFO a SCHED_RR, manipulace se sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1
  • V ovladači ENA nemělo povolení režimů Offload (segmentace, scatter-gather, rx/tx kontrolní součet), vytváření s příznakem „-O3“ a použití parametrů ena.rx_queue_size a ena.force_large_llq_header žádný účinek.
  • Změny v síťovém zásobníku nezlepšily výkon:
    • Zakázat IPv6: ipv6.disable=1
    • Zakázat VLAN: modprobe -rv 8021q
    • Zakázat kontrolu zdroje balíčku
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negativní účinek)
    • 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_PRIORITA
    • TCP_NODELAY

    Zdroj: opennet.ru

Přidat komentář