TomcatやJBossでHTTPリクエスト単位で並行実行数を制限するサーブレットフィルタ
WebLogicからの移行とかで、HTTPリクエスト単位で流量制御などの目的で並行実行数を制限したいという要望がたまにある。WebLogicではWork Managerというのがあって、これがHTTPリクエスト単位での設定なのだそうだ。
TomcatやJBossではApache httpdのMaxClientsと同じく、リクエスト単位ではなくクライアント単位(ソケット単位)でスレッドを割り当てる。このモデルでは、例えばmaxThreads="20"とかにしたら常に同時に20個のリクエストをさばいてくれる、という仮定は成り立たない。クライアントがkeep aliveで接続している間はスレッドも待ち続けるので、21番目のリクエストは先に接続した20のクライアントがkeep aliveを終了してコネクションを切断するまで処理されない。MaxClientsは名前の通りMaxClientsなのであってMaxConcurrentRequestsではない、ということだ。
というわけでスレッド割り当てモデルに左右されずにMaxConcurrentRequestsを実現するものをサーブレットフィルタで簡単に書いてみる。
単なるサンプルなので安直な実装にしてる。Semaphore使っただけでロジックと呼べるようなものはほとんど無いのだけど。
あとは設定を細かくできるようにしたり、読みやすい設定ファイルにしたりするとそこそこ使えるんじゃないか。例えば以下のような設定ができるようにするとか。
- A機能30並行リクエスト、20ブロッキング可能
- B機能50並行リクエスト、30ブロッキング可能
- C機能70並行リクエスト、40ブロッキング可能
- A, B, C全部合わせて最大で100並行リクエストおよび50ブロッキング可能
実は上のユースケースはこのサンプルで書いたサーブレットフィルタそのままでも実現できるけど、web.xmlにこの設定をモリモリ書いたらたぶん読み書きしにくいので独自の設定ファイルにしたほうが良い。
あと、TomcatやJBoss ASにはSemaphoreValveというこれと同じようなコンテナプラグインがあるのだけど、これを使ってしまうとポータビリティが失われるので今回紹介したようにFilterで実装するほうが良いと思う。
きちんとしたSIerさんはこういうようなセッションサイズ測ったりユーザのトラッキングしてくれたりミドルウェアに機能付加するようないろいろなサーブレットフィルタのライブラリを持っていると思うんだけど、オープンソースで公開されてたりするものはないだろうか?