Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngnix transfers data to a unix domain socket incompletely

My application is listening on a unix domain socket (UDS) for incoming data while nginx is sending data using PHP. Sending smaller data chunks of several KB works perfectly but as soon as it gets to certain limit, the browser gets the error 504 Gateway Time-out, nginx logs

upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: _, request: "GET /foo/bar.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock", host: "localhost"

The socket still gets some data (always cut at around 1.5 MB) and replies but the webserver doesn't seem to get the response. Are there any UDS stream limits or nginx variables that must be adjusted?

PHP code:

public function send ($msg)
{
    $str = "{$msg}".chr(27);

    $ret = socket_write($this->socket, $str, strlen($str));

    if ($ret == FALSE)
    {
        return false;
    }
    else
    {
        $response = "";

        while (($chunk = socket_read($this->socket, 2048, PHP_BINARY_READ)) !== FALSE)
        {
            $response .= $chunk;

            if (substr($chunk, -1) == chr(27))
                break;
        }

        //close the connection
        if ($this->connected !== false)
        {
            socket_shutdown($this->socket);
            socket_close($this->socket);
            $this->connected = false;
        }

        return $response;
    }
}
like image 982
Sceptical Jule Avatar asked Nov 08 '22 12:11

Sceptical Jule


1 Answers

Ok for staters Nginx has nothing to do with this question it's that is quite clearly PHP sending and receiving data.

It is more than likely your remote system is not closing the socket at the correct time or is just taking far to long to respond.

while (($chunk = socket_read($this->socket, 2048, PHP_BINARY_READ)) !== FALSE)
{
    $response .= $chunk;
    if (substr($chunk, -1) == chr(27))
    break;
}

This code block has the potential to be an infinite loop with this code if the remote system has not closed the connection/socket and told you about it will keep trying to read and be waiting for 2048 (Bit's or Bytes - I can never remember which size it asks for sure a comment will inform) of data to come through or the socket to close before the read is finished.

So a couple of things to try to lower your read bytes set it to something like 128, put in a timer to your socket (requires async programming in PHP) read so kill it after 28 seconds give your code 2 more seconds to execute (safely exit). or use set_time_limit to increase your time limit.

If you do increase your time limit you will need to increase the amount of time nginx is allowed to get the response from the connection to PHP to do this set your fastcgi_read_timeout

like image 185
Barkermn01 Avatar answered Nov 15 '22 05:11

Barkermn01