mod_proxy_httpとmod_proxy_ajpとmod_jk
公開は少し前になりますが、ApacheCon2009での発表の「mod_proxy versus mod_jk」があります。
事情を知らない人のために背景を説明します。
Tomcatの前にApache HTTPサーバ(以下、単にApache)をリバースプロクシサーバとして置くことはよくあります。静的ファイルのパフォーマンスチューニングやセキュリティ設定の容易さが理由としてあります。最近ではロードバランサとしての役割の方が大きいかもしれません。
ApacheとTomcatの間の接続方法として、現状、次の3つの方法が一般的です。
- mod_proxy_http
- mod_proxy_ajp
- mod_jk
この中でデファクト標準的な位置を占めている(占めていた?)のがmod_jkです。
上記の資料にもありますが、mod_jkは混乱の歴史を持っていて、一時期はmod_jkがmod_jk2より新しい、などという変態的な時期もありました。今は落ち着いて、Tomcat Connectorとして次のサイトが配布元になっています。
mod_jkの特徴は、ApacheとTomcatの間の通信プロトコルに独自のAJPという通信プロトコルを使う点です。AJPの仕様は次のようにオープンです(今はバージョン1.3)。
- http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
- http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html
AJPのHTTPと比べた特徴は次のふたつです。
- TCP/IPレベルの接続を維持したまま接続を使いまわす(コネクションプーリング)
- (テキストベースのHTTPに対して)一部、バイナリ化する
mod_jkの動作は、HTTPで受けたリクエストをAJPに変換してTomcatに送り、TomcatからのAJPのレスポンスをHTTPのレスポンスに変換してWebブラウザ(UA)に返すことです。
上記ふたつの特徴でAJPはHTTPより速いことを主張しています。
最初の特徴はHTTPのキープアライブに似ていますが、同じTCP/IP接続を異なるHTTP通信で共有する点が異なります(ただし、ひとつのHTTP通信が使っている間は他のHTTP通信は使えません)。
Apache2.0まで、ApacheとTomcatを接続する方法のもうひとつのデファクト標準がmod_proxy_httpでした。mod_jkと違いmod_proxy_httpはApacheの標準モジュールです。mod_proxy_httpをリバースプロクシとして動作させればmod_jkと同じことができます。mod_proxy_httpは、プロトコル変換をせずに(HTTPのまま)ApacheがTomcatにリクエストを投げてレスポンスを受け取ります。
Apache2.0まで選択基準は簡単でした。標準モジュールのmod_proxy_httpは導入が簡単、一方、非標準モジュールのmod_jkは速度が速い、という基準でした。mod_jkにはロードバランシングの機能もあり、mod_proxy_httpには無かったので、その点でも非標準のmod_jkに分がありました。
Apache2.2で次の3つの変化がありました。
- 標準モジュールmod_proxy_ajpができた
- mod_proxyがロードバランシング機能を持った
- mod_proxy_httpがコネクションプーリングをサポートした
mod_proxy_ajpはその名のとおり通信プロトコルAJPで動作するmod_proxyモジュールです。要はmod_jkの別実装です。しかも標準モジュールです。
話がここで終わればApache2.2での選択基準もまあまあ明解でした。簡単に使えるmod_proxy_http、少し速いmod_proxy_ajp、(実装の枯れで)更に速いかもしれないmod_jk、という位置づけです。
しかしここで問題にしたいのがmod_proxy_httpもコネクションプーリングをするようになった点です。元々、AJPがHTTPより速いと主張していた理由はコネクションプーリングとバイナリ化の2点です。mod_proxy_httpがコネクションプーリングをすると前者の利点は失われます。
後者のバイナリ化はどれほど優位に働くのでしょうか。実は結構微妙です。そもそもHTTPの転送データの中でバイナリ化できるのはヘッダだけです。ボディ部はバイナリ化できません。HTTPのトラフィックで支配的なのはレスポンスのボディ部なので、AJPのバイナリ化の効果には疑問があります。
mod_pxory_httpがコネクションプーリングをして複数のHTTP通信が同じTCP/IP接続を共有できるようになりましたが、Tomcat側がデフォルト60秒でHTTP通信のTCP/IP接続を切ってしまいます(connectionTimeout設定値)。残念ながらデフォルトのTomcatではmod_proxy_httpのコネクションプーリングの効果はあまり高くありません。
AJPの場合、Tomcat側がデフォルトでTCP/IP接続を切りません。
Tomcat側のHTTPコネクタのconnectionTimeout値を充分に長くすれば、AJPとほぼ同じ動作になります。
HTTPのコネクションプーリングは、しょせんTCPの3way handshakeを省略できるだけなので、多くの場合は誤差の範囲かもしれません。
そんな背景の元、結局、mod_proxyとmod_jkの性能はどうなんだ、というのが冒頭の資料です。が、グラフの縦軸の意味が微妙です。結局、ほとんど差がないように見えます。mod_proxy_httpの方がAJP版ふたつよりスケールするようにすら読めます。
世間的には今でもmod_jkを勧めるのが一般的ですが個人的には、Apache2.2以降、ApacheとTomcatの接続はmod_proxy_httpが良いと思っています。
fyi, 他のベンチマーク:
mod_proxy_ajpが一番速いと結論づけています。TomcatがApacheより速い、と結論づけているぐらいなので信用度は微妙ですが。コネクタの違いは誤差の気がします。速度の差が誤差の範囲内なら問題切り分けの容易さからmod_proxy_httpが推奨です。
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/tomcat-apache/tbping
Re:mod_proxy_httpとmod_proxy_ajpとmod_jk
ものすごいバイアスかかってますね。
Re:mod_proxy_httpとmod_proxy_ajpとmod_jk