Optimaliserer Linux for å håndtere 1.2 millioner JSON-forespørsler per sekund

Det er publisert en detaljert veiledning om innstilling av Linux-miljøet for å oppnå maksimal ytelse for behandling av HTTP-forespørsler. De foreslåtte metodene gjorde det mulig å øke ytelsen til JSON-prosessoren basert på libreactor-biblioteket i Amazon EC2-miljøet (4 vCPU) fra 224 tusen API-forespørsler per sekund med standardinnstillinger for Amazon Linux 2 med kjerne 4.14 til 1.2 millioner forespørsler pr. sekund etter optimalisering (en økning på 436 %), og førte også til en reduksjon i forsinkelser i behandlingen av forespørsler med 79 %. De foreslåtte metodene er ikke spesifikke for libreactor og fungerer ved bruk av andre http-servere, inkludert nginx, Actix, Netty og Node.js (libreactor ble brukt i tester fordi løsningen basert på den viste bedre ytelse).

Optimaliserer Linux for å håndtere 1.2 millioner JSON-forespørsler per sekund

Grunnleggende optimaliseringer:

  • Optimalisering av libreactor-kode. R18-alternativet fra Techempower-settet ble brukt som grunnlag, som ble forbedret ved å fjerne kode for å begrense antall CPU-kjerner som ble brukt (optimalisering tillot å øke hastigheten på arbeidet med 25-27%), og sette sammen i GCC med "-O3"-alternativene (en økning på 5-10%) og "-march-native" (5-10%), erstatter lese/skrive-anrop med recv/send (5-10%) og redusere overhead ved bruk av pthreads (2-3%) . Den generelle ytelsesøkningen etter kodeoptimalisering var 55 %, og gjennomstrømningen økte fra 224k rekv/s til 347k rekv/s.
  • Deaktiver beskyttelse mot spekulative utførelsessårbarheter. Bruk av parameterne "nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off" når du laster inn kjernen, tillot å øke ytelsen med 28 %, og gjennomstrømningen økte fra 347k req/s til 446k req/s. Separat var økningen 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%. Innstillingene for beskyttelse mot L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass og SRBDS-angrep ble stående uendret, noe som ikke påvirket ytelsen siden de ikke krysset den testede konfigurasjonen (for eksempel spesifikt for KVM, nestet virtualisering og andre CPU-modeller).
  • Deaktivering av revisjon og systemanropsblokkeringsmekanismer ved å bruke "auditctl -a never,task"-kommandoen og spesifisere "--security-opt seccomp=unconfined"-alternativet når du starter docker-beholderen. Den totale ytelsesøkningen var 11 %, og gjennomstrømningen økte fra 446 495 rekv/s til XNUMX XNUMX rekv/s.
  • Deaktivering av iptables/netfilter ved å laste ut de tilknyttede kjernemodulene. Ideen om å deaktivere brannmuren, som ikke ble brukt i en spesifikk serverløsning, ble foranlediget av profileringsresultater, ettersom nf_hook_slow-funksjonen tok 18 % av tiden å utføre. Det bemerkes at nftables fungerer mer effektivt enn iptables, men Amazon Linux fortsetter å bruke iptables. Etter deaktivering av iptables var ytelsesøkningen 22 %, og gjennomstrømningen økte fra 495k req/s til 603k req/s.
  • Redusert migrering av behandlere mellom forskjellige CPU-kjerner for å forbedre effektiviteten av prosessorens hurtigbufferbruk. Optimalisering ble utført både på nivået for binding av libreactor-prosesser til CPU-kjerner (CPU Pinning) og gjennom pinning av kjernenettverksbehandlere (Receive Side Scaling). For eksempel ble irqbalance deaktivert og køaffinitet til CPU ble eksplisitt satt i /proc/irq/$IRQ/smp_affinity_list. For å bruke den samme CPU-kjernen til å behandle libreactor-prosessen og nettverkskøen av innkommende pakker, brukes en tilpasset BPF-behandler, koblet til ved å sette SO_ATTACH_REUSEPORT_CBPF-flagget når du oppretter sokkelen. For å binde køer av utgående pakker til CPU, er innstillingene /sys/class/net/eth0/queues/tx- endret /xps_cpus. Den totale ytelsesøkningen var 38 %, og gjennomstrømningen økte fra 603 834 rekv/s til XNUMX XNUMX rekv/s.
  • Optimalisering av avbruddshåndtering og bruk av polling. Aktivering av adaptiv rx-modus i ENA-driveren og manipulering av sysctl net.core.busy_read økte ytelsen med 28 % (gjennomstrømningen økte fra 834k req/s til 1.06M req/s, og latensen ble redusert fra 361μs til 292μs).
  • Deaktivering av systemtjenester som fører til unødvendig blokkering i nettverksstakken. Deaktivering av dhclient og manuell innstilling av IP-adressen resulterte i en ytelsesøkning på 6 % og gjennomstrømningen økte fra 1.06M req/s til 1.12M req/s. Grunnen til at dhclient påvirker ytelsen er i trafikkanalyse ved bruk av en rå-socket.
  • Fighting Spin Lock. Å bytte nettverksstabelen til "noqueue"-modus via sysctl "net.core.default_qdisc=noqueue" og "tc qdisc replace dev eth0 root mq" førte til en ytelsesøkning på 2 %, og gjennomstrømningen økte fra 1.12M req/s til 1.15M krav/s.
  • Siste mindre optimaliseringer, som å deaktivere GRO (Generisk mottaksavlastning) med kommandoen "ethtool -K eth0 gro off" og erstatte algoritmen for kubisk overbelastningskontroll med reno ved å bruke sysctl "net.ipv4.tcp_congestion_control=reno". Den samlede produktivitetsøkningen var 4 %. Gjennomstrømningen økte fra 1.15 millioner krav/s til 1.2 millioner krav/s.

I tillegg til optimaliseringene som fungerte, diskuterer artikkelen også metoder som ikke førte til forventet ytelsesøkning. For eksempel viste følgende seg å være ineffektiv:

  • Å kjøre libreactor separat skilte seg ikke i ytelse fra å kjøre den i en beholder. Å erstatte writev med send, øke maxevents i epoll_wait og eksperimentere med GCC-versjoner og flagg hadde ingen effekt (effekten var merkbar bare for "-O3" og "-march-native"-flaggene).
  • Oppgradering av Linux-kjernen til versjon 4.19 og 5.4, ved hjelp av SCHED_FIFO og SCHED_RR planleggere, manipulering av sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=ts clock ytelse påvirket ikke ytelsen.
  • I ENA-driveren hadde det ingen effekt å aktivere Offload-moduser (segmentering, scatter-gather, rx/tx checksum), bygge med "-O3"-flagget og bruke parameterne ena.rx_queue_size og ena.force_large_llq_header.
  • Endringer i nettverksstakken forbedret ikke ytelsen:
    • Deaktiver IPv6: ipv6.disable=1
    • Deaktiver VLAN: modprobe -rv 8021q
    • Deaktiver pakkekildekontroll
      • 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

Legg til en kommentar