Optimizacija Linuxa za obdelavo 1.2 milijona zahtev JSON na sekundo

Objavljen je bil podroben vodnik o prilagajanju okolja Linux za doseganje največje zmogljivosti za obdelavo zahtev HTTP. Predlagane metode so omogočile povečanje zmogljivosti procesorja JSON, ki temelji na knjižnici libreactor v okolju Amazon EC2 (4 vCPU) z 224 tisoč zahtev API na sekundo s standardnimi nastavitvami Amazon Linux 2 z jedrom 4.14 na 1.2 milijona zahtev na sekundo. drugo mesto po optimizaciji (povečanje za 436 %), privedlo pa je tudi do zmanjšanja zamud pri obdelavi zahtevkov za 79 %. Predlagane metode niso specifične za libreactor in delujejo pri uporabi drugih strežnikov http, vključno z nginx, Actix, Netty in Node.js (libreactor je bil uporabljen v testih, ker je rešitev, ki temelji na njem, pokazala boljšo zmogljivost).

Optimizacija Linuxa za obdelavo 1.2 milijona zahtev JSON na sekundo

Osnovne optimizacije:

  • Optimizacija kode libreactorja. Za osnovo je bila uporabljena možnost R18 iz kompleta Techempower, ki je bila izboljšana z odstranitvijo kode za omejitev števila uporabljenih CPE jeder (optimizacija je omogočila pospešitev dela za 25-27%), sestavljanje v GCC z možnostmi “-O3” (povečanje za 5-10 %) in "-march-native" (5-10 %), ki nadomešča klice za branje/pisanje z recv/send (5-10 %) in zmanjšuje stroške pri uporabi pthreads (2-3 %) . Splošno povečanje zmogljivosti po optimizaciji kode je bilo 55 %, prepustnost pa se je povečala z 224k zahtev/s na 347k zahtev/s.
  • Onemogoči zaščito pred špekulativnimi ranljivostmi izvajanja. Uporaba parametrov “nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” pri nalaganju jedra je omogočila povečanje zmogljivosti za 28 %, prepustnost pa se je povečala s 347k zahtev/s na 446k zahtev/s. Ločeno je bilo povečanje parametra "nospectre_v1" (zaščita pred Spectre v1 + SWAPGS) 1-2%, "nospectre_v2" (zaščita pred Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload in TSX Asynchronous Abort) - 6%. Nastavitve za zaščito pred napadi L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass in napadi SRBDS so ostale nespremenjene, kar pa ni vplivalo na delovanje, saj se niso sekale s testirano konfiguracijo (na primer specifično za KVM, ugnezdeno). virtualizacija in drugi modeli CPE).
  • Onemogočanje nadzora in mehanizmov za blokiranje sistemskih klicev z ukazom "auditctl -a never,task" in podajanjem možnosti "--security-opt seccomp=unconfined" ob zagonu vsebnika dockerja. Skupna zmogljivost se je povečala za 11 %, prepustnost pa se je povečala s 446k zahtev/s na 495k zahtev/s.
  • Onemogočanje iptables/netfilter z razkladanjem povezanih modulov jedra. Idejo o onemogočitvi požarnega zidu, ki ni bil uporabljen v določeni strežniški rešitvi, so spodbudili rezultati profiliranja, sodeč po katerih je funkcija nf_hook_slow vzela 18 % časa za izvedbo. Opozoriti je treba, da nftables deluje bolj učinkovito kot iptables, vendar Amazon Linux še naprej uporablja iptables. Po onemogočanju iptables je bilo povečanje zmogljivosti 22 %, prepustnost pa se je povečala s 495k req/s na 603k req/s.
  • Zmanjšana selitev obdelovalcev med različnimi jedri CPU za izboljšanje učinkovitosti uporabe predpomnilnika procesorja. Optimizacija je bila izvedena tako na ravni vezave procesov libreactorja na jedra CPE (CPU Pinning) kot prek pripenjanja omrežnih obdelovalcev jedra (Receive Side Scaling). Na primer, irqbalance je bil onemogočen in afiniteta čakalne vrste do CPE je bila izrecno nastavljena v /proc/irq/$IRQ/smp_affinity_list. Za uporabo istega jedra CPU za obdelavo procesa libreactor in omrežne čakalne vrste dohodnih paketov se uporablja upravljalnik BPF po meri, povezan z nastavitvijo zastavice SO_ATTACH_REUSEPORT_CBPF pri ustvarjanju vtičnice. Za vezavo čakalnih vrst odhodnih paketov na CPE so bile spremenjene nastavitve /sys/class/net/eth0/queues/tx- /xps_cpus. Skupno povečanje zmogljivosti je bilo 38 %, prepustnost pa se je povečala s 603k zahtev/s na 834k zahtev/s.
  • Optimizacija obdelave prekinitev in uporabe anketiranja. Omogočanje načina adaptive-rx v gonilniku ENA in manipulacija sysctl net.core.busy_read sta povečala zmogljivost za 28 % (pretok se je povečal z 834 k zahtev/s na 1.06 milijona zahtev/s, zakasnitev pa se je zmanjšala s 361 μs na 292 μs).
  • Onemogočanje sistemskih storitev, ki vodijo do nepotrebnega blokiranja v omrežnem skladu. Onemogočanje dhclienta in ročna nastavitev naslova IP sta povzročila 6-odstotno povečanje zmogljivosti in pretok povečal z 1.06M req/s na 1.12M req/s. Razlog, da dhclient vpliva na zmogljivost, je analiza prometa z uporabo neobdelane vtičnice.
  • Boj proti Spin Locku. Preklop omrežnega sklada v način »noqueue« prek sysctl »net.core.default_qdisc=noqueue« in »tc qdisc replace dev eth0 root mq« je vodil do 2-odstotnega povečanja zmogljivosti, prepustnost pa se je povečala z 1.12M req/s na 1.15M zahteva
  • Končne manjše optimizacije, kot je onemogočanje GRO (Generic Receive Offload) z ukazom »ethtool -K eth0 gro off« in zamenjava kubičnega algoritma za nadzor prezasedenosti z reno z uporabo sysctl »net.ipv4.tcp_congestion_control=reno«. Skupna produktivnost se je povečala za 4 %. Prepustnost se je povečala z 1.15M req/s na 1.2M req/s.

Poleg optimizacij, ki so delovale, članek obravnava tudi metode, ki niso vodile do pričakovanega povečanja zmogljivosti. Za neučinkovito se je na primer izkazalo naslednje:

  • Ločeno izvajanje libreactorja se v zmogljivosti ni razlikovalo od izvajanja v vsebniku. Zamenjava writev s send, povečanje maxevents v epoll_wait in eksperimentiranje z različicami in zastavicami GCC ni imelo učinka (učinek je bil opazen le pri zastavicah »-O3« in »-march-native«).
  • Nadgradnja jedra Linuxa na različici 4.19 in 5.4 z uporabo načrtovalcev SCHED_FIFO in SCHED_RR, manipulacija sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 in clocksource=tsc ni vplivalo na zmogljivost.
  • V gonilniku ENA omogočanje načinov razbremenitve (segmentacija, zbiranje razpršenosti, kontrolna vsota rx/tx), gradnja z zastavico »-O3« in uporaba parametrov ena.rx_queue_size in ena.force_large_llq_header niso imeli učinka.
  • Spremembe v omrežnem skladu niso izboljšale zmogljivosti:
    • Onemogoči IPv6: ipv6.disable=1
    • Onemogoči VLAN: modprobe -rv 8021q
    • Onemogoči preverjanje vira paketa
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negativen uč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_PRIORITY
    • TCP_NODELAY

    Vir: opennet.ru

Dodaj komentar