Trasis Inc.

渋谷拠点のシステム開発会社

apache, tomcatで負荷分散

概要

apache+tomcat サーバ2台で負荷分散環境設定の記録。

要件

  • 正常時は2台のtomcatサーバで負荷分散。
  • セッションは DB(postgresql) に格納する。
  • 負荷分散時、stickysession 機能により、一ユーザのアクセスは可能な限り、1つの tomcat サーバに固定する。
  • 1台あたりのtomcatサーバで扱うセッション数はなるべく少なくし、余計なメモリを消費しないようにする。

Apacheサーバ設定

/etc/httpd/conf.d/tomcat.conf を作成し、次のように記述した。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyRequests off
ProxyPass / balancer://test/ stickysession=JSESSIONID nofailover=Off timeout=2 maxattempts=1
<Proxy balancer://test/>
BalancerMember ajp://host1:8009 keepalive=On retry=2 route=r1 loadfactor=10
BalancerMember ajp://host2:8009 keepalive=On retry=2 route=r2 loadfactor=10
</Proxy>

ProxyRequest 設定

ProxyRequests off は、リバースプロキシであることを明示。

ProxyPass 設定

ProxyPass 設定項目の解説。

stickysession=JSESSIONID は、tomcat によって生成されたセッションを特定のサーバに紐付けるために使用。
PHP ならPHPSESSIONID、tomcat サーバなら JSESSIONID を指定する。

nofailover=Off は、tomcat サーバ同士でセッション・レプリケーションが行われることを Apache に知らせている。
tomcat5 以上はセッション・レプリケーションに対応している。

timeout=2 は、バランサーのタイムアウト時間の設定 [秒]。

maxattempts=1 は、フェイルオーバーを試みる最大回数の指定。

BalancerMember 設定

ajp://host1:8009 は、接続先のtomcat サーバのホスト名とポート番号。

keepalive=On は、Apache とバックエンドサーバとのコネクションを保持し続けるかどうか。

retry=2 は、バックエンドサーバへの接続失敗時のリトライ回数。

route=r1 は、stickysession に関連した設定。
tomcat サーバにおいて jvmRoute を指定しておくと、セッション生成時に JSESSIONID の後尾にその文字列が付加される。
そして Apache 側で route 指定をしておくことで、Apache は JSESSIONID の後尾文字列を参照し、route 指定がある tomcat サーバへ優先的に接続してくれるようになる。
tomcat 側での jvmRoute 設定を合わせて設定しておくこと(後述)。

loadfactor=10 は複数の BalancerMember に対し、どのくらいの割合で負荷を分散するかを指定する。

tomcatサーバ設定

conf/server.xml で次のように修正する。

<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Service name="Catalina">
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="r1">
<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"/>
</Engine>
</Service>
</Server>

ホスト host2 上の tomcat では jvmRoute="r2" となる。

webアプリケーション設定

META-INF/context.xml (例: maven2 で管理されたプロジェクトの場合、 src/main/webapp/META-INF/context.xml) で次のように記述する。

<?xml version="1.0" encoding="UTF-8" ?>
<Context backgroundProcessorDelay="1">
<Manager className="org.apache.catalina.session.PersistentManager"
debug="0"
saveOnRestart="true" maxActiveSessions="2048" minIdleSwap="600"
maxIdleBackup="0" distributable="true">
<Store className="org.apache.catalina.session.JDBCStore"
driverName="org.postgresql.Driver"
connectionURL="jdbc:postgresql://dbserver:5432/tomcat?user=foo&amp;password=bar"
sessionTable="tomcat_sessions" sessionIdCol="session_id" />
</Manager>
</Context>

PersistentManager 設定

backgroundProcessorDelay はセッションのスワップアウトやバックアップなどが行われる間隔を指定する。
backgroundProcessorDelay * processExpiresFrequency 秒間隔で実行されるらしい。(参考文献)

saveOnRestart は、tomcat 停止時にセッションを(DBへ)保管するかどうか。

maxActiveSessions は、メモリ内に保持するセッション数。

minIdleSwap。セッション数が maxActiveSessions を越えたとき、スワップアウト(DBへの保管)が発生するが、ここで指定した秒数を超えない限りはスワップアウトされない。

maxIdleBackup はセッションが最後に使われてからDBへバックアップされるまでの時間 [秒]。
バックアップが行われてもメモリからは削除されない。

distributable は、アプリケーションからセッションに格納するオブジェクトがシリアライズ可能(Serializable)かどうかを指定する。
true にすると、シリアライズ不可なオブジェクトを HttpSession に格納しようとすると IllegalArgumentException 例外が発生する。

データベース作成

PostgreSQL に対し、データベースとテーブルを作成する。

# /bin/su postgres
$ createdb tomcat
$ psql tomcat
次の SQL を実行する
CREATE TABLE tomcat_sessions (
session_id character varying(100) NOT NULL,
valid character(1) NOT NULL,
maxinactive integer NOT NULL,
lastaccess bigint NOT NULL,
app character varying(255),
data bytea,
CONSTRAINT tomcat_sessions_pkey PRIMARY KEY (session_id)
)
WITHOUT OIDS;
ALTER TABLE tomcat_sessions OWNER TO postgres;
CREATE INDEX tomcat_session_idx1 ON tomcat_sessions USING btree (app);

参考文献