Pengoptimalan Linux untuk menangani 1.2 juta permintaan JSON per detik

Panduan terperinci telah diterbitkan tentang penyetelan lingkungan Linux untuk mencapai kinerja maksimum untuk memproses permintaan HTTP. Metode yang diusulkan memungkinkan peningkatan kinerja prosesor JSON berdasarkan pustaka libreactor di lingkungan Amazon EC2 (4 vCPU) dari 224 ribu permintaan API per detik dengan pengaturan standar Amazon Linux 2 dengan kernel 4.14 menjadi 1.2 juta permintaan per detik setelah optimasi (peningkatan sebesar 436%), dan juga menyebabkan pengurangan penundaan dalam pemrosesan permintaan sebesar 79%. Metode yang diusulkan tidak spesifik untuk libreactor dan berfungsi saat menggunakan server http lain, termasuk nginx, Actix, Netty, dan Node.js (libreactor digunakan dalam pengujian karena solusi berdasarkan metode tersebut menunjukkan kinerja yang lebih baik).

Pengoptimalan Linux untuk menangani 1.2 juta permintaan JSON per detik

Pengoptimalan dasar:

  • Mengoptimalkan kode perpustakaan. Opsi R18 dari kit Techempower digunakan sebagai dasar, yang ditingkatkan dengan menghapus kode untuk membatasi jumlah inti CPU yang digunakan (optimasi memungkinkan mempercepat pekerjaan sebesar 25-27%), dirakit di GCC dengan opsi “-O3” (peningkatan 5-10% ) dan "-march-native" (5-10%), menggantikan panggilan baca/tulis dengan recv/send (5-10%) dan mengurangi overhead saat menggunakan pthreads (2-3%) . Peningkatan kinerja keseluruhan setelah pengoptimalan kode adalah 55%, dan throughput meningkat dari 224 ribu permintaan/dtk menjadi 347 ribu permintaan/dtk.
  • Nonaktifkan perlindungan terhadap kerentanan eksekusi spekulatif. Menggunakan parameter “nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” saat memuat kernel memungkinkan peningkatan kinerja sebesar 28%, dan throughput meningkat dari 347k req/s menjadi 446k req/s. Secara terpisah, peningkatan dari parameter “nospectre_v1” (perlindungan dari Spectre v1 + SWAPGS) adalah 1-2%, “nospectre_v2” (perlindungan dari Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload dan TSX Asynchronous Abort) - 6%. Pengaturan untuk perlindungan terhadap serangan L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass, dan SRBDS tidak diubah, yang tidak memengaruhi kinerja karena tidak bersinggungan dengan konfigurasi yang diuji (misalnya, khusus untuk KVM, bersarang virtualisasi dan model CPU lainnya).
  • Menonaktifkan mekanisme audit dan pemblokiran panggilan sistem menggunakan perintah "auditctl -a never,task" dan menentukan opsi "--security-opt seccomp=unconfined" saat memulai kontainer buruh pelabuhan. Peningkatan performa keseluruhan sebesar 11%, dan throughput meningkat dari 446 ribu req/s menjadi 495 ribu req/s.
  • Menonaktifkan iptables/netfilter dengan membongkar modul kernel terkait. Ide untuk menonaktifkan firewall, yang tidak digunakan dalam solusi server tertentu, dipicu oleh hasil pembuatan profil, berdasarkan fungsi nf_hook_slow yang memerlukan 18% waktu untuk dijalankan. Perlu dicatat bahwa nftables bekerja lebih efisien daripada iptables, namun Amazon Linux terus menggunakan iptables. Setelah menonaktifkan iptables, peningkatan kinerja sebesar 22%, dan throughput meningkat dari 495k req/s menjadi 603k req/s.
  • Mengurangi migrasi penangan antara inti CPU yang berbeda untuk meningkatkan efisiensi penggunaan cache prosesor. Optimalisasi dilakukan baik pada tingkat pengikatan proses libreactor ke inti CPU (CPU Pinning) dan melalui penyematan penangan jaringan kernel (Receive Side Scaling). Misalnya, irqbalance dinonaktifkan dan afinitas antrian ke CPU secara eksplisit diatur di /proc/irq/$IRQ/smp_affinity_list. Untuk menggunakan inti CPU yang sama untuk memproses proses libreactor dan antrian jaringan paket masuk, digunakan pengendali BPF khusus, yang dihubungkan dengan menyetel flag SO_ATTACH_REUSEPORT_CBPF saat membuat soket. Untuk mengikat antrian paket keluar ke CPU, pengaturan /sys/class/net/eth0/queues/tx-/xps_cpus telah diubah. Peningkatan performa keseluruhan sebesar 38%, dan throughput meningkat dari 603 ribu req/s menjadi 834 ribu req/s.
  • Optimalisasi penanganan interupsi dan penggunaan polling. Mengaktifkan mode adaptif-rx di driver ENA dan memanipulasi sysctl net.core.busy_read meningkatkan kinerja sebesar 28% (throughput meningkat dari 834k req/s menjadi 1.06M req/s, dan latensi menurun dari 361μs menjadi 292μs).
  • Menonaktifkan layanan sistem yang menyebabkan pemblokiran yang tidak perlu di tumpukan jaringan. Menonaktifkan dhclient dan mengatur alamat IP secara manual menghasilkan peningkatan kinerja sebesar 6% dan throughput meningkat dari 1.06 juta req/s menjadi 1.12 juta req/s. Alasan dhclient mempengaruhi kinerja adalah dalam analisis lalu lintas menggunakan soket mentah.
  • Melawan Kunci Putar. Mengalihkan tumpukan jaringan ke mode “noqueue” melalui sysctl “net.core.default_qdisc=noqueue” dan “tc qdisc replace dev eth0 root mq” menghasilkan peningkatan kinerja sebesar 2%, dan throughput meningkat dari 1.12 juta permintaan/dtk menjadi 1.15 juta permintaan/dtk.
  • Optimasi kecil terakhir, seperti menonaktifkan GRO (Generic Accept Offload) dengan perintah “ethtool -K eth0 gro off” dan mengganti algoritma kontrol kemacetan kubik dengan reno menggunakan sysctl “net.ipv4.tcp_congestion_control=reno”. Peningkatan produktivitas secara keseluruhan adalah 4%. Throughput meningkat dari 1.15 juta kebutuhan menjadi 1.2 juta kebutuhan.

Selain pengoptimalan yang berhasil, artikel ini juga membahas metode yang tidak menghasilkan peningkatan kinerja yang diharapkan. Misalnya, hal berikut ini ternyata tidak efektif:

  • Menjalankan libreactor secara terpisah tidak berbeda kinerjanya dengan menjalankannya dalam sebuah container. Mengganti writev dengan send, meningkatkan maxevents di epoll_wait, dan bereksperimen dengan versi dan flag GCC tidak berpengaruh (efeknya hanya terlihat untuk flag “-O3” dan “-march-native”).
  • Memutakhirkan kernel Linux ke versi 4.19 dan 5.4, menggunakan penjadwal SCHED_FIFO dan SCHED_RR, memanipulasi sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, Transparent_hugepages=never, skew_tick=1 dan clocksource=tsc tidak memengaruhi kinerja.
  • Pada driver ENA, mengaktifkan mode Offload (segmentasi, scatter-gather, rx/tx checksum), membangun dengan flag “-O3”, dan menggunakan parameter ena.rx_queue_size dan ena.force_large_llq_header tidak berpengaruh.
  • Perubahan pada tumpukan jaringan tidak meningkatkan kinerja:
    • Nonaktifkan IPv6: ipv6.disable=1
    • Nonaktifkan VLAN: modprobe -rv 8021q
    • Nonaktifkan pemeriksaan sumber paket
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (efek negatif)
    • 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_PRIORITAS
    • TCP_NODELAY

    Sumber: opennet.ru

Tambah komentar