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;