Optimització de Linux per gestionar 1.2 milions de sol·licituds JSON per segon

S'ha publicat una guia detallada sobre l'ajust de l'entorn Linux per aconseguir el màxim rendiment per processar les sol·licituds HTTP. Els mètodes proposats van permetre augmentar el rendiment del processador JSON basat en la biblioteca libreactor a l'entorn Amazon EC2 (4 vCPU) de 224 mil sol·licituds d'API per segon amb la configuració estàndard d'Amazon Linux 2 amb el nucli 4.14 a 1.2 milions de sol·licituds per segon. segon després de l'optimització (un augment del 436%), i també va provocar una reducció dels retards en la tramitació de les sol·licituds en un 79%. Els mètodes proposats no són específics de libreactor i funcionen quan s'utilitzen altres servidors http, inclosos nginx, Actix, Netty i Node.js (libreactor es va utilitzar a les proves perquè la solució basada en ell mostrava un millor rendiment).

Optimització de Linux per gestionar 1.2 milions de sol·licituds JSON per segon

Optimitzacions bàsiques:

  • Optimització del codi de libreactor. Es va utilitzar com a base l'opció R18 del kit Techempower, que es va millorar eliminant el codi per limitar el nombre de nuclis de CPU utilitzats (l'optimització va permetre accelerar el treball entre un 25 i un 27%), muntant en GCC amb les opcions "-O3" (un augment del 5-10%) i "-march-native" (5-10%), substituint les trucades de lectura/escriptura per recv/send (5-10%) i reduint la sobrecàrrega quan s'utilitzen pthreads (2-3%) . L'augment del rendiment global després de l'optimització del codi va ser del 55% i el rendiment va augmentar de 224k req/s a 347k req/s.
  • Desactiva la protecció contra vulnerabilitats d'execució especulativa. L'ús dels paràmetres "nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off" quan es carregava el nucli va permetre augmentar el rendiment en un 28% i el rendiment va augmentar de 347k req/s a 446k req/s. Per separat, l'augment del paràmetre "nospectre_v1" (protecció de Spectre v1 + SWAPGS) va ser de l'1-2%, "nospectre_v2" (protecció de Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6%, "mds=off tsx_async_abort=off" (MDS/Zombieload i TSX avortament asíncron) - 6%. Els paràmetres de protecció contra els atacs L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass i SRBDS es van deixar sense canvis, cosa que no va afectar el rendiment, ja que no es creuaven amb la configuració provada (per exemple, específica per a KVM, imbricada). virtualització i altres models de CPU).
  • Desactivar els mecanismes d'auditoria i de bloqueig de trucades del sistema mitjançant l'ordre "auditctl -a never,task" i especificant l'opció "--security-opt seccomp=unconfined" quan s'inicia el contenidor docker. L'augment del rendiment global va ser de l'11% i el rendiment va augmentar de 446k req/s a 495k req/s.
  • Desactivant iptables/netfilter descarregant els mòduls del nucli associats. La idea de desactivar el tallafoc, que no s'utilitzava en una solució de servidor específica, es va plantejar pels resultats del perfil, a jutjar per com la funció nf_hook_slow va trigar un 18% del temps a executar-se. S'observa que nftables funciona de manera més eficient que iptables, però Amazon Linux continua utilitzant iptables. Després de desactivar iptables, l'augment del rendiment va ser del 22% i el rendiment va augmentar de 495k req/s a 603k req/s.
  • Reducció de la migració de controladors entre diferents nuclis de CPU per millorar l'eficiència de l'ús de la memòria cau del processador. L'optimització es va dur a terme tant a nivell d'enllaç dels processos de libreactor als nuclis de la CPU (CPU Pinning) com mitjançant la fixació de controladors de xarxa del nucli (Receive Side Scaling). Per exemple, irqbalance es va desactivar i l'afinitat de la cua amb la CPU es va establir explícitament a /proc/irq/$IRQ/smp_affinity_list. Per utilitzar el mateix nucli de la CPU per processar el procés de libreactor i la cua de xarxa dels paquets entrants, s'utilitza un controlador BPF personalitzat, connectat establint el senyalador SO_ATTACH_REUSEPORT_CBPF en crear el sòcol. Per vincular cues de paquets sortints a la CPU, s'ha canviat la configuració /sys/class/net/eth0/queues/tx- /xps_cpus. L'augment del rendiment global va ser del 38% i el rendiment va augmentar de 603k req/s a 834k req/s.
  • Optimització del maneig d'interrupcions i ús del sondeig. L'habilitació del mode rx adaptatiu al controlador ENA i la manipulació de sysctl net.core.busy_read van augmentar el rendiment en un 28% (el rendiment va augmentar de 834k req/s a 1.06M req/s i la latència va disminuir de 361μs a 292μs).
  • Desactivació dels serveis del sistema que provoquen un bloqueig innecessari a la pila de xarxa. La desactivació de dhclient i la configuració manual de l'adreça IP van donar lloc a un augment del rendiment del 6% i el rendiment va augmentar d'1.06 milions de requeriments/s a 1.12 milions de requeriments/s. La raó per la qual dhclient afecta el rendiment és en l'anàlisi del trànsit mitjançant un sòcol en brut.
  • Fighting Spin Lock. Canviar la pila de xarxa al mode "noqueue" mitjançant sysctl "net.core.default_qdisc=noqueue" i "tc qdisc replace dev eth0 root mq" va provocar un augment del rendiment del 2% i el rendiment va augmentar d'1.12 M req/s a 1.15 M requeriment/s.
  • Optimitzacions menors finals, com ara desactivar GRO (Generic Receive Offload) amb l'ordre "ethtool -K eth0 gro off" i substituir l'algoritme de control de la congestió cúbica per reno mitjançant sysctl "net.ipv4.tcp_congestion_control=reno". L'augment global de la productivitat va ser del 4%. El rendiment ha augmentat d'1.15 milions de requeriments/s a 1.2 milions de requeriments/s.

A més de les optimitzacions que van funcionar, l'article també parla de mètodes que no van provocar l'augment de rendiment esperat. Per exemple, el següent va resultar ineficaç:

  • L'execució de libreactor per separat no difereix en rendiment d'executar-lo en un contenidor. La substitució de writev per send, l'augment dels esdeveniments màxims a epoll_wait i l'experimentació amb versions i banderes de GCC no van tenir cap efecte (l'efecte només es va notar per a les banderes "-O3" i "-march-native").
  • Actualització del nucli de Linux a les versions 4.19 i 5.4, utilitzant els programadors SCHED_FIFO i SCHED_RR, manipulant sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=mai, skew_source i no afectaven el rendiment.=tsc.
  • Al controlador ENA, l'habilitació dels modes de descàrrega (segmentació, dispersió, suma de comprovació rx/tx), la creació amb la bandera "-O3" i l'ús dels paràmetres ena.rx_queue_size i ena.force_large_llq_header no va tenir cap efecte.
  • Els canvis a la pila de xarxa no van millorar el rendiment:
    • Desactiva IPv6: ipv6.disable=1
    • Desactiva la VLAN: modprobe -rv 8021q
    • Desactiva la comprovació de l'origen del paquet
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (efecte negatiu)
    • 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_PRIORITAT
    • TCP_NODELAY

    Font: opennet.ru

Afegeix comentari