]> git.kaiwu.me - nginx.git/commitdiff
Lingering close for connections with pipelined requests.
authorMaxim Dounin <mdounin@mdounin.ru>
Thu, 2 Feb 2023 20:38:48 +0000 (23:38 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Thu, 2 Feb 2023 20:38:48 +0000 (23:38 +0300)
This is expected to help with clients using pipelining with some constant
depth, such as apt[1][2].

When downloading many resources, apt uses pipelining with some constant
depth, a number of requests in flight.  This essentially means that after
receiving a response it sends an additional request to the server, and
this can result in requests arriving to the server at any time.  Further,
additional requests are sent one-by-one, and can be easily seen as such
(neither as pipelined, nor followed by pipelined requests).

The only safe approach to close such connections (for example, when
keepalive_requests is reached) is with lingering.  To do so, now nginx
monitors if pipelining was used on the connection, and if it was, closes
the connection with lingering.

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=973861#10
[2] https://mailman.nginx.org/pipermail/nginx-devel/2023-January/ZA2SP5SJU55LHEBCJMFDB2AZVELRLTHI.html

src/core/ngx_connection.h
src/http/ngx_http_request.c

index 6d3348d9c26d28cbd535a2bca44395d2e12bdebd..36e1be27c64622a1c741005501f4c948144c4123 100644 (file)
@@ -172,6 +172,7 @@ struct ngx_connection_s {
     unsigned            timedout:1;
     unsigned            error:1;
     unsigned            destroyed:1;
+    unsigned            pipeline:1;
 
     unsigned            idle:1;
     unsigned            reusable:1;
index 131a2c83cac958d97dac1ca93829f8c2d2d1f2f1..5e0340b288141e7471a71238ba859c5c964c89b7 100644 (file)
@@ -2753,7 +2753,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
             && (r->lingering_close
                 || r->header_in->pos < r->header_in->last
-                || r->connection->read->ready)))
+                || r->connection->read->ready
+                || r->connection->pipeline)))
     {
         ngx_http_set_lingering_close(r->connection);
         return;
@@ -3123,6 +3124,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
 
         c->sent = 0;
         c->destroyed = 0;
+        c->pipeline = 1;
 
         if (rev->timer_set) {
             ngx_del_timer(rev);