nginx 将数据不完整地传输到 unix 域套接字

Posted

技术标签:

【中文标题】nginx 将数据不完整地传输到 unix 域套接字【英文标题】:ngnix transfers data to a unix domain socket incompletely 【发布时间】:2018-06-14 04:55:57 【问题描述】:

nginx 使用 php 发送数据时,我的应用程序正在 unix 域套接字 (UDS) 上侦听传入数据。发送几 KB 的较小数据块效果很好,但是一旦达到一定的限制,浏览器就会收到错误 504 Gateway Time-out,nginx 日志

读取响应时上游超时(110:连接超时) 来自上游的标头,客户端:127.0.0.1,服务器:_,请求:“GET /foo/bar.php HTTP/1.1",上游: “fastcgi://unix:/run/php/php7.0-fpm.sock”,主机:“localhost”

套接字仍会获取一些数据(总是在 1.5 MB 左右)并进行回复,但网络服务器似乎没有收到响应。 是否有必须调整的 UDS 流限制或 nginx 变量?

PHP 代码:

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;
    

【问题讨论】:

“504 网关超时”意味着负载均衡器(或代理)已断开 TCP 连接,即使仍有未完成的流量。我不应该发生直接连接。 你应该展示你的代码。几年前,我在模块中编写处理程序非常困难。 Nginx 并不容易,文档还有很多不足之处。 我添加了代码 【参考方案1】:

好吧,Nginx 与这个问题无关,很明显是 PHP 发送和接收数据。

很可能您的远程系统没有在正确的时间关闭套接字,或者只是需要很长时间才能响应。

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

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

如果远程系统没有关闭连接/套接字并告诉您它将继续尝试读取并等待 2048(位或字节 - 我可以永远不要记住它要求的大小(确定注释会通知)在读取完成之前要通过的数据或要关闭的套接字。

所以有几件事可以尝试降低你的读取字节数,将它设置为128,在你的套接字上设置一个计时器(需要在 PHP 中进行异步编程)读取,所以在 28 秒后杀死它,再给你的代码 2 个秒执行(安全退出)。或使用set_time_limit 增加您的时间限制。

如果您确实增加了时间限制,您将需要增加允许 nginx 从连接到 PHP 获得响应的时间,以设置您的 fastcgi_read_timeout

【讨论】:

就是这样。我的应用程序没有正确关闭连接(不是 PHP)。由于一个错误,它仅适用于不超过缓冲区大小的短流。谢谢! @ScepticalJule 你能把它标记为答案,那么如果它用声明your remote system is not closing the socket at the correct time回答你的问题【参考方案2】:

错误表明 Nginx 和上游服务器之间的连接超时。

您的请求是否需要 1 分钟以上才能完成?

尝试按照以下方式更改 nginx 位置并阅读有关fastcgi_read_timeout的信息

location ~* \.php$ 
    include         fastcgi_params;
    fastcgi_index   index.php;
    fastcgi_read_timeout 120;
    fastcgi_pass    127.0.0.1:9000;
    fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;

【讨论】:

以上是关于nginx 将数据不完整地传输到 unix 域套接字的主要内容,如果未能解决你的问题,请参考以下文章

Beats:将 Unix 域套接字中的数据索引到 Elastic Stack

Beats:将 Unix 域套接字中的数据索引到 Elastic Stack

高流量站点NGINX与PHP-fpm配置优化

高流量站点NGINX与PHP-fpm配置优化

unix进程间通信方式(下)-unix域套接字(转)

Unix 域套接字和 NPAPI