ããã«ã¡ã¯ãSustain ãã¼ã ã®å±±å£ã§ãã
ä»ãµã¤ãã¦ãºãªã¢ã¼ããµã¼ãã¹ã¨ããVPNã»ä¸ç¶ãµã¼ãã¹ã§ä½¿ç¨ãã L7LB ã nginx ã«ç§»è¡ãããã¨ãããã調æ»ããã¦ãã¾ãã
nginx ããªãã¼ã¹ãããã·ã¨ãã¦ä½¿ç¨ããéã«å°ã é害ã¨ãªãåä½ããããããã«é¢ããã¢ãããã¼ããæè¿ãã£ãã®ã§ãä»åã¯ãã®ã話ã§ãã
3è¡ã§åããæ¬è¨äºã®å 容
- nginx ããªãã¼ã¹ãããã·ã¨ãã¦ä½¿ãå ´åããªã¯ã¨ã¹ããããã¯ã¨ã³ããµã¼ãã«äºéã§é£ã¶å¯è½æ§ããã
- 対çã¨ã㦠proxy_request_buffering off ã使ãããã ãã使ããªã
- nginx 1.9.13 ã§ä»æ§å¤æ´ãå ¥ããPOST, LOCK, PATCH ã¡ã½ããã®ãªã¯ã¨ã¹ãã¯äºéã§é£ã°ãªããã¨ãä¿è¨¼ããã
nginx ã®ååç㪠health check ã¨ãªã¯ã¨ã¹ãã®ãªãã©ã¤åä½
nginx ã¯ãªãã¼ã¹ãããã·ã¨ãã¦ä½¿ãå ´åã«ãããã¯ã¨ã³ããµã¼ãã®çå確èªæ段ã¨ãã¦åºæ¬çã«ååç㪠health check ãæ¡ç¨ãã¦ãã¾ãã
nginx ã¯ããã¯ã¨ã³ããµã¼ãã®çå確èªãèªåããã¯è¡ãã¾ãããã¯ã©ã¤ã¢ã³ãããæ¥ããªã¯ã¨ã¹ããè¨å®ãããããã¯ã¨ã³ããµã¼ãã«éã£ã¦ã¬ã¹ãã³ã¹ãå¾
ã¡ã¾ãã
ã¬ã¹ãã³ã¹ãè¿ã£ã¦ããªãã£ãå ´åãéã£ãå
ã®ããã¯ã¨ã³ããµã¼ããå©ç¨ã§ããªãç¶æ
ã§ããã¨è¦ãªãã¦ãä¸å®æéãã©ã³ã·ã³ã°å¯¾è±¡ããå¤ãã¾ãã
ãã®å ´åããªã¯ã¨ã¹ãèªä½ã¯å¥ã®ããã¯ã¨ã³ããµã¼ãã«éããªãããã¨ã§ã¬ã¹ãã³ã¹ãå¾ãããããã«ãã¦ãã¾ãããã®éããªããåä½ããªãã©ã¤ã¨å¼ãã§ãã¾ãã
ä¾ãã° upstream ã«ä»¥ä¸ã®ãããªè¨å®ãããå ´åã
upstream backend_server { server backend_a; server backend_b; }
- ãªã¯ã¨ã¹ãã nginx ãåãä»ãã
- nginx ã backend_a(ããã㯠backend_b)ã«ãªã¯ã¨ã¹ããéä¿¡ãã
- error/timeout ãªã©ã§ backend_a ããã¬ã¹ãã³ã¹ãå¾ãããªãå ´å㯠backend_b ã¸ãªã¯ã¨ã¹ãããªãã©ã¤ãã
- backend_a ã¯ãã©ã³ã·ã³ã°å¯¾è±¡ããå¤ãã¦ãã
- backend_b ããè¿ã£ã¦ããã¬ã¹ãã³ã¹ãã¯ã©ã¤ã¢ã³ãã«è¿ã
- ãããã¹ã¦ã®ããã¯ã¨ã³ããµã¼ããã ãã ã£ãå ´åã¯ã502/504 ãè¿ã
ã¨ããåä½ããã¾ãã
ãªãã©ã¤ã®åé¡ç¹ : ãªã¯ã¨ã¹ããäºéã«éããã¦ãã¾ãå¯è½æ§
ãã ããã®å ´åã
- ããã¯ã¨ã³ããµã¼ãã§ãªã¯ã¨ã¹ãã®å¦çã«æéãããã£ã
- proxy_read_timeout ãªã©
- å¦çã¯çµãã£ã¦ããã®ã« nginx ã«ã¬ã¹ãã³ã¹ãè¿ããªãã£ã
- ã¬ã¹ãã³ã¹åä¿¡ä¸ã®ã¨ã©ã¼ãªã©
ãªã©ã§ã nginx ããªãã©ã¤ãã¦ãã¾ããåããªã¯ã¨ã¹ããè¤æ°åããã¯ã¨ã³ããµã¼ãã«å±ãå¯è½æ§ãããã¾ãã
error
an error occurred while establishing a connection with the server, passing a request to it, or reading the response header;timeout
a timeout has occurred while establishing a connection with the server, passing a request to it, or reading the response header;
nginx ã§ã¯ connection æã® error/timeoutããªã¯ã¨ã¹ãéä¿¡æã® error/timeoutãã¬ã¹ãã³ã¹èªã¿è¾¼ã¿æã® error/timeout ãåºå¥ããæ¹æ³ããªããããä¸è¨ã®ãããªåé¡ãèµ·ããã¾ãã
ããã¶ãåããææããã¦ããåé¡ãªã®ã§ããããªããªãæ¹åããã¾ããã§ããã
äºéãªã¯ã¨ã¹ã㯠proxy_request_buffering off ã§ã¯é²ããªã
1.9.12 以åã®å ´åããããé²ãããã«ä½ãè¯ãè¨å®ã¯ãªããã¨ããã¥ã¡ã³ããæ¢ãã¨ç®ã«ã¤ãã®ã¯ä»¥ä¸ã®è¨å®ã§ã¯ãªããã¨æãã¾ãã
When buffering is disabled, the request body is sent to the proxied server immediately as it is received. In this case, the request cannot be passed to the next server if nginx already started sending the request body.
ãªã¯ã¨ã¹ãããã£ã®éä¿¡ãå§ã¾ã£ãå¾ãªããªã¯ã¨ã¹ãã¯ãªãã©ã¤ã§ããªãï¼ï¼
GET ã¯ã ãªã§ããªã¯ã¨ã¹ãããã£ããããªã¯ã¨ã¹ãã¯ãªãã©ã¤ããªãããã«åºæ¥ãã¨ï¼ï¼
åªçã§ãªã POST ãªã¯ã¨ã¹ããäºéãªã¯ã¨ã¹ãã«ãªããªãã®ãä¿è¨¼ã§ããã®ãªããã¨ã¦ããããããï¼
â¦ã¨ä¸è¦ããããã«è¦ãã¾ãããçµè«ããè¨ãã¨æ®å¿µãªãããã®è¨å®ã§ã¯äºéãªã¯ã¨ã¹ããå®å ¨ã«é²ããã¨ã¯ã§ãã¾ããã 確ãã«ãªã¯ã¨ã¹ãããããã¡ãªã³ã°ãããªãå ´åã¯ãªãã©ã¤ããªãã¨ããã®ã¯ããã¥ã¡ã³ãéããªã®ã§ãããå¼·å¶çã«ãããã¡ãªã³ã°ãã¦ãã¾ãå ´åãåå¨ããããã§ãã
ä¾ãã°ãªã¯ã¨ã¹ãããã£ã preread ã§èªã¿åãããããªå°ããªãªã¯ã¨ã¹ãããã£ã®ãªã¯ã¨ã¹ãã®å ´åã¯ãrequest buffering ãå¼·å¶çã« on ã«ãªãã¾ãã (=proxy_request_buffering offãç¡å¹ã«ãªã)
該å½ç®æã¯ããã§ãã
if (rb->rest == 0) { /* the whole request body was pre-read */ ... r->request_body_no_buffering = 0; post_handler(r); return NGX_OK; }
ä»ã«ã proxy_request_buffering ãå¼·å¶çã« on ã«ãªãæ¡ä»¶ãããã¤ãããã¾ãã
- chunked-transfer-encoding ãªãªã¯ã¨ã¹ãã«å¯¾ãã¦ãããã¯ã¨ã³ããµã¼ãã¸ã®é信㧠HTTP/1.1 ã§ã¯ãªãå ´å
- HTTP/2 ãæå¹ãªå ´å
- nginx 1.9.14 㧠HTTP/2 ã§ã proxy_request_buffering off ãæå¹åããããã«ãªãã¾ãã
- Content-Length ãããããªããã㤠chunked-transfer-encoding ã§ããªãå ´å
- proxy_set_body ããã㯠proxy_pass_request_body ã off ã®å ´å
- ããããããããæå¹ã«ããå ´åã« request_buffering ã off ã«ããå¿ è¦ããã®ãã¨ãã話ã§ããã
ãªã©ã§ãã(å¤åä»ã«ãã¾ã ããã¾ã)
proxy_request_buffering ã on ã«ãªã£ãå ´åã¯å¾æ¥éãã®åä½ã¨ãªããçµæã¨ãã¦ãªã¯ã¨ã¹ãéä¿¡å/å¾ã®ã©ã¡ãã§ããªãã©ã¤ã«ããäºéãªã¯ã¨ã¹ããçºçãã¦ãã¾ãã¾ãã
proxy_request_buffering ãäºéãªã¯ã¨ã¹ãé»æ¢ã®ããã«è¨å®ããã®ã«ã¯ä¾å¤ãå¤ããããã¦ãããæ¹ãããããã§ãã
ä»ã«ã upstream_connect_time ã Lua ã§æ¯è¼ãããproxy_connect_timeout ã調æ´ãããªã©ãæ¤è¨ãã¾ããããçµå±ã®ã¨ãã nginx 1.9.12 以ä¸ã§ãªãã©ã¤åä½ãå®å ¨ã«å¶éãããã¨ã¯ã§ãã¾ããã¨ããçµè«ã«è³ãã¾ããã
1.9.13 ã§ã®ãªãã©ã¤ã®ä»æ§å¤æ´
1.9.13 (ãã mainline-1.9.15 ã¾ã§åºã¦ã¾ãããstable-1.10.0 ã«ãªãã¾ããã) ã§ã¯ UDP ã®ãµãã¼ãã大ããªè©±é¡ã¨ãã¦æãããã¾ãããåæã«ãã®ãã¼ã¸ã§ã³ã§ä¸ã§æ¸ãããªã¯ã¨ã¹ããªãã©ã¤ã®åä½ã«ä»æ§å¤æ´ãå ¥ãã¾ããã
*) Change: non-idempotent requests (POST, LOCK, PATCH) are no longer passed to the next server by default if a request has been sent to a backend; the "non_idempotent" parameter of the "proxy_next_upstream" directive explicitly allows retrying such requests.
åªçã§ã¯ãªãã¡ã½ãã(POST, LOCK, PATCH)ã®ãªã¯ã¨ã¹ãã¯ä¸åº¦ããã¯ã¨ã³ããµã¼ãã«éã£ãããrequest buffering ã®æç¡ã«ããããããªãã©ã¤ããªãããã«ãªãã¾ããã
http://hg.nginx.org/nginx/rev/91c8d990fb45
+ if (u->request_sent + && (r->method & (NGX_HTTP_POST|NGX_HTTP_LOCK|NGX_HTTP_PATCH)))
ãªã¯ã¨ã¹ãéä¿¡å¾ã®ãã©ã°ã¨ POST, LOCK, PATCH ã§ã®æ¡ä»¶æãçµã¾ãã¦ãã¦ããªãã©ã¤ããªãããã«ãªã£ã¦ãã¾ãã
ããã®æç¹ã§ request_sent ã®ãã©ã°ãç«ã£ã¦ããã°ãPOST, LOCK, PATCH ã®ãªã¯ã¨ã¹ãã¯ãªãã©ã¤ããªããããrequet éä¿¡å¾ã¨ãã以å¤ã§åä½ãåãããã¨ãå¯è½ã«ãªãã¾ãã(æ£ç¢ºã«ã¯ãªã¯ã¨ã¹ãããã£ã®éä¿¡åå¾)
- ãªã¯ã¨ã¹ãã nginx ãåãä»ãã
- nginx ã backend_a (ããã㯠backend_b)ã«ãªã¯ã¨ã¹ããéä¿¡ãã
- error/timeout ãªã©ã§ backend_a ããã¬ã¹ãã³ã¹ãå®äºããªãå ´å
- request éä¿¡æ¸ãªã
- POST, LOCK, PATCH 㯠502/504 ãè¿ã
- ãã以å¤ã¯ backend_b ã«ãªãã©ã¤ãã
- request éä¿¡åãªã
- backend_b ã«ãªãã©ã¤ããè¿ã£ã¦ããã¬ã¹ãã³ã¹ãã¯ã©ã¤ã¢ã³ãã«è¿ã
- ãããã¹ã¦ã®ããã¯ã¨ã³ããµã¼ããã ãã ã£ãå ´å㯠502/504 ãè¿ã
- request éä¿¡æ¸ãªã
ããã©ã«ãã®åä½ãå¤ãã£ã¦ãããããéã«1.9.12以åã®ãããªã©ããªã¡ã½ããã§ããªãã©ã¤ããåä½ã«ãããå ´å㯠proxy_next_upstream non_idempotent
ãè¨å®ããå¿
è¦ãããã¾ãã
ãããã«
ä»åã®ä»¶ã¯ä¸æè°ãªä»æ§(ã¨ãããå®è£ )ã§ããªãæ©ã¾ããã¾ããããéããã¢ãããã¼ããå ¥ã£ãã®ã§ä¸ä»¶è½çãã¾ãããç´°ããä¸ã«ãã¾ãèµ·ããªãäºä¾ã§ã¯ããã¾ããããã£ãã調æ»ã»æ¤è¨¼ããä¸ã§éç¨ãã¦ããããã¨æãã¾ãã
ä»åã®ãã®è¨äºãå°ãã§ãçæ§ã®åèã«ãªãã°å¹¸ãã§ãã
åè
- http://nrok81.hatenablog.com/entry/2014/02/20/202919
- http://qiita.com/cubicdaiya/items/0678396f11982e537e2d
注è¨) nginx ã§è½åçã« health check ãã
ããã¯ã¨ã³ããµã¼ããçåãã¦ãããã©ããã®è½åçãªãã«ã¹ãã§ãã¯ãåºæ¥ããªããæ¥ç¶ã§ããããã¯ã¨ã³ããµã¼ãã®ã¿ã«ãªã¯ã¨ã¹ããåé
ã§ããã®ã§ã
proxy_next_upstream error
ãåã£ã¦ãã¾ããã¨ã©ã¼æã®ãªãã©ã¤ã off ã«ãã¦ãã¾ãã°ãããã§å¤§ä¸å¤«ãªã¯ãã§ãã(ææçã® NGINX Plus ã 3rdPartyModule ã使ç¨ããã°ã§ãã¾ã)
ä»åã¯å¥ã®é½åä¸ 3rdPartyModule ã追å ã§ããªãç¶æ³ã§ããã¤ãã¼ã¸ã§ã³ã¢ããã§å¯¾å¿ã§ããããªã®ã§ä¸è¨ã®æ¤è¨¼ã¯è¡ã£ã¦ãã¾ããã
*1:2016/05/09追è¨
proxy_next_upstream ã off ã«ãããã¨ã§ãªãã©ã¤ãã®ãã®ãããªãããã«è¨å®ãããã¨ãã§ãã¾ãã
ãã ããã®è¨å®ã§ã¯ connection error/timeout æããªãã©ã¤ããªããªã£ã¦ãã¾ãã¾ãã
ä¾ãã°ããã¯ã¨ã³ããµã¼ãã®ä¸é¨ããã¦ã³ããæã«ãä»ã«ç¨¼åãã¦ããããã¯ã¨ã³ããµã¼ããããã®ã«ã500 ãè¿ãå ´åãããã¨ããå¥ã®åé¡ãçºçãã¾ãã
ãã®ããä»åã¯ä½¿ç¨ãè¦éãã¾ããã