2011年8月7日日曜日

痒いところに手が届かないnginxのHttpLimitReqModuleさん

軽くて早いと巷で評判のリバースプロキシサーバnginxですが、
標準で連続リクエストを制御する機能がついているのもまた魅力の一つです。

 nginxのHttpLimitReqModuleを試してみる | tech.kayac.com - KAYAC engineers' blog

こちらで詳しく紹介されているHttpLimitReqModuleを利用することで、任意のURLに対して1秒あたり/1分あたりに何リクエストまでしか処理しません、という制御が設定ひとつで出来てしまいます。例えば公開しているAPIのURLがあって、もちろん使って欲しいのだけどDOS攻撃みたいなのは困るわ...みたいな時に安心です。なお、リクエストが溢れた場合に速攻で503レスポンスを返すのか、ある程度は「処理待ち」としてキューに貯めるのか(burst対策)というのも設定一つです。ここまでの機能をアプリケーション側で実装するとなると結構な手間ですしね。

という訳で、制御をかけるURLの範囲や、制御の条件(何req/sec or min)をさらさらとシンプルなnginxのconfファイルに書けばいい感じにしてくれるHttpLimitReqModuleさん、こいつはすげえや、ということで丁度案件的にこの機能が欲しかった自分は飛びついたのですが一つだけ困ったところがありました。

HttpLimitReqModuleは、「sec/minあたりのリクエスト数」の上限を制御することはできても「受付可能な最大コネクション数」は制御できないのです。

とある処理の重い(レスポンスするのにどうしても数秒かかるような)APIがあったとしましょう。重い処理のAPIなので、連続で処理依頼されてもさばけません、最大で処理可能な件数を仮に10処理とします。もうおわかりかと思いますが、HttpLimitReqModuleは1秒/分あたりに何リクエストまで、を制御するモジュールですので、仮に1秒あたり10reqまで受け付けるような設定にしても最初の1秒で10req受け付けて次の秒ではまた10reqまで受け付けてしまいます。。だったら設定値を調整して巧いことやれよ、とか言われそうですがAPIの処理速度が状況によって読めない場合は途方にくれてしまいます。

んだばどうしたもんか。と数分悩んだらすぐに見つかりました。

こちらも標準モジュールのHttpLimitZoneModuleさん。というかこちらの方がnginxに昔からあったモジュールのようです。ここの「limit_conn」で最大コネクション数を制御することができました(ただしこちらはburstの制御ができないので溢れたリクエストは速攻で503になってしまいますが)。

ということで、細かいところは下記リンクの説明にお任せします。

---
nginx.org (公式サイト)
wiki.nginx.org/Modules (nginx module一覧)

HttpLimitReqModule
HttpLimitZoneModule

0 件のコメント:

コメントを投稿