Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 7924:d9e009b39596
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.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 06 Sep 2021 14:54:50 +0300 |
parents | 4775c1d27378 |
children | 336084ff943b |
comparison
equal
deleted
inserted
replaced
7923:4775c1d27378 | 7924:d9e009b39596 |
---|---|
1090 | 1090 |
1091 static u_char * | 1091 static u_char * |
1092 ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, | 1092 ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, |
1093 u_char *end) | 1093 u_char *end) |
1094 { | 1094 { |
1095 size_t size, window; | 1095 size_t size; |
1096 ngx_buf_t *buf; | 1096 ngx_buf_t *buf; |
1097 ngx_int_t rc; | 1097 ngx_int_t rc; |
1098 ngx_connection_t *fc; | 1098 ngx_connection_t *fc; |
1099 ngx_http_request_t *r; | 1099 ngx_http_request_t *r; |
1100 ngx_http_v2_stream_t *stream; | 1100 ngx_http_v2_stream_t *stream; |
1144 stream->in_closed, 0); | 1144 stream->in_closed, 0); |
1145 | 1145 |
1146 if (rc != NGX_OK && rc != NGX_AGAIN) { | 1146 if (rc != NGX_OK && rc != NGX_AGAIN) { |
1147 stream->skip_data = 1; | 1147 stream->skip_data = 1; |
1148 ngx_http_finalize_request(r, rc); | 1148 ngx_http_finalize_request(r, rc); |
1149 } | |
1150 | |
1151 if (rc == NGX_AGAIN | |
1152 && !stream->no_flow_control | |
1153 && !r->request_body_no_buffering) | |
1154 { | |
1155 buf = r->request_body->buf; | |
1156 | |
1157 if (r->request_body->busy == NULL) { | |
1158 buf->pos = buf->start; | |
1159 buf->last = buf->start; | |
1160 } | |
1161 | |
1162 window = buf->end - buf->last; | |
1163 window -= h2c->state.length - size; | |
1164 | |
1165 if (window < stream->recv_window) { | |
1166 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, | |
1167 "http2 negative window update"); | |
1168 return ngx_http_v2_connection_error(h2c, | |
1169 NGX_HTTP_V2_INTERNAL_ERROR); | |
1170 } | |
1171 | |
1172 if (window > stream->recv_window) { | |
1173 if (ngx_http_v2_send_window_update(h2c, stream->node->id, | |
1174 window - stream->recv_window) | |
1175 == NGX_ERROR) | |
1176 { | |
1177 return ngx_http_v2_connection_error(h2c, | |
1178 NGX_HTTP_V2_INTERNAL_ERROR); | |
1179 } | |
1180 | |
1181 stream->recv_window = window; | |
1182 } | |
1183 } | 1149 } |
1184 | 1150 |
1185 ngx_http_run_posted_requests(fc); | 1151 ngx_http_run_posted_requests(fc); |
1186 | 1152 |
1187 } else if (size) { | 1153 } else if (size) { |
4261 | 4227 |
4262 if (size == 0 && last) { | 4228 if (size == 0 && last) { |
4263 rb->rest = 0; | 4229 rb->rest = 0; |
4264 } | 4230 } |
4265 | 4231 |
4266 if (r->request_body_no_buffering && !flush) { | 4232 if (size == 0) { |
4267 break; | 4233 break; |
4268 } | 4234 } |
4269 | 4235 } |
4270 /* pass buffer to request body filter chain */ | 4236 |
4271 | 4237 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, |
4238 "http2 request body rest %O", rb->rest); | |
4239 | |
4240 if (flush) { | |
4272 rc = ngx_http_v2_filter_request_body(r); | 4241 rc = ngx_http_v2_filter_request_body(r); |
4273 | 4242 |
4274 if (rc != NGX_OK) { | 4243 if (rc != NGX_OK) { |
4275 return rc; | 4244 return rc; |
4276 } | 4245 } |
4277 | 4246 } |
4278 if (rb->rest == 0) { | |
4279 break; | |
4280 } | |
4281 | |
4282 if (size == 0) { | |
4283 break; | |
4284 } | |
4285 } | |
4286 | |
4287 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, | |
4288 "http2 request body rest %O", rb->rest); | |
4289 | 4247 |
4290 if (rb->rest == 0 && rb->last_saved) { | 4248 if (rb->rest == 0 && rb->last_saved) { |
4291 break; | 4249 break; |
4292 } | 4250 } |
4293 | 4251 |
4294 if (size == 0) { | 4252 if (size == 0) { |
4295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 4253 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
4296 ngx_add_timer(fc->read, clcf->client_body_timeout); | 4254 ngx_add_timer(fc->read, clcf->client_body_timeout); |
4297 | 4255 |
4298 if (r->request_body_no_buffering) { | 4256 if (!flush) { |
4299 if (!flush) { | 4257 ngx_post_event(fc->read, &ngx_posted_events); |
4300 ngx_post_event(fc->read, &ngx_posted_events); | |
4301 } | |
4302 | |
4303 return NGX_AGAIN; | |
4304 } | 4258 } |
4305 | 4259 |
4306 return NGX_AGAIN; | 4260 return NGX_AGAIN; |
4307 } | 4261 } |
4308 } | 4262 } |
4464 ngx_http_finalize_request(r, rc); | 4418 ngx_http_finalize_request(r, rc); |
4465 return; | 4419 return; |
4466 } | 4420 } |
4467 | 4421 |
4468 if (rc == NGX_OK) { | 4422 if (rc == NGX_OK) { |
4423 return; | |
4424 } | |
4425 | |
4426 if (r->stream->no_flow_control) { | |
4469 return; | 4427 return; |
4470 } | 4428 } |
4471 | 4429 |
4472 if (r->request_body->rest == 0) { | 4430 if (r->request_body->rest == 0) { |
4473 return; | 4431 return; |