Linux-optimering för att hantera 1.2 miljoner JSON-förfrågningar per sekund

En detaljerad guide har publicerats för att ställa in Linux-miljön för att uppnå maximal prestanda för bearbetning av HTTP-förfrågningar. De föreslagna metoderna gjorde det möjligt att öka prestanda för JSON-processorn baserad på libreactor-biblioteket i Amazon EC2-miljön (4 vCPU) från 224 tusen API-förfrågningar per sekund med standardinställningar för Amazon Linux 2 med kärna 4.14 till 1.2 miljoner förfrågningar per sekund. sekund efter optimering (en ökning med 436 %), och ledde också till en minskning av förseningar i behandlingen av förfrågningar med 79 %. De föreslagna metoderna är inte specifika för libreactor och fungerar när man använder andra http-servrar, inklusive nginx, Actix, Netty och Node.js (libreactor användes i tester eftersom lösningen baserad på den visade bättre prestanda).

Linux-optimering för att hantera 1.2 miljoner JSON-förfrågningar per sekund

Grundläggande optimeringar:

  • Optimering av libreactor-kod. R18-alternativet från Techempower-satsen användes som bas, vilket förbättrades genom att ta bort koden för att begränsa antalet använda CPU-kärnor (optimering gjorde det möjligt att påskynda arbetet med 25-27%), montera i GCC med "-O3"-alternativen (en ökning med 5-10 %) och "-march-native" (5-10 %), ersätter läs/skrivanrop med recv/send (5-10 %) och minskar overhead vid användning av pthreads (2-3 %) . Den totala prestandaökningen efter kodoptimering var 55 %, och genomströmningen ökade från 224k req/s till 347k req/s.
  • Inaktivera skydd mot spekulativa exekveringssårbarheter. Användning av parametrarna “nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” vid laddning av kärnan tillät öka prestanda med 28 %, och genomströmningen ökade från 347k req/s till 446k req/s. Separat var ökningen från parametern "nospectre_v1" (skydd från Spectre v1 + SWAPGS) 1-2%, "nospectre_v2" (skydd från Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload och TSX Asynchronous Abort) - 6%. Inställningarna för skydd mot L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass och SRBDS-attacker lämnades oförändrade, vilket inte påverkade prestandan eftersom de inte korsade den testade konfigurationen (till exempel specifik för KVM, kapslad virtualisering och andra CPU-modeller).
  • Inaktivera revision och systemanropsblockering med kommandot "auditctl -a never,task" och ange alternativet "--security-opt seccomp=unconfined" när du startar docker-behållaren. Den totala prestandaökningen var 11 %, och genomströmningen ökade från 446k req/s till 495k req/s.
  • Inaktivera iptables/netfilter genom att ladda ur de associerade kärnmodulerna. Idén att inaktivera brandväggen, som inte användes i en specifik serverlösning, skapades av profileringsresultat, att döma av vilka funktionen nf_hook_slow tog 18 % av tiden att köra. Det noteras att nftables fungerar mer effektivt än iptables, men Amazon Linux fortsätter att använda iptables. Efter att ha inaktiverat iptables var prestandaökningen 22 % och genomströmningen ökade från 495k req/s till 603k req/s.
  • Minskad migrering av hanterare mellan olika CPU-kärnor för att förbättra effektiviteten i processorcacheanvändning. Optimering utfördes både på nivån för att binda libreactor-processer till CPU-kärnor (CPU Pinning) och genom att fästa kärnnätverkshanterare (Receive Side Scaling). Till exempel inaktiverades irqbalance och köaffinitet till CPU:n var uttryckligen inställd i /proc/irq/$IRQ/smp_affinity_list. För att använda samma CPU-kärna för att bearbeta libreactor-processen och nätverkskön av inkommande paket, används en anpassad BPF-hanterare, ansluten genom att sätta SO_ATTACH_REUSEPORT_CBPF-flaggan när socket skapas. För att binda köer av utgående paket till CPU:n har inställningarna /sys/class/net/eth0/queues/tx- ändrats /xps_cpus. Den totala prestandaökningen var 38 %, och genomströmningen ökade från 603k req/s till 834k req/s.
  • Optimering av avbrottshantering och användning av polling. Aktivering av adaptive-rx-läget i ENA-drivrutinen och manipulering av sysctl net.core.busy_read ökade prestandan med 28 % (genomströmningen ökade från 834k req/s till 1.06M req/s, och latensen minskade från 361μs till 292μs).
  • Inaktivera systemtjänster som leder till onödig blockering i nätverksstacken. Inaktivering av dhclient och manuell inställning av IP-adressen resulterade i en prestandaökning på 6 % och genomströmningen ökade från 1.06 M req/s till 1.12 M req/s. Anledningen till att dhclient påverkar prestandan är i trafikanalys med hjälp av en rå socket.
  • Fighting Spin Lock. Att byta nätverksstacken till "noqueue"-läge via sysctl "net.core.default_qdisc=noqueue" och "tc qdisc replace dev eth0 root mq" ledde till en prestandaökning på 2 %, och genomströmningen ökade från 1.12 M req/s till 1.15 M krav/s.
  • Sista mindre optimeringar, som att inaktivera GRO (Generic Receive Offload) med kommandot "ethtool -K eth0 gro off" och ersätta algoritmen för kontroll av kubisk överbelastning med reno med sysctl "net.ipv4.tcp_congestion_control=reno". Den totala produktivitetsökningen var 4 %. Genomströmningen ökade från 1.15 M req/s till 1.2 M req/s.

Utöver de optimeringar som fungerade diskuterar artikeln även metoder som inte ledde till förväntad prestandaökning. Till exempel visade sig följande vara ineffektivt:

  • Att köra libreactor separat skilde sig inte i prestanda från att köra den i en behållare. Att ersätta writev med send, öka maxevents i epoll_wait och experimentera med GCC-versioner och flaggor hade ingen effekt (effekten märktes endast för "-O3" och "-march-native" flaggorna).
  • Uppgradering av Linux-kärnan till version 4.19 och 5.4, med hjälp av SCHED_FIFO och SCHED_RR schemaläggare, manipulering av sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=ts clock prestanda påverkade inte prestanda.
  • I ENA-drivrutinen hade det ingen effekt att aktivera avlastningslägen (segmentering, scatter-gather, rx/tx checksum), bygga med "-O3"-flaggan och använda parametrarna ena.rx_queue_size och ena.force_large_llq_header.
  • Ändringar i nätverksstacken förbättrade inte prestandan:
    • Inaktivera IPv6: ipv6.disable=1
    • Inaktivera VLAN: modprobe -rv 8021q
    • Inaktivera kontroll av paketkälla
      • 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

    Källa: opennet.ru

Lägg en kommentar