Rumah  >  Artikel  >  hujung hadapan web  >  Menggunakan Node.js dengan Nginx untuk melaksanakan network_node.js beban tinggi

Menggunakan Node.js dengan Nginx untuk melaksanakan network_node.js beban tinggi

WBOY
WBOYasal
2016-05-16 15:52:321261semak imbas

Apabila ia datang untuk membina aplikasi web berkemampuan tinggi, NginX dan Node.js adalah padanan semula jadi. Kesemuanya direka bentuk berdasarkan model dipacu acara dan boleh dengan mudah menembusi kesesakan pelayan web tradisional C10K seperti Apache. Konfigurasi lalai sudah boleh mencapai keselarasan tinggi, tetapi jika anda ingin mencapai lebih daripada beribu-ribu permintaan sesaat pada perkakasan murah, masih terdapat beberapa kerja yang perlu dilakukan.

Artikel ini menganggap bahawa pembaca menggunakan HttpProxyModule NginX untuk bertindak sebagai proksi terbalik untuk pelayan node.js huluan. Kami akan memperkenalkan penalaan sysctl dalam sistem Ubuntu 10.04 dan ke atas, serta penalaan aplikasi node.js dan NginX. Sudah tentu, jika anda menggunakan sistem Debian, anda juga boleh mencapai matlamat yang sama, tetapi kaedah penalaan adalah berbeza.

Penalaan Rangkaian

Jika anda tidak memahami terlebih dahulu mekanisme penghantaran asas Nginx dan Node.js dan menjalankan pengoptimuman disasarkan, tidak kira betapa terperinci pengoptimuman kedua-duanya, ia mungkin sia-sia. Secara umumnya, Nginx menghubungkan klien dan aplikasi huluan melalui soket TCP.

Sistem kami mempunyai banyak ambang dan sekatan untuk TCP, yang ditetapkan melalui parameter kernel. Nilai lalai parameter ini selalunya ditetapkan untuk tujuan umum dan tidak dapat memenuhi trafik tinggi dan keperluan hayat pendek pelayan web.


Berikut ialah beberapa parameter yang menjadi calon untuk menala TCP. Untuk menjadikannya berkesan, anda boleh meletakkannya dalam fail /etc/sysctl.conf, atau meletakkannya dalam fail konfigurasi baharu, seperti /etc/sysctl.d/99-tuning.conf, dan kemudian jalankan sysctl -p ke biarkan kernel memuatkan mereka. Kami menggunakan sysctl-cookbook untuk melakukan kerja fizikal ini.

Perlu diambil perhatian bahawa nilai yang disenaraikan di sini adalah selamat untuk digunakan, tetapi masih disyorkan agar anda mengkaji maksud setiap parameter untuk memilih nilai yang lebih sesuai berdasarkan beban, perkakasan dan penggunaan anda.

Salin kod Kod adalah seperti berikut:
net.ipv4.ip_local_port_range='1024 65000'
net.ipv4.tcp_tw_reuse='1'
net.ipv4.tcp_fin_timeout='15'
net.core.netdev_max_backlog='4096'
net.core.rmem_max='16777216'
net.core.somaxconn='4096'
net.core.wmem_max='16777216'
net.ipv4.tcp_max_syn_backlog='20480'
net.ipv4.tcp_max_tw_buckets='400000'
net.ipv4.tcp_no_metrics_save='1'
net.ipv4.tcp_rmem='4096 87380 16777216'
net.ipv4.tcp_syn_retries='2'
net.ipv4.tcp_synack_retries='2'
net.ipv4.tcp_wmem='4096 65536 16777216'
vm.min_free_kbytes='65536'

Serlahkan beberapa perkara penting.

Salin kod Kod adalah seperti berikut:
net.ipv4.ip_local_port_range

Untuk melayan klien hiliran untuk aplikasi huluan, NginX mesti membuka dua sambungan TCP, satu kepada klien dan satu kepada aplikasi. Apabila pelayan menerima banyak sambungan, port yang tersedia sistem akan cepat habis. Dengan mengubah suai parameter net.ipv4.ip_local_port_range, anda boleh meningkatkan julat port yang tersedia. Jika ralat sedemikian ditemui dalam /var/log/syslog: "kemungkinan SYN banjir pada port 80. Menghantar kuki", ini bermakna sistem tidak dapat mencari port yang tersedia. Meningkatkan parameter net.ipv4.ip_local_port_range boleh mengurangkan ralat ini.

Salin kod Kod adalah seperti berikut:
net.ipv4.tcp_tw_reuse

Apabila pelayan perlu bertukar antara sejumlah besar sambungan TCP, sejumlah besar sambungan dalam keadaan TIME_WAIT akan dijana. TIME_WAIT bermakna sambungan itu sendiri ditutup, tetapi sumber belum dikeluarkan. Menetapkan net_ipv4_tcp_tw_reuse kepada 1 membolehkan kernel cuba mengitar semula sambungan apabila ia selamat, yang jauh lebih murah daripada mewujudkan semula sambungan baharu.

Salin kod Kod adalah seperti berikut:
net.ipv4.tcp_fin_timeout

Ini ialah masa minimum sambungan dalam keadaan TIME_WAIT mesti menunggu sebelum dikitar semula. Menjadikannya lebih kecil boleh mempercepatkan kitar semula.
Cara menyemak status sambungan

Gunakan netstat:

Salin kod Kod adalah seperti berikut:
netstat -tan | susun |. uniq -c

atau gunakan ss:

Salin kod Kod adalah seperti berikut:
ss -s

NginX

Apabila beban pada pelayan web meningkat secara beransur-ansur, kami akan mula menghadapi beberapa batasan aneh NginX. Sambungan terputus dan kernel terus melaporkan banjir SYN. Pada masa ini, purata beban dan penggunaan CPU adalah sangat kecil, dan pelayan jelas boleh mengendalikan lebih banyak sambungan, yang benar-benar mengecewakan.

Selepas siasatan, didapati terdapat banyak sambungan dalam keadaan TIME_WAIT. Ini adalah output daripada salah satu pelayan:

Salin kod Kod adalah seperti berikut:
ss -s
Jumlah: 388 (kernel 541)
TCP: 47461 (estab 311, ditutup 47135, yatim piatu 4, synrecv 0, timewait 47135/0), port 33938

Jumlah Pengangkutan IPv6 IP
* 541 - - -
MENTAH 0 0 0 0
UDP 13 10 3
TCP 326 325 1
INET 339 335 4
FRAG 0 0 0 0


Terdapat 47135 TIME_WAIT sambungan! Lebih-lebih lagi, ia dapat dilihat dari ss bahawa mereka semua adalah sambungan tertutup. Ini menunjukkan bahawa pelayan telah menggunakan kebanyakan port yang tersedia, dan juga membayangkan bahawa pelayan memperuntukkan port baharu untuk setiap sambungan. Penalaan rangkaian membantu sedikit masalah ini, tetapi masih tidak ada port yang mencukupi.

Selepas penyelidikan lanjut, saya menjumpai dokumen tentang arahan keepalive uplink, yang berbunyi:

  • Tetapkan bilangan maksimum sambungan kekal-hidup terbiar ke pelayan huluan Sambungan ini akan dikekalkan dalam cache proses pekerja.

Menarik. Secara teorinya, persediaan ini meminimumkan sambungan terbuang dengan menghantar permintaan ke atas sambungan tembolok. Dokumentasi juga menyebut bahawa kita harus menetapkan proxy_http_version kepada "1.1" dan mengosongkan pengepala "Sambungan". Selepas penyelidikan lanjut, saya mendapati bahawa ini adalah idea yang baik, kerana HTTP/1.1 sangat mengoptimumkan penggunaan sambungan TCP berbanding HTTP1.0, dan Nginx menggunakan HTTP/1.0 secara lalai.

Selepas mengubah suai seperti yang dicadangkan dalam dokumen, fail konfigurasi pautan atas kami menjadi seperti ini:

Salin kod Kod adalah seperti berikut:
upstream backend_nodejs {
pelayan nodejs-3:5016 max_fails=0 fail_timeout=10s;
pelayan nodejs-4:5016 max_fails=0 fail_timeout=10s;
pelayan nodejs-5:5016 max_fails=0 fail_timeout=10s;
pelayan nodejs-6:5016 max_fails=0 fail_timeout=10s;
keepalive 512;
}

Saya juga mengubah suai tetapan proksi dalam bahagian pelayan seperti yang dicadangkan. Pada masa yang sama, proxy_next_upstream telah ditambahkan untuk melangkau pelayan yang gagal, keepalive_timeout pelanggan telah dilaraskan dan log akses telah dimatikan. Konfigurasi menjadi seperti ini:

Salin kod Kod adalah seperti berikut:
pelayan {
dengar 80;
nama_pelayan fast.gosquared.com;

klien_maks_badan_saiz 16M;
keepalive_timeout 10;

lokasi / {
tamat masa ralat proxy_next_upstream http_500 http_502 http_503 http_504;
proxy_set_header Sambungan "";
​ proxy_http_versi 1.1;
proxy_pass http://backend_nodejs;
}

akses_log keluar;
error_log /dev/null crit;
}

Selepas menggunakan konfigurasi baharu, saya mendapati soket yang diduduki oleh pelayan telah dikurangkan sebanyak 90%. Permintaan kini boleh dihantar menggunakan sambungan yang jauh lebih sedikit. Keluaran baharu adalah seperti berikut:

Salin kod Kod adalah seperti berikut:
ss -s

Jumlah: 558 (kernel 604)
TCP: 4675 (estab 485, ditutup 4183, yatim piatu 0, synrecv 0, timewait 4183/0), port 2768

Jumlah Pengangkutan IPv6 IP
* 604 - - -
MENTAH 0 0 0 0
UDP 13 10 3
TCP 492 491 1
INET 505 501 4

Node.js

Terima kasih kepada reka bentuk dipacu acara yang mengendalikan I/O secara tak segerak, Node.js boleh mengendalikan sejumlah besar sambungan dan permintaan di luar kotak. Walaupun terdapat kaedah penalaan lain, artikel ini akan menumpukan terutamanya pada aspek proses node.js.

Nod adalah satu-benang dan tidak secara automatik menggunakan berbilang teras. Dalam erti kata lain, aplikasi tidak boleh mendapatkan keupayaan penuh pelayan secara automatik.

Mencapai pengelompokan proses Nod

Kami boleh mengubah suai aplikasi supaya ia memotong berbilang benang dan menerima data pada port yang sama, dengan itu membolehkan beban menjangkau berbilang teras. Node mempunyai modul kelompok yang menyediakan semua alatan yang diperlukan untuk mencapai matlamat ini, tetapi menambahkannya pada aplikasi memerlukan banyak kerja manual. Jika anda menggunakan express, eBay mempunyai modul yang dipanggil cluster2 yang boleh digunakan.

Halang penukaran konteks

Apabila menjalankan berbilang proses, anda harus memastikan bahawa setiap teras CPU hanya sibuk dengan satu proses pada satu masa. Secara umumnya, jika CPU mempunyai teras N, kita harus menjana proses aplikasi N-1. Ini memastikan bahawa setiap proses mendapat potongan masa yang munasabah, meninggalkan satu teras percuma untuk penjadual kernel menjalankan tugas lain. Kami juga perlu memastikan bahawa pada asasnya tiada tugas lain selain Node.js dilaksanakan pada pelayan untuk mengelakkan perbalahan CPU.

Kami pernah membuat kesilapan dan menggunakan dua aplikasi node.js pada pelayan, dan kemudian setiap aplikasi membuka proses N-1. Akibatnya, mereka bersaing antara satu sama lain untuk CPU, menyebabkan beban sistem meningkat dengan mendadak. Walaupun pelayan kami semuanya mesin 8 teras, prestasi overhed yang disebabkan oleh penukaran konteks masih dapat dirasai dengan jelas. Penukaran konteks merujuk kepada fenomena di mana CPU menggantung tugas semasa untuk melaksanakan tugas lain. Apabila bertukar, kernel mesti menggantung semua keadaan proses semasa dan kemudian memuatkan dan melaksanakan proses lain. Untuk menyelesaikan masalah ini, kami mengurangkan bilangan proses yang dimulakan oleh setiap aplikasi supaya mereka boleh berkongsi CPU secara adil Akibatnya, beban sistem telah dikurangkan:

2015628112206774.png (802×404)

Sila perhatikan gambar di atas untuk melihat bagaimana beban sistem (garisan biru) menurun di bawah bilangan teras CPU (garisan merah). Pada pelayan lain, kami melihat perkara yang sama. Memandangkan jumlah beban kerja kekal sama, peningkatan prestasi dalam graf di atas hanya boleh dikaitkan dengan pengurangan suis konteks.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn