Avem un server care rulează un site WordPress cu o stivă nginx instalată de serverpilot pe Ubuntu 20 LTS.
Încărcările foarte mari par să rămână blocate în transferul dintre proxy-ul nginx și PHP și am ajuns la sfârșitul a ceea ce știu cum să depanez fără doar să mă uit la el pentru a vedea ce se întâmplă (ceea ce rareori este o utilizare bună a timpului sau cale de a merge înainte). Din câte îmi pot da seama, am mărit timeout-urile necesare și am ridicat toate limitele de disc, dar evident că încă îmi lipsește ceva.
Pentru cazul nostru de utilizare, trebuie să permitem încărcări de până la 50 GB, pe care le-am funcționat fără probleme într-un mediu de pregătire care rulează o stivă LAMP standard. Nu avem probleme cu fișierele sub ~ 2 GB, dar orice lucru peste acesta poate sau nu eșua pe baza unor criterii pe care nu le-am putut găsi. În timp ce depanați problema mai devreme, ora la care copierea fișierului s-a oprit părea arbitrară (cu succes de până la 10 GB), dar cu configurația actuală (a se vedea mai jos), se oprește constant când PHP tmp
fișierul ajunge la 2 GB.
Când încărcăm fișiere foarte mari, putem urmări că fișierul temporar primit consumă spațiu pe disc până când întregul fișier există în /mnt/tmp/[nginx_tmp_path]
(da, există o mulțime de spațiu disponibil pe disc). După aceea, putem vedea că fișierul este copiat în php tmp
calea, dar după câteva secunde, php tmp
fișierul încetează să crească în dimensiune și procesul de copiere se blochează. În cele din urmă, este atins unul dintre intervalele de timp de 600 de secunde și există erori înregistrate (vezi mai jos). În această captură de ecran, avem o încărcare finalizată (din perspectiva browserului/utilizatorului final) de 14,8 GB, care s-a blocat pe transferul de fișiere tmp la aproximativ 2 GB.
La sfârșitul perioadei de 600 de secunde, aceasta se află în jurnalul de erori Apache:
(70008)Rezultatele parțiale sunt valide, dar procesarea este incompletă: [client <MY_IP>] AH01075: Eroare la expedierea cererii către : (citirea brigadei de intrare), referer: https://<THE_URL>/wp-admin/media-new.php
Și jurnalul de erori nginx spunea asta:
2512066#0: *9 expirat în amonte (110: conexiune a expirat) în timpul trimiterii cererii către amonte, client: <IP_MEU>, server: <IP_INTERN>, cerere: „POST /wp-admin/async-upload.php HTTP/ 2.0”, în amonte: „http://127.0.0.1:81/wp-admin/async-upload.php”, gazdă: „<THE_URL>”, referitor: „https://<THE_URL>/wp-admin/ media-new.php"
Este important de reținut că aceste mesaje nu apar în fișierul jurnal decât după 10 minute după ce încărcarea ajunge inițial complet la server, adică la 9 sau mai multe minute după ce copia fișierului pare a fi întreruptă/blocată. Sunt convins că ceva face ca copia fișierului să se blocheze și, în cele din urmă, se ajunge la un timeout - nu cred că problema este cu timeout-ul în sine. În intervalul dintre oprirea copierii fișierului și eroarea de timeout care apare în fișierul jurnal, nu există activitate crescută sau neobișnuită pe server și toate serviciile funcționează și răspund conform așteptărilor.
Cu configurația actuală, PHP tmp
fișierul crește întotdeauna la 2097152 KB (conform du -a
), ceea ce mă face să cred că ating o limită de dimensiune a fișierului încorporată pe care nu am descoperit-o încă.
Opțiunile relevante de configurare a serverului nginx sunt:
În Server
context:
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_max_temp_file_size 51200m;
fastcgi_connect_timeout 600;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
fastcgi_request_buffering dezactivat;
keepalive_timeout 600;
send_timeout 600;
client_max_body_size 0;
client_body_temp_path /mnt/tmp;
client_body_in_file_only clean;
Configurația VirtualHost a Apache:
RequestReadTimeout header=0 body=0
Timeout 3600
ProxyTimeout 3600
Și în sfârșit, configurația PHP:
limita_memorie = -1
max_execution_time = 0
max_input_time = -1
post_max_size = 50G
upload_max_filesize = 50G
default_socket_timeout = -1
Nu știu ce ar putea cauza simptomul pe care îl văd.Orice indicații sunt apreciate!
Note suplimentare: Simptomele mă fac să simt că nu este relevant, dar în cazul în care este... Site-ul rulează prin WP Rocket, dar nu există un serviciu proxy extern precum CloudFlare.
ACTUALIZAȚI: Am adăugat aceste linii la configurația nginx:
proxy_http_versiunea 1.1;
proxy_set_header Conexiune „”;
Acest lucru a schimbat ușor simptomul, dar nu a rezolvat problema. Odată cu această schimbare, comportamentul a revenit la ceea ce am explicat anterior și transferul fișierelor se blochează într-un loc imprevizibil. Primul exemplu de mai jos s-a oprit la 3823176 KB, iar al doilea s-a oprit la 3264364 KB. Motivul diferenței de comportament nu are sens pentru mine, dar merită raportat.
UPDATE 2: Am reușit să stabilesc definitiv acest lucru pentru a fi o problemă în transmiterea tmp
fișier între nginx și php, dar nu reușesc să rezolv exact lucrul care provoacă blocarea procesului.
Putem sări peste proxy-ul nginx și să folosim numai PHP tmp
prin adăugarea acestor linii la configurația nginx:
proxy_buffering dezactivat;
proxy_request_buffering dezactivat;
Cu această configurație, fișierele intră direct în /mnt/tmp/php<RND_STR>
iar când încărcarea este completă, aplicația noastră alege corect fișierul tmp
și își îndeplinește sarcinile.
Cu toate acestea, acest lucru încetinește încărcările la aproximativ 1/3 din lățimea de bandă disponibilă, deci nu este o soluție bună. Totuși, demonstrează că aceasta nu este o problemă de aplicație.
Deci iată ce se întâmplă:
- Utilizatorul încarcă un fișier mare (50 GB este cazul nostru maxim)
- Fișierul ajunge în nginx
tmp
locația în întregime
- Se încearcă copiarea fișierului din nginx
tmp
în PHP tmp
- procesul de copiere se va bloca în câteva secunde undeva imprevizibil, dar între 3 GB și 10 GB. [3b] În acest moment, le putem vedea pe amândouă tmp
fișiere și PHP tmp
fișierul conține un număr de octeți care ar trebui să crească până când este egal cu dimensiunea nginx tmp
dosar, dar nu sunt.Ambele fișiere vor rămâne complet așa cum sunt până când se atinge unul dintre intervalele de timp de 600 de secunde (vezi mai sus), apoi apare o eroare în fișierele jurnal și ambele tmp
fișierele dispar. [3c] Dacă fișierul este sub 3 GB, va funcționa de fiecare dată. Dacă fișierul are mai mult de 3 GB, va funcționa uneori, dar nu și altele - cu cât fișierul este mai mic, cu atât este mai probabil să funcționeze.
- Ocolind Nginx's
tmp
funcționează conform așteptărilor, cu excepția faptului că încărcările sunt lente.
Cu siguranță ceva se blochează în timpul tmp
transfer de fișiere între nginx și PHP atunci când fișierele sunt îngrozitor de mari și mi-ar plăcea să îmi dau seama ce este.