Optimizacija Linuxa za rukovanje 1.2 miliona JSON zahtjeva u sekundi

Objavljen je detaljan vodič o podešavanju Linux okruženja za postizanje maksimalnih performansi za obradu HTTP zahtjeva. Predložene metode omogućile su povećanje performansi JSON procesora zasnovanog na biblioteci libreactor u okruženju Amazon EC2 (4 vCPU) sa 224 hiljade API zahtjeva u sekundi sa standardnim postavkama Amazon Linux 2 sa kernelom 4.14 na 1.2 miliona zahtjeva po drugo nakon optimizacije (povećanje od 436%), a takođe je dovelo do smanjenja kašnjenja u obradi zahtjeva za 79%. Predložene metode nisu specifične za libreactor i rade kada se koriste drugi http serveri, uključujući nginx, Actix, Netty i Node.js (libreactor je korišten u testovima jer je rješenje zasnovano na njemu pokazalo bolje performanse).

Optimizacija Linuxa za rukovanje 1.2 miliona JSON zahtjeva u sekundi

Osnovne optimizacije:

  • Optimizacija koda libreaktora. Kao osnova je korištena opcija R18 iz Techempower kita, koja je poboljšana uklanjanjem koda za ograničavanje broja korištenih CPU jezgara (optimizacija je omogućila ubrzanje rada za 25-27%), sklapanje u GCC sa opcijama “-O3” (povećanje od 5-10%) i "-march-native" (5-10%), zamjenjujući pozive za čitanje/pisanje sa recv/send (5-10%) i smanjenje troškova pri korištenju pthread-a (2-3%) . Ukupno povećanje performansi nakon optimizacije koda bilo je 55%, a protok je povećan sa 224k req/s na 347k req/s.
  • Onemogućite zaštitu od ranjivosti spekulativnog izvršenja. Korišćenje parametara “nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” prilikom učitavanja kernela omogućilo je povećanje performansi za 28%, a propusnost je povećana sa 347k req/s na 446k req/s. Odvojeno, povećanje od parametra “nospectre_v1” (zaštita od Spectre v1 + SWAPGS) je bilo 1-2%, “nospectre_v2” (zaštita od Spectre v2) - 15-20%, “pti=off” (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload i TSX Asynchronous Abort) - 6%. Postavke zaštite od L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass i SRBDS napada ostavljene su nepromijenjene, što nije uticalo na performanse jer se nisu ukrštale s testiranom konfiguracijom (na primjer, specifično za KVM, ugniježđeno virtuelizacija i drugi modeli procesora).
  • Onemogućavanje mehanizama revizije i blokiranja sistemskih poziva korištenjem naredbe "auditctl -a never,task" i navođenjem opcije "--security-opt seccomp=unconfined" prilikom pokretanja docker kontejnera. Ukupno povećanje performansi bilo je 11%, a propusnost je povećana sa 446k req/s na 495k req/s.
  • Onemogućavanje iptables/netfilter istovarom povezanih modula kernela. Na ideju da se onemogući firewall, koji nije korišten u određenom serverskom rješenju, potaknuli su rezultati profiliranja, sudeći po kojima je funkciji nf_hook_slow trebalo 18% vremena da se izvrši. Primećeno je da nftables radi efikasnije od iptablesa, ali Amazon Linux nastavlja da koristi iptables. Nakon onemogućavanja iptablesa, povećanje performansi je bilo 22%, a propusnost se povećala sa 495k req/s na 603k req/s.
  • Smanjena migracija rukovalaca između različitih CPU jezgara kako bi se poboljšala efikasnost upotrebe keš memorije procesora. Optimizacija je obavljena kako na nivou vezivanja procesa libreaktora za jezgre CPU-a (CPU Pinning) tako i putem pinovanja kernel mrežnih rukovaoca (Receive Side Scaling). Na primjer, irqbalance je onemogućen i afinitet reda prema CPU-u je eksplicitno postavljen u /proc/irq/$IRQ/smp_affinity_list. Da bi se koristilo isto CPU jezgro za obradu procesa libreaktora i mrežnog reda dolaznih paketa, koristi se prilagođeni BPF rukovalac, povezan postavljanjem SO_ATTACH_REUSEPORT_CBPF zastavice prilikom kreiranja utičnice. Za vezanje redova odlaznih paketa na CPU, postavke /sys/class/net/eth0/queues/tx- su promijenjene /xps_cpus. Ukupno povećanje performansi bilo je 38%, a propusnost je povećana sa 603k req/s na 834k req/s.
  • Optimizacija rukovanja prekidima i korištenje prozivanja. Omogućavanje adaptive-rx moda u ENA drajveru i manipulacija sysctl net.core.busy_read povećali su performanse za 28% (propusnost je povećana sa 834k req/s na 1.06M req/s, a latencija je smanjena sa 361μs na 292μs).
  • Onemogućavanje sistemskih usluga koje dovode do nepotrebnog blokiranja u mrežnom stogu. Onemogućavanje dhclient-a i ručno podešavanje IP adrese rezultiralo je povećanjem performansi od 6% i povećanjem propusnosti sa 1.06M req/s na 1.12M req/s. Razlog zašto dhclient utječe na performanse je u analizi saobraćaja korištenjem sirove utičnice.
  • Fighting Spin Lock. Prebacivanje mrežnog steka na “noqueue” način rada putem sysctl-a “net.core.default_qdisc=noqueue” i “tc qdisc replace dev eth0 root mq” dovelo je do povećanja performansi od 2%, a propusnost se povećala sa 1.12M req/s na 1.15M req/s.
  • Završne manje optimizacije, kao što je onemogućavanje GRO (generičko oslobađanje prijema) naredbom “ethtool -K eth0 gro off” i zamjena algoritma kubične kontrole zagušenja sa reno koristeći sysctl “net.ipv4.tcp_congestion_control=reno”. Ukupno povećanje produktivnosti iznosilo je 4%. Propusnost je povećana sa 1.15M req/s na 1.2M req/s.

Osim optimizacija koje su uspjele, u članku se govori i o metodama koje nisu dovele do očekivanog povećanja performansi. Na primjer, sljedeće se pokazalo neefikasnim:

  • Pokretanje libreactor-a zasebno se nije razlikovalo u performansama od pokretanja u kontejneru. Zamjena writev sa send, povećanje maksimalnih događaja u epoll_wait i eksperimentiranje sa GCC verzijama i zastavicama nije imalo efekta (efekat je bio primjetan samo za zastavice “-O3” i “-march-native”).
  • Nadogradnja Linux kernela na verzije 4.19 i 5.4, korištenjem planera SCHED_FIFO i SCHED_RR, manipuliranje sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1c nije utjecalo na performanse
  • U ENA drajveru, omogućavanje režima Offload (segmentacija, raspršivanje, rx/tx kontrolna suma), građenje sa “-O3” zastavicom i korišćenje parametara ena.rx_queue_size i ena.force_large_llq_header nije imalo efekta.
  • Promjene u mrežnom stogu nisu poboljšale performanse:
    • Onemogući IPv6: ipv6.disable=1
    • Onemogući VLAN: modprobe -rv 8021q
    • Onemogućite provjeru izvora paketa
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negativan efekat)
    • 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

    izvor: opennet.ru

Dodajte komentar