Optimiziranje Linuxa za obradu 1.2 milijuna JSON zahtjeva u sekundi

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

Optimiziranje Linuxa za obradu 1.2 milijuna JSON zahtjeva u sekundi

Osnovne optimizacije:

  • Optimiziranje libreactor koda. Kao osnova korištena je opcija R18 iz Techempower kita, koja je poboljšana uklanjanjem koda za ograničavanje broja korištenih CPU jezgri (optimizacija je omogućila ubrzanje rada za 25-27%), sklapanje u GCC s opcijama “-O3” (povećanje od 5-10% ) i "-march-native" (5-10%), zamjena poziva za čitanje/pisanje s recv/send (5-10%) i smanjenje opterećenja pri korištenju pnit (2-3%) . Ukupno povećanje performansi nakon optimizacije koda iznosilo je 55%, a propusnost se povećala s 224k req/s na 347k req/s.
  • Onemogući zaštitu od spekulativnih ranjivosti izvršenja. Korištenje 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. Zasebno, povećanje od parametra “nospectre_v1” (zaštita od Spectre v1 + SWAPGS) bilo je 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 asinkroni prekid) - 6%. Postavke za zaštitu od L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass i SRBDS napada ostavljene su nepromijenjene, što nije utjecalo na izvedbu jer se nisu presijecale s testiranom konfiguracijom (na primjer, specifične za KVM, ugniježđene virtualizacija i drugi CPU modeli).
  • Onemogućavanje revizije i mehanizama za blokiranje poziva sustava korištenjem naredbe "auditctl -a never,task" i navođenjem opcije "--security-opt seccomp=unconfined" prilikom pokretanja docker spremnika. Ukupno povećanje performansi iznosilo je 11%, a propusnost se povećala sa 446k req/s na 495k req/s.
  • Onemogućavanje iptables/netfilter istovarom povezanih modula kernela. Ideja da se onemogući vatrozid, koji nije korišten u određenom poslužiteljskom rješenju, potaknuta je rezultatima profiliranja, sudeći prema kojima je funkciji nf_hook_slow trebalo 18% vremena da se izvrši. Primijećeno je da nftables radi učinkovitije od iptables, ali Amazon Linux nastavlja koristiti iptables. Nakon onemogućavanja iptables, povećanje performansi bilo je 22%, a propusnost se povećala sa 495k req/s na 603k req/s.
  • Smanjena migracija rukovatelja između različitih CPU jezgri radi poboljšanja učinkovitosti korištenja predmemorije procesora. Optimizacija je provedena i na razini vezanja libreactor procesa na CPU jezgre (CPU Pinning) i putem pinning kernel mrežnih rukovatelja (Receive Side Scaling). Na primjer, irqbalance je onemogućen, a afinitet reda čekanja prema CPU-u izričito je postavljen u /proc/irq/$IRQ/smp_affinity_list. Za korištenje iste CPU jezgre za obradu libreactor procesa i mrežnog reda dolaznih paketa, koristi se prilagođeni BPF rukovatelj, povezan postavljanjem zastavice SO_ATTACH_REUSEPORT_CBPF 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 načina rada u ENA upravljačkom programu i manipuliranje sysctl net.core.busy_read povećalo je performanse za 28% (propusnost je povećana s 834k req/s na 1.06M req/s, a latencija smanjena s 361μs na 292μs).
  • Onemogućavanje usluga sustava koje dovode do nepotrebnog blokiranja u mrežnom stogu. Onemogućavanje dhclienta i ručno postavljanje IP adrese rezultiralo je povećanjem performansi od 6%, a propusnost je povećana s 1.06M req/s na 1.12M req/s. Razlog zašto dhclient utječe na izvedbu je analiza prometa korištenjem sirove utičnice.
  • Borba protiv Spin Locka. Prebacivanje mrežnog stoga u način rada "noqueue" putem sysctl "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 s 1.12M req/s na 1.15M zahtjev/s.
  • Završne manje optimizacije, kao što je onemogućavanje GRO (Generic Receive Offload) naredbom “ethtool -K eth0 gro off” i zamjena kubičnog algoritma za kontrolu zagušenja s reno koristeći sysctl “net.ipv4.tcp_congestion_control=reno”. Ukupno povećanje produktivnosti iznosilo je 4%. Protok je povećan s 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 neučinkovitim:

  • Odvojeno pokretanje libreactora nije se razlikovalo u izvedbi od pokretanja u spremniku. Zamjena writev s send, povećanje maxevents u epoll_wait i eksperimentiranje s GCC verzijama i zastavicama nije imalo učinka (učinak je bio primjetan samo za zastavice "-O3" i "-march-native").
  • Nadogradnja Linux kernela na verzije 4.19 i 5.4, korištenje planera SCHED_FIFO i SCHED_RR, manipuliranje sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 i clocksource=tsc nije utjecalo na performanse.
  • U ENA drajveru, omogućavanje Offload modova (segmentacija, scatter-gather, rx/tx checksum), izgradnja sa zastavom “-O3” i korištenje parametara ena.rx_queue_size i ena.force_large_llq_header nije imalo učinka.
  • Promjene u mrežnom stogu nisu poboljšale performanse:
    • Onemogući IPv6: ipv6.disable=1
    • Onemogući VLAN: modprobe -rv 8021q
    • Onemogući 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 učinak)
    • 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_PRIORITET
    • TCP_NODELAY

    Izvor: opennet.ru

Dodajte komentar