Re: патч для Connection: Keep-Alive

Maxim Dounin mdounin at mdounin.ru
Tue May 14 16:17:27 UTC 2013


Hello!

On Tue, May 14, 2013 at 09:39:42PM +0600, Илья Шипицин wrote:

> 14 мая 2013 г., 21:16 пользователь Maxim Dounin <mdounin at mdounin.ru> написал:
> > Hello!
> >
> > On Tue, May 14, 2013 at 06:15:05PM +0600, Илья Шипицин wrote:
> >
> > [...]
> >
> >> во всех случаях, когда добавлялся Keep-Alive: timeout, добавлялся
> >> также и Connection. не вижу ничего некорректного. можете уточнить ?
> >>
> >> другое дело, что я накосячил и не добавлял Keep-Alive: timeout там,
> >> где предполагалось. да, признаю ошибку. вложил новый патч.
> >
> > Это я не досмотрел патч, и предположил не ту ошибку из двух
> > возможных.
> >
> > [...]
> >
> >> --- src/http/ngx_http_header_filter_module.c.orig       Tue May 14 12:17:59 2013
> >> +++ src/http/ngx_http_header_filter_module.c    Tue May 14 16:04:29 2013
> >> @@ -382,7 +382,7 @@
> >>      if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
> >>          len += sizeof("Connection: upgrade" CRLF) - 1;
> >>
> >> -    } else if (r->keepalive) {
> >> +    } else if ((r->keepalive) && ((r->http_version == NGX_HTTP_VERSION_10) || (clcf->keepalive_header)) ) {
> >>          len += sizeof("Connection: keep-alive" CRLF) - 1;
> >>
> >>          /*
> >> @@ -397,9 +397,7 @@
> >>              len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2;
> >>          }
> >>
> >> -    } else {
> >> -        len += sizeof("Connection: close" CRLF) - 1;
> >> -    }
> >> +    }
> >
> > "Connection: close" при выключенном keepalive'е нужно указывать,
> > не возвращать соответствующий заголовок - чревато ненужными
> > проблемами и безуспешными попытками клиентов послать в то же
> > соединение следующий запрос.
> >
> 
> я понимаю ваши опасения, однако с точки зрения буквы закона, rfc 2616
> 
> 8.1.4 Practical Considerations
> 
> 
>  ........
> 
>    A client, server, or proxy MAY close the transport connection at any
>    time.
>  .........
> 
> 
> 

Это _можно_ делать, но на практике - это приводит к сильно 
неоптимальному поведению клиентов.  Поэтому убирать "Connection: 
close" из ответов, keepalive в которых не предполагается  - это 
плохая идея.

С учётом того, что keepalive в нормальных условиях влючён чуть 
более, чем всегда - убирать "Connection: close" не представляется 
разумным ни с какой точки зрения.

> с точки зрения духа закона так поступает IIS (по данным Netcraft-а 16%
> сайтов), как-то же это работает ...

Специально сходил проверил на первый попавшийся сайт с IIS'ом - 
_так_ IIS, насколько я вижу, не поступает:

$ telnet W3schools.com 80
Trying 66.29.212.73...
Connected to W3schools.com.
Escape character is '^]'.
HEAD / HTTP/1.1
Host: w3scools.com

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 29839
Content-Type: text/html
Server: Microsoft-IIS/7.5
Set-Cookie: ASPSESSIONIDCABDDTCD=OMAGHFBBMDCIEKCKOIEGKPAO; path=/
X-Powered-By: ASP.NET
Date: Tue, 14 May 2013 16:10:08 GMT

HEAD / HTTP/1.1
Host: w3scools.com
Connection: close

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 29839
Content-Type: text/html
Server: Microsoft-IIS/7.5
Set-Cookie: ASPSESSIONIDCABDDTCD=MICGHFBBKNHMJHAFKDAJJOJD; path=/
X-Powered-By: ASP.NET
Date: Tue, 14 May 2013 16:10:28 GMT
Connection: close

Connection closed by foreign host.

Т.е. если соединение закрывается - то "Connection: close" в ответе 
присутствует.

> у нас 50 миллионов запросов в день. это в районе 1 гигабайта на
> хедерах "Connection:". нам эта цифра интересна.
> мы, пожалуй, потестируем, всех желающих тоже приглашаю к тесту.
> 
> 
> > Вообще я бы, честно говоря, не трогал это место.
> 
> это абстрактные опасения или вы знаете сценарии, при которых это
> приведет к проблемам ?

При правильной реализации - т.е. не слать "Connection: keep-alive" 
для соединений по HTTP/1.1, если заголовок Keep-Alive не отдаётся - 
только абстрактные.  Все изложенные выше замечания - вполне 
конкретные.

Just in case, правильный патч какой-то такой:

--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -383,7 +383,10 @@ ngx_http_header_filter(ngx_http_request_
         len += sizeof("Connection: upgrade" CRLF) - 1;
 
     } else if (r->keepalive) {
-        len += sizeof("Connection: keep-alive" CRLF) - 1;
+
+        if (r->http_version < NGX_HTTP_VERSION_11 || clcf->keepalive_header) {
+            len += sizeof("Connection: keep-alive" CRLF) - 1;
+        }
 
         /*
          * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header.
@@ -556,8 +559,11 @@ ngx_http_header_filter(ngx_http_request_
                              sizeof("Connection: upgrade" CRLF) - 1);
 
     } else if (r->keepalive) {
-        b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
-                             sizeof("Connection: keep-alive" CRLF) - 1);
+
+        if (r->http_version < NGX_HTTP_VERSION_11 || clcf->keepalive_header) {
+            b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
+                                 sizeof("Connection: keep-alive" CRLF) - 1);
+        }
 
         if (clcf->keepalive_header) {
             b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,


-- 
Maxim Dounin
http://nginx.org/en/donation.html



Подробная информация о списке рассылки nginx-ru