Rumah > Artikel > Operasi dan penyelenggaraan > Bagaimana untuk menyelesaikan kod status HTTP perkhidmatan nginx+php-fpm 502
Untuk salah satu projek web kami, disebabkan peningkatan dalam bandar baharu, bilangan lawatan telah meningkat dan tekanan terhadap db telah meningkat Sebagai pihak perniagaan yang menyediakan antara muka, sejumlah besar permintaan "502". telah dilaporkan baru-baru ini oleh maklum balas hiliran.
502, gerbang buruk, biasanya ralat di hulu (ini adalah PHP, sebab biasa 502 ialah pelaksanaan skrip melebihi masa tetapan tamat masa, atau tetapan tamat masa terlalu besar). menyebabkan proses PHP mengambil masa yang lama Ia tidak boleh dikeluarkan dan tiada proses pekerja terbiar untuk mengambil tetamu.
Projek kami disebabkan oleh tetapan masa pelaksanaan PHP yang terlalu singkat Dalam kes ini, anda boleh terlebih dahulu meningkatkan masa pelaksanaan PHP dengan sewajarnya dan memastikan bahawa Pengoptimuman 502 akan mengambil lebih banyak masa.
Terdapat dua pilihan untuk mengawal masa pelaksanaan php, max_execution_time dalam php.ini dan request_terminate_timeout dalam php-fpm request_terminate_timeout boleh mengatasi max_execution_time, jadi jika anda tidak mahu menukar php.ini global, tukar sahaja. php- Konfigurasi fpm sudah memadai.
Di bawah saya akan menganalisis secara terperinci mengapa nginx mengembalikan 502 apabila pelaksanaan skrip php melebihi masa yang ditetapkan.
Mari kita tetapkan adegan dahulu dan hasilkan semula masalah:
nginx dan php masing-masing memulakan hanya seorang pekerja untuk penjejakan yang mudah.
permintaan_terminate_timeout php-fpm ditetapkan kepada 3s.
Uji skrip test.php
sleep(20); echo 'ok';
go go go:
Lawati www.v.com/test.php dalam penyemak imbas, dan ia akan muncul seperti yang dijangkakan selepas 3 saat...404 ? ? ? apa? ? ?
Permulaan yang buruk, cepat lihat fail konfigurasi nginx
Konfigurasi lokasi ini apabila Ralat 5xx berlaku Lompat ke antara muka yang kelihatan bagus, tetapi saya tidak mempunyai fail 50x.html di bawah /usr/share/nginx/html. Jadi saya mendapat 404. Tidakkah ini menjejaskan ketepatan penghakiman saya terhadap masalah itu? Komen sahaja! Lawati lagi, tunggu 3 saat, dan akhirnya antara muka 'biasa' keluar.
Memandangkan persekitaran sudah sedia, mari ikut rutin dan ikut rutin penyelesaian masalah untuk masalah web dahulu:
nginx:
Ralat yang dilaporkan adalah recv() gagal (104: sambungan ditetapkan semula oleh rakan sebaya.
Recv gagal dan sambungan telah ditetapkan semula. Mengapakah tetapan semula sambungan? Adakah ia benar? daripada php. dalam php.ini Tetapi di sini kita tidak melihat ralat php, tetapi pada ralat php-fpm ditentukan oleh pilihan error_log dalam php-fpm.conf)
Setiap permintaan menjana 2 amaran dan 1 notis:amaran: Pelaksanaan skrip tamat masa dan ditamatkan
amaran: Proses anak menerima sigterm. Isyarat telah keluar.
Notis: Memulakan sub-proses baharu (kerana saya menetapkan pm.min_spare_servers = 1)
Nampaknya jika proses pekerja php tamat, ia bukan sahaja akan ditamatkan pelaksanaan skrip , dan proses pekerja juga akan keluar Nampaknya sambungan ralat nginx ditetapkan semula kerana proses pekerja php keluar (jika satu pihak dalam sambungan tcp diputuskan, pertama akan dihantar kepada pihak lain)
Melalui log Telah diketahui bahawa pelaksanaan skrip php tamat dan sub-proses pekerja keluar, menyebabkan nginx melaporkan tetapan semula sambungan ralat oleh rakan sebaya Mari kita gunakan strace untuk melihat situasi php dan nginx:
php:
1.Terima permintaan sambungan nginx (soket, ikat dan dengar semuanya selesai dalam induk). port nginx ialah 47039. Membaca data daripada fd0 adalah daripada input standard Ini ditetapkan oleh protokol fast-cgi , dan menerima 856 bait dalam format protokol fastcgi. Bagaimana pula dengan masaOleh kerana paket data protokol fastcgi adalah sejajar 8-bait dan terdiri daripada pengepala paket dan badan paket. Dan ia mula-mula akan menghantar paket permintaan, termasuk beberapa id permintaan, versi, jenis dan maklumat lain (pengepala dan badan masing-masing menduduki 8 bait), dan kemudian menghantar paket params untuk lulus get parameter dan pembolehubah persekitaran (header ialah 8 bytes), badan paket menjadi lebih panjang), dan akhirnya paket data params tanpa badan paket dan hanya pengepala paket dihantar, menunjukkan penghujung penghantaran parameter (8 bait pengepala paket). Jadi tiga bacaan pertama digunakan untuk membaca pengepala dan badan paket permintaan, serta pengepala paket params Bacaan keempat adalah untuk membaca data sebenar, dan bacaan terakhir adalah untuk membaca pengepala yang terakhir paket params. Oleh itu, data yang dihantar oleh nginx hendaklah 8+8+8+856+8=896 bait (yang sepadan dengan bait penghantaran nginx di bawah). Ambil perhatian bahawa jika ia adalah mod pos, paket data stdin juga akan dihantar.
3. Tetapkan tidur selama 20s, iaitu tidur(20) dalam program php Selepas itu, kerana proses ditamatkan, tidak akan ada lagi. Program strace juga telah dikeluarkan.
nginx:
1.Terima permintaan kepada penyemak imbas Anda boleh melihat bahawa port pada bahagian penyemak imbas ialah 56434, ip ialah 192.168. 1.105, dan ia telah ditubuhkan Fd yang disambungkan ialah 3.
2. Terima data daripada fd3, protokol http.
3. Cipta soket, fd21, untuk mewujudkan sambungan dengan php.
4. Sambungkan ke fd21, anda boleh melihat bahawa sambungan adalah port 9000 mesin tempatan Di sini nginx dan php-fpm menggunakan kaedah sambungan soket ip Jika nginx dan php-fpm digunakan pada satu mesin , unix boleh dipertimbangkan.
5. Tulis data ke fd21, format protokol cepat-cgi, kita lihat bahawa panjang bertulis ialah 896, yang sepadan dengan panjang yang diterima oleh php di atas.
6. Fungsi recvfrom mengembalikan econnreset (tetapan semula sambungan oleh rakan sebaya) daripada fd21
7. Tulis maklumat ralat ke fd9. Ia boleh disimpulkan bahawa fd9 ialah deskriptor fail log ralat .
8. Tutup sambungan dengan fd21.
9 Tulis 502 gerbang buruk ke fd3, iaitu maklumat yang dikembalikan kepada penyemak imbas.
10 Tulis log akses kepada fd8. Dapat disimpulkan bahawa fd8 ialah deskriptor fail log akses nginx.
Mari sahkan inferens log akses nginx dan log ralat. Anda boleh melihat bahawa ia sememangnya fd8, fd9, dan dalam mod tulis.
Kemudian kita juga boleh melihat pada penghantaran keseluruhan paket rangkaian semasa proses ini:
Tangkap paket melalui tcpdump Ia lebih mudah menggunakan artifak untuk melihatnya.
Oleh kerana saya hanya mahu melihat komunikasi antara nginx dan php, dan saya tahu di atas bahawa port nginx ialah 47039, saya boleh menapis pakej yang sepadan melalui tcp.srcport==47039.
Anda boleh melihat proses interaksi data antara nginx dan php-fpm: 47039->9000 mewujudkan jabat tangan tiga hala, kemudian menghantar data ke 9000, 9000 balasan dengan ack, dan 9000 selepas 3 saat Balas kepada yang pertama. Tak salah pun.
Nota:
syn, setiap sirip menduduki nombor siri
ack, pertama tidak menduduki nombor siri (reqnum dan acknum bagi dua pakej 28 dan 29 ialah yang sama )
Nombor jujukan ditambah 1 untuk setiap bait (896 bait dihantar dalam 29 paket, manakala seq 29 paket ialah 4219146879, dan ack 30 paket ialah 4219147775, yang betul-betul berbeza daripada 896)
Pertama Tiada Balasan diperlukan.
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan kod status HTTP perkhidmatan nginx+php-fpm 502. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!