Upstream: limited next_upstream time and tries (ticket #544).
The new directives {proxy,fastcgi,scgi,uwsgi,memcached}_next_upstream_tries
and {proxy,fastcgi,scgi,uwsgi,memcached}_next_upstream_timeout limit
the number of upstreams tried and the maximum time spent for these tries
when searching for a valid upstream.
Roman Arutyunyan
7 years ago
41 | 41 | ngx_str_t *name; |
42 | 42 | |
43 | 43 | ngx_uint_t tries; |
44 | ngx_msec_t start_time; | |
44 | 45 | |
45 | 46 | ngx_event_get_peer_pt get; |
46 | 47 | ngx_event_free_peer_pt free; |
441 | 441 | offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream), |
442 | 442 | &ngx_http_fastcgi_next_upstream_masks }, |
443 | 443 | |
444 | { ngx_string("fastcgi_next_upstream_tries"), | |
445 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
446 | ngx_conf_set_num_slot, | |
447 | NGX_HTTP_LOC_CONF_OFFSET, | |
448 | offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_tries), | |
449 | NULL }, | |
450 | ||
451 | { ngx_string("fastcgi_next_upstream_timeout"), | |
452 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
453 | ngx_conf_set_msec_slot, | |
454 | NGX_HTTP_LOC_CONF_OFFSET, | |
455 | offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_timeout), | |
456 | NULL }, | |
457 | ||
444 | 458 | { ngx_string("fastcgi_param"), |
445 | 459 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, |
446 | 460 | ngx_http_upstream_param_set_slot, |
2313 | 2327 | |
2314 | 2328 | conf->upstream.store = NGX_CONF_UNSET; |
2315 | 2329 | conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
2330 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; | |
2316 | 2331 | conf->upstream.buffering = NGX_CONF_UNSET; |
2317 | 2332 | conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
2318 | 2333 | |
2321 | 2336 | conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
2322 | 2337 | conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
2323 | 2338 | conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
2339 | conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; | |
2324 | 2340 | |
2325 | 2341 | conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
2326 | 2342 | conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
2386 | 2402 | ngx_conf_merge_uint_value(conf->upstream.store_access, |
2387 | 2403 | prev->upstream.store_access, 0600); |
2388 | 2404 | |
2405 | ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, | |
2406 | prev->upstream.next_upstream_tries, 0); | |
2407 | ||
2389 | 2408 | ngx_conf_merge_value(conf->upstream.buffering, |
2390 | 2409 | prev->upstream.buffering, 1); |
2391 | 2410 | |
2403 | 2422 | |
2404 | 2423 | ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
2405 | 2424 | prev->upstream.read_timeout, 60000); |
2425 | ||
2426 | ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, | |
2427 | prev->upstream.next_upstream_timeout, 0); | |
2406 | 2428 | |
2407 | 2429 | ngx_conf_merge_size_value(conf->upstream.send_lowat, |
2408 | 2430 | prev->upstream.send_lowat, 0); |
100 | 100 | NGX_HTTP_LOC_CONF_OFFSET, |
101 | 101 | offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), |
102 | 102 | &ngx_http_memcached_next_upstream_masks }, |
103 | ||
104 | { ngx_string("memcached_next_upstream_tries"), | |
105 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
106 | ngx_conf_set_num_slot, | |
107 | NGX_HTTP_LOC_CONF_OFFSET, | |
108 | offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_tries), | |
109 | NULL }, | |
110 | ||
111 | { ngx_string("memcached_next_upstream_timeout"), | |
112 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
113 | ngx_conf_set_msec_slot, | |
114 | NGX_HTTP_LOC_CONF_OFFSET, | |
115 | offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_timeout), | |
116 | NULL }, | |
103 | 117 | |
104 | 118 | { ngx_string("memcached_gzip_flag"), |
105 | 119 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
582 | 596 | */ |
583 | 597 | |
584 | 598 | conf->upstream.local = NGX_CONF_UNSET_PTR; |
599 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; | |
585 | 600 | conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
586 | 601 | conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
587 | 602 | conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
603 | conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; | |
588 | 604 | |
589 | 605 | conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
590 | 606 | |
618 | 634 | ngx_conf_merge_ptr_value(conf->upstream.local, |
619 | 635 | prev->upstream.local, NULL); |
620 | 636 | |
637 | ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, | |
638 | prev->upstream.next_upstream_tries, 0); | |
639 | ||
621 | 640 | ngx_conf_merge_msec_value(conf->upstream.connect_timeout, |
622 | 641 | prev->upstream.connect_timeout, 60000); |
623 | 642 | |
626 | 645 | |
627 | 646 | ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
628 | 647 | prev->upstream.read_timeout, 60000); |
648 | ||
649 | ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, | |
650 | prev->upstream.next_upstream_timeout, 0); | |
629 | 651 | |
630 | 652 | ngx_conf_merge_size_value(conf->upstream.buffer_size, |
631 | 653 | prev->upstream.buffer_size, |
503 | 503 | NGX_HTTP_LOC_CONF_OFFSET, |
504 | 504 | offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), |
505 | 505 | &ngx_http_proxy_next_upstream_masks }, |
506 | ||
507 | { ngx_string("proxy_next_upstream_tries"), | |
508 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
509 | ngx_conf_set_num_slot, | |
510 | NGX_HTTP_LOC_CONF_OFFSET, | |
511 | offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_tries), | |
512 | NULL }, | |
513 | ||
514 | { ngx_string("proxy_next_upstream_timeout"), | |
515 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
516 | ngx_conf_set_msec_slot, | |
517 | NGX_HTTP_LOC_CONF_OFFSET, | |
518 | offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout), | |
519 | NULL }, | |
506 | 520 | |
507 | 521 | { ngx_string("proxy_pass_header"), |
508 | 522 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
2454 | 2468 | |
2455 | 2469 | conf->upstream.store = NGX_CONF_UNSET; |
2456 | 2470 | conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
2471 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; | |
2457 | 2472 | conf->upstream.buffering = NGX_CONF_UNSET; |
2458 | 2473 | conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
2459 | 2474 | |
2462 | 2477 | conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
2463 | 2478 | conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
2464 | 2479 | conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
2480 | conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; | |
2465 | 2481 | |
2466 | 2482 | conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
2467 | 2483 | conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
2542 | 2558 | ngx_conf_merge_uint_value(conf->upstream.store_access, |
2543 | 2559 | prev->upstream.store_access, 0600); |
2544 | 2560 | |
2561 | ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, | |
2562 | prev->upstream.next_upstream_tries, 0); | |
2563 | ||
2545 | 2564 | ngx_conf_merge_value(conf->upstream.buffering, |
2546 | 2565 | prev->upstream.buffering, 1); |
2547 | 2566 | |
2559 | 2578 | |
2560 | 2579 | ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
2561 | 2580 | prev->upstream.read_timeout, 60000); |
2581 | ||
2582 | ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, | |
2583 | prev->upstream.next_upstream_timeout, 0); | |
2562 | 2584 | |
2563 | 2585 | ngx_conf_merge_size_value(conf->upstream.send_lowat, |
2564 | 2586 | prev->upstream.send_lowat, 0); |
297 | 297 | NGX_HTTP_LOC_CONF_OFFSET, |
298 | 298 | offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream), |
299 | 299 | &ngx_http_scgi_next_upstream_masks }, |
300 | ||
301 | { ngx_string("scgi_next_upstream_tries"), | |
302 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
303 | ngx_conf_set_num_slot, | |
304 | NGX_HTTP_LOC_CONF_OFFSET, | |
305 | offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_tries), | |
306 | NULL }, | |
307 | ||
308 | { ngx_string("scgi_next_upstream_timeout"), | |
309 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
310 | ngx_conf_set_msec_slot, | |
311 | NGX_HTTP_LOC_CONF_OFFSET, | |
312 | offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_timeout), | |
313 | NULL }, | |
300 | 314 | |
301 | 315 | { ngx_string("scgi_param"), |
302 | 316 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, |
1073 | 1087 | |
1074 | 1088 | conf->upstream.store = NGX_CONF_UNSET; |
1075 | 1089 | conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
1090 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; | |
1076 | 1091 | conf->upstream.buffering = NGX_CONF_UNSET; |
1077 | 1092 | conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
1078 | 1093 | |
1081 | 1096 | conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
1082 | 1097 | conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
1083 | 1098 | conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
1099 | conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; | |
1084 | 1100 | |
1085 | 1101 | conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
1086 | 1102 | conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
1141 | 1157 | ngx_conf_merge_uint_value(conf->upstream.store_access, |
1142 | 1158 | prev->upstream.store_access, 0600); |
1143 | 1159 | |
1160 | ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, | |
1161 | prev->upstream.next_upstream_tries, 0); | |
1162 | ||
1144 | 1163 | ngx_conf_merge_value(conf->upstream.buffering, |
1145 | 1164 | prev->upstream.buffering, 1); |
1146 | 1165 | |
1158 | 1177 | |
1159 | 1178 | ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
1160 | 1179 | prev->upstream.read_timeout, 60000); |
1180 | ||
1181 | ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, | |
1182 | prev->upstream.next_upstream_timeout, 0); | |
1161 | 1183 | |
1162 | 1184 | ngx_conf_merge_size_value(conf->upstream.send_lowat, |
1163 | 1185 | prev->upstream.send_lowat, 0); |
352 | 352 | NGX_HTTP_LOC_CONF_OFFSET, |
353 | 353 | offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream), |
354 | 354 | &ngx_http_uwsgi_next_upstream_masks }, |
355 | ||
356 | { ngx_string("uwsgi_next_upstream_tries"), | |
357 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
358 | ngx_conf_set_num_slot, | |
359 | NGX_HTTP_LOC_CONF_OFFSET, | |
360 | offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries), | |
361 | NULL }, | |
362 | ||
363 | { ngx_string("uwsgi_next_upstream_timeout"), | |
364 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
365 | ngx_conf_set_msec_slot, | |
366 | NGX_HTTP_LOC_CONF_OFFSET, | |
367 | offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout), | |
368 | NULL }, | |
355 | 369 | |
356 | 370 | { ngx_string("uwsgi_param"), |
357 | 371 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23, |
1253 | 1267 | |
1254 | 1268 | conf->upstream.store = NGX_CONF_UNSET; |
1255 | 1269 | conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
1270 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; | |
1256 | 1271 | conf->upstream.buffering = NGX_CONF_UNSET; |
1257 | 1272 | conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
1258 | 1273 | |
1261 | 1276 | conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
1262 | 1277 | conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
1263 | 1278 | conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
1279 | conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC; | |
1264 | 1280 | |
1265 | 1281 | conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
1266 | 1282 | conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
1328 | 1344 | ngx_conf_merge_uint_value(conf->upstream.store_access, |
1329 | 1345 | prev->upstream.store_access, 0600); |
1330 | 1346 | |
1347 | ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries, | |
1348 | prev->upstream.next_upstream_tries, 0); | |
1349 | ||
1331 | 1350 | ngx_conf_merge_value(conf->upstream.buffering, |
1332 | 1351 | prev->upstream.buffering, 1); |
1333 | 1352 | |
1345 | 1364 | |
1346 | 1365 | ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
1347 | 1366 | prev->upstream.read_timeout, 60000); |
1367 | ||
1368 | ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout, | |
1369 | prev->upstream.next_upstream_timeout, 0); | |
1348 | 1370 | |
1349 | 1371 | ngx_conf_merge_size_value(conf->upstream.send_lowat, |
1350 | 1372 | prev->upstream.send_lowat, 0); |
697 | 697 | return; |
698 | 698 | } |
699 | 699 | |
700 | u->peer.start_time = ngx_current_msec; | |
701 | ||
702 | if (u->conf->next_upstream_tries | |
703 | && u->peer.tries > u->conf->next_upstream_tries) | |
704 | { | |
705 | u->peer.tries = u->conf->next_upstream_tries; | |
706 | } | |
707 | ||
700 | 708 | ngx_http_upstream_connect(r, u); |
701 | 709 | } |
702 | 710 | |
3420 | 3428 | ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, |
3421 | 3429 | ngx_uint_t ft_type) |
3422 | 3430 | { |
3431 | ngx_msec_t timeout; | |
3423 | 3432 | ngx_uint_t status, state; |
3424 | 3433 | |
3425 | 3434 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
3489 | 3498 | |
3490 | 3499 | if (status) { |
3491 | 3500 | u->state->status = status; |
3492 | ||
3493 | if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) { | |
3494 | ||
3501 | timeout = u->conf->next_upstream_timeout; | |
3502 | ||
3503 | if (u->peer.tries == 0 | |
3504 | || !(u->conf->next_upstream & ft_type) | |
3505 | || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) | |
3506 | { | |
3495 | 3507 | #if (NGX_HTTP_CACHE) |
3496 | 3508 | |
3497 | 3509 | if (u->cache_status == NGX_HTTP_CACHE_EXPIRED |
135 | 135 | ngx_msec_t send_timeout; |
136 | 136 | ngx_msec_t read_timeout; |
137 | 137 | ngx_msec_t timeout; |
138 | ngx_msec_t next_upstream_timeout; | |
138 | 139 | |
139 | 140 | size_t send_lowat; |
140 | 141 | size_t buffer_size; |
152 | 153 | ngx_uint_t ignore_headers; |
153 | 154 | ngx_uint_t next_upstream; |
154 | 155 | ngx_uint_t store_access; |
156 | ngx_uint_t next_upstream_tries; | |
155 | 157 | ngx_flag_t buffering; |
156 | 158 | ngx_flag_t pass_request_headers; |
157 | 159 | ngx_flag_t pass_request_body; |