[nginx] HTTP/2: optimized processing of small DATA frames.
Maxim Dounin
mdounin at mdounin.ru
Mon Sep 6 13:41:04 UTC 2021
details: https://hg.nginx.org/nginx/rev/d9e009b39596
branches:
changeset: 7924:d9e009b39596
user: Maxim Dounin <mdounin at mdounin.ru>
date: Mon Sep 06 14:54:50 2021 +0300
description:
HTTP/2: optimized processing of small DATA frames.
The request body filter chain is no longer called after processing
a DATA frame. Instead, we now post a read event to do this. This
ensures that multiple small DATA frames read during the same event loop
iteration are coalesced together, resulting in much faster processing.
Since rb->buf can now contain unprocessed data, window update is no
longer sent in ngx_http_v2_state_read_data() in case of flow control
being used due to filter buffering. Instead, window will be updated
by ngx_http_v2_read_client_request_body_handler() in the posted read
event.
diffstat:
src/http/v2/ngx_http_v2.c | 72 +++++++++-------------------------------------
1 files changed, 15 insertions(+), 57 deletions(-)
diffs (117 lines):
diff -r 4775c1d27378 -r d9e009b39596 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Mon Sep 06 14:54:48 2021 +0300
+++ b/src/http/v2/ngx_http_v2.c Mon Sep 06 14:54:50 2021 +0300
@@ -1092,7 +1092,7 @@ static u_char *
ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
u_char *end)
{
- size_t size, window;
+ size_t size;
ngx_buf_t *buf;
ngx_int_t rc;
ngx_connection_t *fc;
@@ -1148,40 +1148,6 @@ ngx_http_v2_state_read_data(ngx_http_v2_
ngx_http_finalize_request(r, rc);
}
- if (rc == NGX_AGAIN
- && !stream->no_flow_control
- && !r->request_body_no_buffering)
- {
- buf = r->request_body->buf;
-
- if (r->request_body->busy == NULL) {
- buf->pos = buf->start;
- buf->last = buf->start;
- }
-
- window = buf->end - buf->last;
- window -= h2c->state.length - size;
-
- if (window < stream->recv_window) {
- ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
- "http2 negative window update");
- return ngx_http_v2_connection_error(h2c,
- NGX_HTTP_V2_INTERNAL_ERROR);
- }
-
- if (window > stream->recv_window) {
- if (ngx_http_v2_send_window_update(h2c, stream->node->id,
- window - stream->recv_window)
- == NGX_ERROR)
- {
- return ngx_http_v2_connection_error(h2c,
- NGX_HTTP_V2_INTERNAL_ERROR);
- }
-
- stream->recv_window = window;
- }
- }
-
ngx_http_run_posted_requests(fc);
} else if (size) {
@@ -4263,22 +4229,6 @@ ngx_http_v2_process_request_body(ngx_htt
rb->rest = 0;
}
- if (r->request_body_no_buffering && !flush) {
- break;
- }
-
- /* pass buffer to request body filter chain */
-
- rc = ngx_http_v2_filter_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- if (rb->rest == 0) {
- break;
- }
-
if (size == 0) {
break;
}
@@ -4287,6 +4237,14 @@ ngx_http_v2_process_request_body(ngx_htt
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
"http2 request body rest %O", rb->rest);
+ if (flush) {
+ rc = ngx_http_v2_filter_request_body(r);
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
+ }
+
if (rb->rest == 0 && rb->last_saved) {
break;
}
@@ -4295,12 +4253,8 @@ ngx_http_v2_process_request_body(ngx_htt
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
ngx_add_timer(fc->read, clcf->client_body_timeout);
- if (r->request_body_no_buffering) {
- if (!flush) {
- ngx_post_event(fc->read, &ngx_posted_events);
- }
-
- return NGX_AGAIN;
+ if (!flush) {
+ ngx_post_event(fc->read, &ngx_posted_events);
}
return NGX_AGAIN;
@@ -4469,6 +4423,10 @@ ngx_http_v2_read_client_request_body_han
return;
}
+ if (r->stream->no_flow_control) {
+ return;
+ }
+
if (r->request_body->rest == 0) {
return;
}
More information about the nginx-devel
mailing list