【问题标题】:nginx, fastcgi and open socketsnginx、fastcgi 和开放式套接字
【发布时间】:2011-11-28 19:37:53
【问题描述】:

我正在尝试在 nginx 上使用 fastcgi,但遇到了一些问题。 Nginx 不重用连接,它在 BeginRequest 标志中给出 0,因此应用程序应该在请求完成后关闭连接。

我有以下关闭代码:

socket.shutdown(SocketShutdown.BOTH);
socket.close();

问题是连接实际上并没有关闭。它们会以 TIME_WAIT 的形式持续存在,而 nginx(或其他东西)不会继续打开新连接。 我的猜测是我在关闭套接字时做错了什么,但我不知道是什么......在相关说明中 - 我怎样才能让 nginx 保持连接打开?

这是使用 nginx 1.0.6 和 D 2.055

编辑: 还没有靠近,但我也检查了 linger 选项,它关闭了:

linger l;
socket.getOption(SocketOptionLevel.SOCKET, SocketOption.LINGER, l);
assert(l.on == 0); // off

getOption 虽然返回 4.. 不知道这意味着什么。返回值未记录。

编辑: 我也尝试在发送的最后一条消息上使用 TCP_NODELAY,但这也没有任何效果:

socket.setOption(SocketOptionLevel.SOCKET, SocketOption.TCP_NODELAY, 1);

编辑: nginx 1.1.4 支持保持连接。但是这并没有按预期工作。正确报告服务器负责连接生命周期管理,但它仍然为每个请求创建一个新套接字。

【问题讨论】:

  • 可能是 socket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);可以帮忙吗?
  • 您使用 Nginx 和 FastCGI 开发高性能网站?然后实现您自己的 HTTP 1.0 协议。这比使用 FCGI 更容易做,而且会更快。或者,您可以为 nginx 编写自己的模块,以通过共享内存 IPC 将请求数据传递给旨在返回响应的另一个进程。
  • 请问为什么选择fastcgi?通常你可以找到一个更好的替代品

标签: sockets nginx d


【解决方案1】:

NGINX 代理保活

关于 fastcgi 的 nginx (v1.1) keepalive。正确的配置方法如下:

upstream fcgi_backend {
  server localhost:9000;
  keepalive 32;
}

server {
  ...
  location ~ \.php$ {
    fastcgi_keep_conn on;
    fastcgi_pass fcgi_backend;
    ...
  }
}

TIME_WAIT

TCP TIME_WAIT 连接状态与 lingers、tcp_no_delays、timeout 等无关。它完全由操作系统内核管理,并且只能受系统范围配置选项的影响。一般来说,这是不可避免的。这正是 TCP 协议的工作方式。阅读herehere

避免 TIME_WAIT 的最根本方法是通过设置 linger=ON 和 linger_timeout=0 在关闭时重置(发送 RST 数据包)TCP 连接。但是对于正常操作不建议这样做,因为您可能会丢失未发送的数据。仅在错误情况下(超时等)重置套接字。

我会尝试以下内容。发送完所有数据后,调用 socket.shutdown(WRITE) (这会将 FIN 数据包发送给对方)并且不要关闭套接字。然后继续从套接字读取,直到收到连接被另一端关闭的指示(在 C 中,通常由 0 长度的 read() 指示)。收到此指示后,关闭套接字。阅读更多关于它的信息here

TCP_NODELAY & TCP_CORK

如果您正在开发任何类型的网络服务器,则必须研究这些选项,因为它们确实会影响性能。如果不使用这些,您可能会在发送的每个数据包上遇到约 20 毫秒的延迟(Nagle 延迟)。尽管这些延迟看起来很小,但它们可能会对您的每秒请求数统计数据产生不利影响。一个很好的阅读是here

另一个关于套接字的好参考是here

关于 FastCGI

我同意其他评论者的观点,即在后端使用 FastCGI 协议可能不是一个好主意。如果您关心性能,那么您应该实现自己的 nginx 模块(或者,如果这看起来太难了,则可以为其他服务器提供一个模块,例如 NXWEB)。否则使用 HTTP。它比 FastCGI 更容易实现并且用途更广泛。而且我不会说 HTTP 比 FastCGI 慢很多。

【讨论】:

    【解决方案2】:

    你好 simendsjo

    以下建议可能完全偏离目标。

    我自己使用 NginX 进行开发;但是,我绝对不是 NginX 专家。

    NginX 工作者

    不过,您的问题让我们想起了 NginX 中的 workers and worker processes

    除此之外,NginX 中的 workers and worker processes 用于当工作人员在磁盘 I/O 上阻塞时减少延迟,并在 select()/ 时限制每个进程的连接数使用 poll()

    你可以找到more info here

    NginX Fcgiwrap 和套接字

    另一个指针可能是下面的代码,虽然这个例子是特定于 Debian 的。

    #!/usr/bin/perl
    
    use strict;
    use warnings FATAL => qw( all );
    
    use IO::Socket::UNIX;
    
    my $bin_path = '/usr/local/bin/fcgiwrap';
    my $socket_path = $ARGV[0] || '/tmp/cgi.sock';
    my $num_children = $ARGV[1] || 1;
    
    close STDIN;
    
    unlink $socket_path;
    my $socket = IO::Socket::UNIX->new(
        Local => $socket_path,
        Listen => 100,
    );
    
    die "Cannot create socket at $socket_path: $!\n" unless $socket;
    
    for (1 .. $num_children) {
        my $pid = fork;
        die "Cannot fork: $!" unless defined $pid;
        next if $pid;
    
        exec $bin_path;
        die "Failed to exec $bin_path: $!\n";
    }
    

    您可以找到有关此解决方案的更多信息here

    【讨论】:

      【解决方案3】:

      将套接字超时设置为尽可能低,然后关闭套接字。 如果您尝试在此之后向套接字写入任何内容,会发生什么?可以推送未转义的二进制文件以发出关闭连接的信号,迫使其结束。这就是 IE 被称为 Internet Exploder 的原因

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-25
        • 2010-11-15
        • 2015-04-08
        • 2010-10-19
        • 1970-01-01
        • 2011-04-25
        • 2012-04-26
        相关资源
        最近更新 更多