如何設定 Apache HTTP Server 透過 AJP 連結 Tomcat

Apache JServ Protocol (AJP13) 是 Tomcat 內建的功能,只要透過 mod_proxy_ajp 模組設定 ProxyPass 就可以讓 Apache HTTP Server 連接 Tomcat 了。

先啟用 mod_proxy_http 和 mod_proxy_ajp 這二個模組,直接在 httpd.conf 把 # 刪掉就可以了。
LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
再設定 ProxyPass 和 ProxyPassReverse 就可以了。

範例一:同一 tomcat server 不同 web app
<IfModule proxy_ajp_module>
# app1
ProxyPass "/app1" "ajp://tomcatserver1:8009/app1" timeout=1800
ProxyPassReverse "/app1" "ajp://server1:8009/app2"
# app2
ProxyPass "/app2" "ajp://tomcatserver1:8009/app2" timeout=1800
ProxyPassReverse "/app2" "ajp://server1:8009/app2"
</IfModule>

範例二:不同 tomcat server 不同 web app
<IfModule proxy_ajp_module>
# server1
ProxyPass "/app1" "ajp://tomcatserver1:8009/app1" timeout=1800
ProxyPassReverse "/app1" "ajp://server1:8009/app2"
# server2
ProxyPass "/app2" "ajp://tomcatserver2:8009/app2" timeout=1800
ProxyPassReverse "/app2" "ajp://server2:8009/app2"
</IfModule>

其實在網路上可以找到不少 mod_jk 模組的設定方法,但是麻煩的是還要另外編譯或是下載 so 檔,還有另外的 workers.properties 要設定 。除非是複雜的環境,才去碰 mod_jk 模組,不然一般情形下,直接用 mod_proxy_ajp 模組就可以適用了。

參考資料:
The Apache Tomcat Connectors - AJP Protocol Reference
Apache Module mod_proxy_ajp

如何設定 Tomcat Clustering

Tomcat 的 Clustering 設定其實很簡單,只要二個步驟就可以完成了。
1. 將 $CATALINA_HOME/conf/server.xml 中 Clustering 功能打開。
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
2. 將 $CATALINA_HOME/conf/web.xml 中 Distributable 功能打開。
<distributable/>
Tomcat 的 Clustering 功能只有一個也是唯一的一個,就是 SimpleTcpCluster 這個 class。它有一些參數設定,可以參看這份文件。不過大多數的情形下,預設值就已經夠用了。

下面是 Tomcat 的 Clustering 的注意事項:
1. SimpleTcpCluster 採用的是 broadcast 廣播的模式與其他 Server 溝通。
2. Broadcast 佔用的 port 是 45564。
3. Tomcat 會自動從 4000~4100 這個範圍的 port 取一個來 listen broadcast 的資訊。
4. 所有實作 javax.servlet.http.HttpSession 的 session 物件,也都必須實作 java.io.Serializable 才能運用在 Tomcat Clustering 架構中。
5. 確保加入 Clustering 的 Server 時間保持同步,可以採用 NTP 同步。

參考資料:
Clustering/Session Replication HOW-TO
The Cluster object

如何設定 Tomcat DataSource

Tomcat 的 DataSource 設定在 $CATALINA_HOME/conf/context.xml 裡。

Derby 的設定範例:
<Resource name="jdbc/EmbeddedDerbyDB"
          type="javax.sql.DataSource"
          maxActive="100"
          maxIdle="10"
          removeAbandoned="true"
          driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
          url="jdbc:derby:C:/DerbyDB;create=true"/>


Oracle 的設定範例:
<Resource name="jdbc/ORA"
          auth="Container"
          type="javax.sql.DataSource"
          maxActive="100"
          maxIdle="10"
          removeAbandoned="true"
          driverClassName="oracle.jdbc.OracleDriver"
          username="oradmin"
          password="ora1234"
          url="jdbc:oracle:thin:@192.168.100.100:1521:sid"/>


JDBC driver 是透過 java.sql.DriverManager 來管理註冊,而不同的 JDBC driver 只會被 java.sql.DriverManager 的 registerDriver 呼叫註冊一次。所以建議將 JDBC driver 放在 $CATALINA_BASE/lib 路徑下,以免造成 JVM Memory Leak 的問題。正確的 Class Loader 的順序,請參考 Class Loader HOW-TO 文件。

由於 Tomcat 的 DataSource 是採用 Apache Commons 專案中的 DBCPPool 來實作及管理,所以在 DataSource 的參數設定其實就是 DBCP 的參數設定。而這二個函式庫 DBCP 和 Pool 已經被包裝在單一 JAR 檔 $CATALINA_HOME/lib/tomcat-dbcp.jar 裡,其中 DBCP 1.4 已經支援 JDBC 4.0 規格。

DBCP 的參數設定可以參考網頁的說明,這裡先將比較常用的參數列舉說明一下。

一般基本參數:
參數名稱:username
說明:建立連線用的 username
參數名稱:password
說明:建立連線用的 password
參數名稱:url
說明:JDBC 的 url 字串
參數名稱:driverClassName
說明:JDBC dirver 的完整 class 名稱

常用參數:
參數名稱:maxActive
預設值:8
說明:Connection Pool 同時所能建立的連線最大數量。若為負值,則無上限。

參數名稱:maxIdle
預設值:8
說明:Connection Pool 同時所能允許閒置的連線最大數量。若為負值,則無上限。

參數名稱:validationQuery
預設值:無
說明:用來驗證測試連線是否成功。必須使用 SQL SELECT 語句,並且至少回傳一筆資料。以 Oracle 為例: select 1 from dual 。

參數名稱:removeAbandoned
預設值:false
說明:值為 true 時,當已建立的連線閒置時間超過 removeAbandonedTimout 設定值時,就會將連線棄置及移除。

參數名稱:removeAbandonedTimeout
預設值:300
說明:超過閒置秒數的連線會被移除。

範例程式:
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/ORA");
Connection conn = ds.getConnection();

參考資料:
Tomcat JNDI Datasource HOW-TO
DBCP Configuration