1. 程式人生 > >tomcat叢集--整合Apache伺服器,採用mod_JK連線模式

tomcat叢集--整合Apache伺服器,採用mod_JK連線模式

一、叢集技術初步分析

1、tomcat叢集多應用伺服器,分擔壓力,並保證服務高可用,使用tomcat自帶cluster實現叢集環境,Manager負責管理session共享
2、web伺服器採用Apache,負責應用伺服器間負載均衡
3、apache伺服器和tomcat的連線方法其實有三種:mod_JK、http_proxy和ajp_proxy,本文采用mod_JK模式
4、盜一張圖,如下:
這裡寫圖片描述

二、tomcat叢集環境安裝與配置

1、下載tomcat伺服器,本文使用apache-tomcat-7.0.64版本,複製兩份,分別為tomcat1和tomcat2,配置server.xml,以tomcat1為例,配置程式碼如下:

<!-- 服務關閉埠 -->
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener"
/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html -->
<GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html --> <Service name="Catalina"> <!-- http聯結器使用nio非阻塞模式,Excutor作為執行器提供執行緒池支援 --> <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="10"/> <!-- 負責建立HTTP連線,使用nio非阻塞模式,配置使用executor執行器,使用連線池 --> <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool"/> <!-- Define an AJP 1.3 Connector on port 8009 --> <!-- AJP聯結器,監聽8009埠,採用AJP協議,連線tomcat伺服器與http伺服器(如Apache伺服器),實現兩者通訊 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> --> <!-- 使用AJP協議實現負載均衡,需要jvmRoute引數,值自定義 Tomcat會在建立session時會根據根據jvmRoute的值在sessionID後面追加route值 用於追蹤分發的請求 --> <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1"> <!-- Cluster:配置管理叢集節點,主要元件包括:Manager、Channel、Valve、ClusterListenner等 其中,Manager用於管理session會話資訊;Channel作為連線各個節點的通訊通道,管理連線各個節點;ClusterListenner監聽器,監聽Cluster元件接收的訊息,並把資訊傳遞給Manager;Valve過濾器或閥門 Cluster節點屬性: className:Cluster的實現類 channelSendOptions:可以設定為2、4、8、10,每個數字代表一種方式 2 = Channel.SEND_OPTIONS_USE_ACK(確認傳送) 4 = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK(同步傳送) 8 = Channel.SEND_OPTIONS_ASYNCHRONOUS(非同步傳送) 10 = 在非同步模式下,可以通過加上確認傳送(Acknowledge)來提高可靠性 --> <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <!-- session manager --> <!-- Manager:決定如何管理叢集的Session資訊,叢集環境下實現有兩種:DeltaManager和BackupManager,經常被使用的是DeltaManager DeltaManager,它會將所有的會話的改變同步給叢集中的每一個節點 BackupManager: 某節點會話的改變只會同步給叢集中的另外一個或者幾個節點,而不是所有節點,只用於會話備份 Manager節點屬性: className:Manager的實現類 expireSessionsOnShutdown:設定為true時,一個節點關閉,將導致叢集下的所有Session失效 notifyListenersOnReplication:叢集下節點間的Session複製、刪除操作時,是否非同步通知Cluster Listener maxInactiveInterval:叢集下Session的有效時間(單位:s)。 maxInactiveInterval:內未活動的Session,將被Tomcat回收。預設值為1800(30min) --> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <!-- Channel:叢集各個節點之間進行通訊通道,管理連線各個節點; 是一個抽象的埠,和socket類似,叢集各個節點通過它收發資訊。 Channel包括4個元件:Membership、Receiver、Sender、Interceptor(可選) --> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <!-- Membership:多播通道,維護叢集的可用節點列表; 所有節點這個配置是相同的; 它可以檢查到新增的節點,也可以檢查到沒有心跳的節點; 叢集中各個節點通過組播地址和組播埠號註冊到多播通道中,來實現由membership管理各個節點的效果 Membership節點屬性: address:組播地址 port:組播埠 frequency:傳送心跳(向組播地址傳送UDP資料包)的時間間隔(單位:ms)。預設值為500 dropTime:Membership在dropTime(單位:ms)內未收到某一節點的心跳,則將該節點從可用節點列表刪除。預設值為3000 --> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <!-- Reciver:接收器,用於Channel中各個節點如何從其他節點的Sender接收復制資料,有 兩種實現模式:阻塞模式和非阻塞模式 1)BioReceiver( org.apache.catalina.tribes.transport.bio.BioReceiver ) 2)NioReceiver( org.apache.catalina.tribes.transport.nio.NioReceiver ) Reciver節點屬性: address:接收訊息所使用的地址,可以理解為消費者註冊的地址 port:接收訊息所使用的埠號,多個tomcat節點在一臺物理伺服器上注意要使用不同的埠 autoBind:埠的變化區間,如果port為4000,autoBind為100,接收器將在4000-4099間取一個埠,進行監聽 selectorTimeout:Receiver內輪詢監聽的超時時間 maxThreads:執行緒池的最大執行緒數 --> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4001" autoBind="100" selectorTimeout="100" maxThreads="6"/> <!-- Sender:傳送器,負責傳送複製訊息,同步給其它節點,實質負責傳送訊息功能的是內嵌的Transport元件 --> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <!-- Transport有兩種實現模式: org.apache.catalina.tribes.transport.bio.PooledMultiSender(阻塞式)、 org.apache.catalina.tribes.transport.nio.PooledParallelSender(非阻塞式) --> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <!-- Interceptor : Cluster的攔截器 --> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/> </Channel> <!-- Valve:閥門、過濾器,用於在節點向客戶端響應前進行檢測或進行某些操作 ReplicationValve:用於檢測當前的響應是否涉及Session資料的更新,如下面配置的filter,即當對靜態頁面圖片等訪問時不進行session replication --> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=".*/.gif;.*/.js;.*/.jpg;.*/.png;.*/.htm;.*/.html;.*/.css;.*/.txt;"/> <!--JvmRouteBinderValve:當一個節點crash時,訪問跳到另一個節點,此時session ID 會將jvmRoute值和以前的session Id 繫結在一起 --> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <!-- ClusterListener : 監聽器,監聽Cluster元件接收的訊息,並把資訊傳遞給Manager 使用DeltaManager時,Cluster接收的資訊通過ClusterSessionListener傳遞給DeltaManager --> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> </Service> </Server>

如果只是實現叢集負載均衡,上面的cluster是可以不配置,cluster的作用是實現叢集高可用,也就是管理session資訊共享

補充配置:

<!-- 如果多個tomcat部署在同一臺機器上,服務關閉埠應該不同,比如tomcat2的配置由8005更改為9005 -->
<Server port="9005" shutdown="SHUTDOWN">

此外還有如下配置:

<!-- http連線埠以及請求轉發埠,8080更改為8090,8443更改為9443 -->
<Connector port="8090" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="9443" 
           executor="tomcatThreadPool"/>
<!-- AJP聯結器埠,由8009更改為9009,8443更改為9443 -->
<Connector port="9009" protocol="AJP/1.3" redirectPort="9443" />
<!-- 實現session資訊追蹤的配置,在tomcat2中,jvmRoute="tomcat1" -->
<Engine name="Catalina" defaultHost="localhost"  jvmRoute="tomcat2">
<!-- 接收器使用的埠,由4001更改為5001 -->
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
    address="auto" 
    port="4001" 
    autoBind="100"
    selectorTimeout="100" 
    maxThreads="6"/>

注意:上面所涉及到的埠,別忘記修改防火牆iptables開放埠,否則出現無法訪問。

2、修改專案的 WEN-INF/web.xml

<web-app></web-app>之間新增:

<distributable/>

3、啟動tomcat服務,測試是否可以訪問

三、安裝配置Apache伺服器

1、下載Apache 2.0.25,官網地址:http://httpd.apache.org,下載地址:點選下載Apache 2.0.25
下載之後的檔案:apache_2.0.55-win32-x86-no_ssl.msi,雙擊安裝執行。
安裝過程中,Network Domain 和 Server Name填寫內容,如果用於本機測試,可以直接localhost,否則填寫遠端主機地址。
或者點選:補充下載地址

2、下載並配置mod_jk.so
因為採用的是mod_jk模式,需要下載mod_jk.so外掛,mod_jk-apache-2.0.55.so
將下載的mod_jk-apache-2.0.55.so檔案拷貝到Apache安裝目錄的modules目錄下面

3、修改apache配置檔案conf/http.conf

開放並修改:

ServerName localhost:80

在檔案最後加上下面一句程式碼:

include conf/mod_jk.conf

4、配置mod_jk.conf
在http.conf同目錄下,建立mod_jk.conf檔案,內容如下:

#載入 mod_jk 模組
LoadModule jk_module modules/mod_jk-apache-2.0.55.so
#載入mod_jk.so 配置檔案
JkWorkersFile conf/workers.properties
#指定那些請求交給tomcat處理,"controller"為在workers.propertise裡指定的負載分配控制器
JkMount /* controller

5、配置workers.properties
在http.conf同目錄下,建立workers.properties檔案 ,內容如下:

###server 列表
###jvm1 需要注意此名字對應tomcat中server.xml<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
worker.list = controller,tomcat1,tomcat2
###tomcat1
###ajp13埠號,在tomcat下server.xml配置,預設8009
worker.tomcat1.port=8009
worker.tomcat1.host=192.168.0.10
worker.tomcat1.type=ajp13
###server的加權比重,值越高,分得的請求越多
worker.tomcat1.lbfactor=1

###tomcat2
worker.tomcat2.port=9009
worker.tomcat2.host=192.168.0.10
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1

###controller
worker.controller.type=lb
###指定分擔請求的tomcat
worker.controller.balance_workers=tomcat1,tomcat2
worker.controller.sticky_session=1

6、啟動Apache服務

四、測試叢集環境

1、tomcat1、tomcat2中,專案分別建立兩個頁面:session_set.jsp和session_get.jsp

tomcat1中
session_set.jsp:

<%@ page language="java" pageEncoding="UTF-8"%>
<%
    request.getSession().setAttribute("name", "tomcat1");
    System.out.println("tomcat1 set attribute success!");
%>
<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    tomcat1 set attribute success!<br>
  </body>
</html>

session_get.jsp:

<%@ page language="java" pageEncoding="UTF-8"%>
<%
    Object name = request.getSession().getAttribute("name");
    System.out.println("tomcat1 get attribute:"+name);
%>
<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    tomcat1 get attribute:<%=name %><br>
  </body>
</html>

tomcat2中
session_set.jsp:

<%@ page language="java" pageEncoding="UTF-8"%>
<%
    request.getSession().setAttribute("name", "tomcat2");
    System.out.println("tomcat2 set attribute success!");
%>
<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    tomcat2 set attribute success!<br>
  </body>
</html>

session_get.jsp:

<%@ page language="java" pageEncoding="UTF-8"%>
<%
    Object name = request.getSession().getAttribute("name");
    System.out.println("tomcat2 get attribute:"+name);
%>
<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    tomcat2 get attribute:<%=name %><br>
  </body>
</html>

負載均衡測試:
啟動tomcat1、tomcat2、Apache服務之後,用不同的瀏覽器多次訪問 http://localhost/test/session_set.jsp
http://localhost/test/session_get.jsp
檢視結果是否請求被分發到tomcat1和tomcat2上面,如果是,則實現負載均衡。

高可用測試:
負載均衡測試完畢之後,關閉tomcat2,然後重新整理會話在tomcat2上面的session_get.jsp頁面,檢視是否能拿到name的值為tomcat2,如果是,則說明tomcat2的會話資訊同步到了tomcat1中,實現了高可用。

關於高可用session不能複製或複製失敗的處理:
1、Receiver接收器這個配置:autoBind=”100”,儘量不配(不過預設值好像就是這個)
2、還是接收器配置:address=”auto”,儘量指定ip地址
3、防火牆開啟埠:8005、9005、8080、8090、8009、9009、8443、4001、5001、45564等上面tomcat配置所涉及的埠
4、如果執行上述操作,不起作用,關閉防火牆,重啟tomcat叢集,測試;成功後,開啟防火牆,再測

文章參考:
http://blog.csdn.net/yipanbo/article/details/44079083/
http://blog.csdn.net/zhuying_linux/article/details/6590700