Nginx TCP_NODELAY и TCP_NOPUSH/TCP_CORK
Информация от Игоря Сысоева (письмо от 2005 года) по поводу того, как работает логика опций:
1 2 |
tcp_nopush on; tcp_nodelay on; |
Судя по описанию – для первой опции нужно использовать sendfile, для второй должен использоваться keep alive. Надо будет посмотреть изменилась ли логика работы в последних версиях Nginx.
Письмо с описанием:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
Да, в Линкусе TCP_CORK (tcp_nopush) и TCP_NODELAY взаимоисключающие, но nginx проявляет недюженный интеллект, пытаясь совместить преимущества обеих опций. "tcp_nopush on" полезно для sendfile(), он в этом случае выводит данные полными пакетами. После того, как весь запрос обработан, TCP_CORK/TCP_NOPUSH выключается, что приводит в сбросу последнего неполного пакета. "tcp_nodelay on" полезно для keep-alive. nginx включает TCP_NODELAY только по окончании запроса, после которого соединение переходит в состоянии keep-alive. До этого nginx выводит данные вызовами writev() достаточно большими порциями для заполнения пакета ("postpone_output 1460"), поэтому данные должны уходить без задержек и TCP_NODELAY не нужен. А вот с последним неполным пакетом может случится небольшая задержка, если соединение не закрывается. Для этого и нужно включить TCP_NODELAY. В Линуксе обработка этих двух опций tcp_nopush on; tcp_nodelay on; такова: 1) если данные будут выводить комбинацией writev(заголовок)/sendfile(), то проверяется, не было ли уже включен TCP_NODELAY. Если было, то TCP_NODELAY выключается и включается TCP_CORK. По окончании передачи TCP_CORK выключается. Включать TCP_NODELAY не нужно, так как выключание TCP_CORK сбрасывает данные. 2) если при переходе в keep-alive TCP_CORK не была включена, то включается TCP_NODELAY, чтобы сбросить неполный пакет. Кстати, возможно, для "proxy_buffering off" имеет смысл включать TCP_NODELAY до отдачи ответа. Игорь Сысоев http://sysoev.ru |