nginx, fastcgi и открытые сокеты - PullRequest
28 голосов
/ 01 октября 2011

Я экспериментирую с использованием fastcgi на nginx, но столкнулся с некоторыми проблемами.Nginx не использует соединения повторно, он дает 0 в флагах BeginRequest, поэтому приложение должно закрыть соединение после завершения запроса.

У меня есть следующий код для закрытия:

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

Проблема в том, что соединения на самом деле не закрыты. Они сохраняются как TIME_WAIT, и nginx (или что-то еще) не будет продолжать открывать новые соединения.Я предполагаю, что я делаю что-то не так при закрытии сокетов, но я не знаю, что .. В соответствующей заметке - как я могу получить nginx, чтобы держать соединения открытыми?

Это использует nginx 1.0.6 и D 2.055

РЕДАКТИРОВАТЬ: Не подобрался ближе, но я также проверил опцию задержки, и она выключена:

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 поддерживает живые соединения.Это работает не так, как ожидалось. Правильно сообщать, что сервер отвечает за управление временем жизни соединения, но все равно создает новый сокет для каждого запроса.

Ответы [ 3 ]

3 голосов
/ 28 февраля 2012

NGINX proxy keepalive

Относительно поддержки активности nginx (v1.1) для fastcgi. Правильный способ его настройки заключается в следующем:

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

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

TIME_WAIT

Состояние соединения TCP TIME_WAIT не имеет никакого отношения к задержкам, tcp_no_delays, тайм-аутам и т. Д. Он полностью управляется ядром ОС и может зависеть только от общесистемных параметров конфигурации. Как правило, это неизбежно. Так работает протокол TCP. Читайте об этом здесь и здесь .

Наиболее радикальный способ избежать TIME_WAIT - сбросить (отправить RST пакет) TCP-соединение при закрытии, установив linger = ON и linger_timeout = 0. Но делать это не рекомендуется для нормальной работы, так как вы можете потерять неотправленные данные. Сбрасывать сокет только в случае ошибки (таймауты и т. Д.).

Я бы попробовал следующее. После того, как вы отправите все свои данные, вызовите socket.shutdown (WRITE) (это отправит пакет FIN другой стороне) и еще не закройте сокет. Затем продолжайте чтение из сокета, пока не получите индикацию о том, что соединение закрыто другим концом (в C, который обычно обозначается как read 0) (). После получения этого указания закройте розетку. Подробнее об этом здесь .

TCP_NODELAY & TCP_CORK

Если вы разрабатываете какой-либо сетевой сервер, вы должны изучить эти параметры, так как они влияют на производительность. Без их использования вы можете столкнуться с задержкой ~ 20 мс ( задержка Нэгла ) для каждого отправленного пакета. Хотя эти задержки выглядят небольшими, они могут отрицательно повлиять на статистику запросов в секунду. Хорошее чтение об этом здесь .

Другая хорошая справка о сокетах: здесь .

О FastCGI

Я бы согласился с другими комментаторами, что использование протокола FastCGI для вашей серверной части может быть не очень хорошей идеей. Если вы заботитесь о производительности, вам следует внедрить собственный модуль nginx (или, если это кажется слишком сложным, модуль для какого-либо другого сервера, такого как NXWEB ). В противном случае используйте HTTP. Его проще реализовать и он гораздо более универсален, чем FastCGI. И я бы не сказал, что HTTP намного медленнее, чем FastCGI.

0 голосов
/ 01 декабря 2011

Установите время ожидания сокета как можно ниже, а затем закройте сокет.Если после этого вы попытаетесь что-нибудь записать в сокет, что произойдет?Можно нажать неэкранированный двоичный файл, чтобы сигнализировать о закрытии соединения, заставляя его завершитьсяВот как IE стал известен как Internet Exploder

0 голосов
/ 24 октября 2011

Привет simendsjo ,

Следующие предложения могут быть полностью не в цель.

Я использую NginX для разработки; однако я абсолютно не эксперт по NginX.

Рабочие NginX

Тем не менее, ваша проблема вернула в память что-то о рабочих и рабочих процессах в NginX.

Помимо прочего, рабочие и рабочие процессы в NginX используются для уменьшения задержки, когда рабочие блокируют на дисковых операциях ввода-вывода и ограничивают количество соединений на процесс, когда используется select () / poll () .

Вы можете найти более подробную информацию здесь .

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";
}

Вы можете найти больше информации об этом решении здесь .

...