CV laden
Zurück zu Business Cases

nginx

502 wegen einer vollen Listen-Queue

PHP-FPM war nicht langsam. Docker-NAT auf Port 9000 warf SYNs, als der Backlog bei 128 endete.

nginx lieferte 502 in kurzen Wellen. Das PHP-FPM-Slowlog war leer. Die acht Worker waren beschäftigt, nicht fest. ss -ltn im php-Container zeigte Recv-Q bei 128 auf 9000/tcp. Neue Verbindungen bekamen ECONNREFUSED. Das ist ein Listen-Backlog, kein Application-Timeout.

Compose veröffentlichte 9000 über docker-proxy. Jeder nginx-Request öffnete eine neue TCP-Verbindung. net.core.somaxconn im php-Image war 128. listen.backlog im Pool wuchs nicht darüber. NAT addierte Latenz, die Queue füllte sich bei einem Katalog-Stampede, den Memcached später schluckte.

Das Problem war eine volle Accept-Queue auf docker-proxy, nicht langsames Laravel. Besucher sahen 502, während Worker gleich frei waren. Ich brauchte einen Unix-Socket, Keepalive und somaxconn passend zu listen.backlog.

Worker sind in einer Sekunde frei. Die Accept-Queue ist schon voll.
Worker sind in einer Sekunde frei. Die Accept-Queue ist schon voll.

Der Socket

nginx und php teilen ein Volume mit einem Unix-Socket. Upstream hat keepalive 16. docker-proxy liegt nicht auf dem Hot Path. somaxconn im php-Container ist 4096. listen.backlog passt dazu. pm.max_children blieb bei acht. Diese Zahl war nie die 502.

Unix-Socket auf demselben Host. Keepalive am Upstream. Kein SYN pro HTML-Request.
Unix-Socket auf demselben Host. Keepalive am Upstream. Kein SYN pro HTML-Request.
  • error_log mit connect() failed meint weiter den Backlog, kein Fatal in Laravel.
  • TCP 9000 bleibt für Host-PHP außerhalb von Compose. Die öffentliche Site nutzt es nicht.
  • queue- und schedule-Container sprechen mit Redis, nicht mit diesem Socket.

Die 502er waren weg beim selben Traffic, der Recv-Q füllte. Die PHP-FPM-Zeit im Access-Log blieb. Geändert hat sich, wie viele Handshakes auf dem Boden warteten.

Was ich daraus mitnehme

Leeres Slowlog plus 502 ist ein Socket-Problem, bis das Gegenteil feststeht. Recv-Q am Listen-Limit ist der Beweis.

docker-proxy plus SYN pro Request ist eine Queue, die ein Stampede füllt. Unix-Socket und Keepalive nehmen sie vom Boden.

pm.max_children hochzusetzen hätte Recv-Q versteckt, bis der Host keinen RAM mehr hat. Das echte Limit war der Backlog.

Zurück zu Business Cases