Linux 優化每秒可處理 1.2 萬個 JSON 請求

已發布有關調整 Linux 環境以實現處理 HTTP 請求的最佳效能的詳細指南。 所提出的方法可以將Amazon EC2 環境(4 個vCPU) 中基於libreactor 庫的JSON 處理器的效能從具有核心224 的Amazon Linux 2 標準設定下的每秒4.14 萬個API 請求提高到每秒1.2 萬個請求優化後排名第二(增加了 436%),也導致處理請求的延遲減少了 79%。 所提出的方法並不特定於libreactor,並且可以在使用其他http 伺服器時工作,包括nginx、Actix、Netty 和Node.js(在測試中使用libreactor 是因為基於它的解決方案顯示出更好的效能) 。

Linux 優化每秒可處理 1.2 萬個 JSON 請求

基本優化:

  • 優化 libreactor 程式碼。 Techempower 套件中的 R18 選項被用作基礎,透過刪除限制所用 CPU 核心數量的程式碼進行了改進(最佳化允許將工作速度加快 25-27%),並使用「-O3」選項在 GCC 中進行組裝(增加5-10%)和「-march-native」(5-10%),用recv/send 取代讀取/寫入呼叫(5-10%)並減少使用pthread 時的開銷(2-3%)。 程式碼優化後整體效能提升55%,吞吐量從224k req/s提升至347k req/s。
  • 停用針對推測執行漏洞的保護。 載入核心時使用參數「nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off」可將效能提高 28%,吞吐量從 347k req/s 增加到 446k req/s。 另外,參數「nospectre_v1」(針對 Spectre v1 + SWAPGS 的保護)的增加為 1-2%,「nospectre_v2」(針對 Spectre v2 的保護)- 15-20%,「pti=off」(Spectre v3/Meltdown) - 6 %,「mds=off tsx_async_abort=off」(MDS/Zombieload 和TSX 非同步中止)- 6%。 針對 L1TF/Foreshadow (l1tf=flush)、iTLB multihit、Speculative Store Bypass 和 SRBDS 攻擊的防護設定保持不變,這不會影響效能,因為它們與測試的配置沒有交叉(例如,特定於 KVM、嵌套虛擬化和其他CPU 模型)。
  • 使用「auditctl -a never,task」指令停用審核和系統呼叫阻止機制,並在啟動 docker 容器時指定「--security-opt seccomp=unconfined」選項。 整體效能提升了 11%,吞吐量從 446k req/s 增加到 495k req/s。
  • 透過卸載關聯的核心模組來停用 iptables/netfilter。 禁用防火牆的想法並沒有在特定的伺服器解決方案中使用,是由分析結果引發的,根據該結果判斷,nf_hook_slow 函數的執行時間為 18%。 值得注意的是,nftables 比 iptables 工作效率更高,但 Amazon Linux 繼續使用 iptables。 禁用 iptables 後,效能提升了 22%,吞吐量從 495k req/s 增加到 603k req/s。
  • 減少不同CPU核心之間處理程序的遷移,以提高處理器快取的使用效率。 在將 libreactor 程序綁定到 CPU 核心(CPU Pinning)和透過固定核心網路處理程序(接收端擴展)的層面上進行了最佳化。 例如,停用了 irqbalance,並在 /proc/irq/$IRQ/smp_affinity_list 中明確設定了與 CPU 的佇列關聯性。 為了使用相同的CPU核心來處理libreactor進程和傳入資料包的網路佇列,需要使用自訂BPF處理程序,透過在建立套接字時設定SO_ATTACH_REUSEPORT_CBPF標誌來連接。 若要將傳出封包佇列綁定到 CPU,設定 /sys/class/net/eth0/queues/tx- 已更改/xps_cpus。 整體效能提升了 38%,吞吐量從 603k req/s 增加到 834k req/s。
  • 優化中斷處理和輪詢的使用。 在 ENA 驅動程式中啟用自適應接收模式並操作 sysctl net.core.busy_read 將效能提高了 28%(吞吐量從 834k req/s 增加到 1.06M req/s,延遲從 361μs 減少到 292μs)。
  • 停用導致網路堆疊中不必要的阻塞的系統服務。 停用 dhclient 並手動設定 IP 位址導致效能提高 6%,吞吐量從 1.06M req/s 增加到 1.12M req/s。 dhclient 影響效能的原因是使用原始套接字進行流量分析。
  • 對抗自旋鎖。 透過 sysctl“net.core.default_qdisc=noqueue”和“tc qdisc Replace dev eth0 root mq”將網路堆疊切換到“noqueue”模式,效能提高了 2%,吞吐量從 1.12M req/s 增加到 1.15M請求/秒。
  • 最後的小優化,例如使用命令“ethtool -K eth0 gro off”禁用 GRO(通用接收卸載),並使用 sysctl“net.ipv4.tcp_congestion_control=reno”將立方擁塞控制演算法替換為 reno。 整體生產力提高了 4%。 吞吐量從 1.15M req/s 增加到 1.2M req/s。

除了有效的優化之外,本文也討論了沒有帶來預期效能提升的方法。 例如,以下內容被證明是無效的:

  • 單獨運行 libreactor 與在容器中運行它在性能上沒有差異。 用 send 取代 writev、增加 epoll_wait 中的 maxevents 以及嘗試 GCC 版本和標誌都沒有效果(僅對「-O3」和「-march-native」標誌效果明顯)。
  • 將Linux 核心升級到版本4.19 和5.4,使用SCHED_FIFO 和SCHED_RR 調度程序,操作sysctl kernel.sched_min_細粒度_ns、kernel.sched_wakeup_細粒度_ns、transparent_hugepages=never、skew_tick=1c 和 skclock影響性能。
  • 在 ENA 驅動程式中,啟用卸載模式(分段、分散收集、rx/tx 校驗和)、使用「-O3」標誌建置以及使用 ena.rx_queue_size 和 ena.force_large_llq_header 參數沒有任何效果。
  • 網路堆疊的變化並沒有提高效能:
    • 停用 IPv6: ipv6.disable=1
    • 停用 VLAN:modprobe -rv 8021q
    • 禁用包源檢查
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1(負向影響)
    • 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

    來源: opennet.ru

添加評論