noob

底辺オペレーターのメモ

nginxのproxy_read_timeoutはupstreamにも注意

proxy_read_timeoutが思ったような挙動ではなかったので実験してみた.

想定していた挙動

こんな設定のnginxに対して

upstream server_pool_a {
    server web001:80 max_fails=3 fail_timeout=30s;
    server web002:80 max_fails=3 fail_timeout=30s;
}

proxy_read_timeout 60

無限ループするようなCGIをプロキシさせたら

web001にリクエスト
↓
60秒以内にレスポンスが完了しない
↓
504 Gateway Time-out 発生

となると思っていた.

実際の挙動

ところが実際には以下のような挙動だった.

web001にリクエスト
↓
60秒以内にレスポンスが完了しない
↓
web002にリクエスト
↓
60秒以内にレスポンスが完了しない
↓
504 Gateway Time-out 発生

upstream先のサーバでwhileしてプロセスの状況をみてみた.
web001にリクエストして60秒(proxy_read_timeout)後にweb002にもリクエストしていることがわかる.

  • web001
*** 前略 ***

2014年  2月 20日 木曜日 19:33:24 JST

2014年  2月 20日 木曜日 19:33:25 JST
10000    26423 20501  0 19:33 ?        00:00:00 /usr/local/bin/perl chk_loop.cgi

*** 後略 ***
  • web002
*** 前略 ***

2014年  2月 20日 木曜日 19:34:23 JST

2014年  2月 20日 木曜日 19:34:24 JST
10000    29708 25141  0 19:34 ?        00:00:00 /usr/local/bin/perl chk_loop.cgi

*** 後略 ***

まとめ

  • proxy_read_timeoutに設定した時間が経過した後,upstreamに他のサーバがいるときは順にリクエストを投げていく.
  • upstreamにあるサーバに順にリクエストしていき,すべてのサーバでproxy_read_timeoutした時にようやく504 Gateway Time-outが発生する.
  • 処理が終わるまで動き続けるようなCGIだと当然リクエスト先で動き続けることになるので注意.
    • また,1リクエストだと思っていたものが実際は複数リクエストになってしまっていて,意図しないリクエストが発生していることにも注意.
      • upstream先でCGIが確実にタイムアウト(強制終了)するようにして,それより長いproxy_read_timeoutを設定するとよいかも?