mod_proxy_ajp

※この記事は以前のブログからの転載です。

結構前の話なんだけど、
Apache 2.2 から mod_proxy_ajp が組み込まれました。
これは TomcatApache を連携するものです。

Apache 2.2.0 は怖いので使っていなかったのですが、
Apache 2.2 もバージョンが進んだので使ってみることにしました。
--enable-proxy 付きでコンパイルして

<Location /hoge/>
    ProxyPass /hoge/ ajp://localhost:8009/hoge/
</Location>

とすることで /hoge/ へのアクセスをTomcatへ渡せます。

だがしかし、これでは静的コンテンツもTomcatに渡してしまい、
連携するメリットがあんまり感じられない。
↑(アクセス制御とかそれらの面は別として、パフォーマンスの面で)

Tomcat に渡すものは動的コンテンツのみであるのが望ましいので
/servlet/* は

ProxyPass /servlet/ ajp://localhost:8009/servlet/

とすることで渡すことができます。

問題はjspです。
jspだけを渡すことができません。
いや、できないというのは言い過ぎでできないこともないです。

mod_rewrite を使って

RewriteEngine On
RewriteCond %{REQUEST_URI} (.*).jsp(.*)
RewriteRule ^/(.*) ajp://localhost:8009/$1 [P]

とやると、一応できます。

これでOKだと思うのは早計です。
ここでパフォーマンスをチェックしてみます。
感覚的に上のjspの処理は遅そうなので。

早速パフォーマンスを測定してみます。

実行したソースは、

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class test extends HttpServlet{
    private static final String CONTENT_TYPE = "text/html; charset=windows-31j";
    private static final SimpleDateFormat formatter
      = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws
      ServletException, IOException{
        response.setContentType(CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        out.println(formatter.format(new Date()));
    }
}
<%@ page contentType="text/html; charset=windows-31j" %>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<%!
private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
%>
<%= formatter.format(new Date()) %>


こんな感じの単純なものです。

ab -n 1000 -c 64 http://hostname/test.jsp
ab -n 1000 -c 64 http://hostname/servlet/test

にて測定しました。

測定結果は以下のようになりました。

mod_proxy_ajp + mod_rewrite - jsp
Requests per second: 241.78 [#/sec]
 
mod_proxy_ajp + mod_rewrite - servlet
Requests per second: 1174.78 [#/sec]
 
mod_jk - jsp
Requests per second: 1097.32 [#/sec]
 
mod_jk - servlet
Requests per second: 1174.78 [#/sec]


うわぁ・・・mod_proxy_ajp + mod_rewrite - jspの処理・・すごく遅いナリ・・・

大体予想通りなのですが、
mod_proxy_ajp - jsp はやはり mod_rewrite を通して行っているので、
とても遅いです。
connection pooling も使えません。

でもこのまま終わるのは悔しいので試行錯誤してみました。

jsp の処理を mod_rewrite を使用することにより、
パフォーマンスが低下してしまうことに関しての
解決策を見つけました。

そもそもjspの処理が遅くなっていた原因は、
mod_rewriteを使用することにより、
mod_proxy_ajp からの、バックエンドサーバへのコネクションが、
再利用されないところにあると考えました。

そこで、再利用の処理を、
mod_proxy_balancer にやってもらおうと言うわけです。

<Proxy balancer://ajp-balancer> 
    BalancerMember ajp://localhost:8009
</Proxy>
ProxyPass /servlet/ balancer://ajp-balancer/servlet/
RewriteRule ^/(.+).jsp(.+)? balancer://ajp-balancer/$1.jsp$2 [P,L]


こんな処理をすることにしました。

さあ、期待に胸膨らませて
ab にてテストをしましょう。

Requests per second:    1296.83 [#/sec]

きたああああああああああああああああ!!!!
どうせだから servlet での値も測定してみましょう。

Requests per second:    1331.42 [#/sec]

こっちもきたあああああああああああああ!!!!

ということで、
mod_proxy_ajp を使用する場合はクラスタ化する必要がなくても、
mod_proxy_balancer を使いましょう。

さようなら mod_jk 今までありがとう

追記

ProxyPass /servlet/ balancer://ajp-balancer/servlet/ stickysession=JSESSIONID
RewriteRule ^/(.+).jsp(.+)? balancer://ajp-balancer/$1.jsp$2 [P,L] stickysession=JSESSIONID

としたら、セッションも渡せましたとさ。

※この記事は以前のブログからの転載です。