Windows中Apache2.2 Tomcat7 集羣配置

今天終於搞定了Apache和tomcat7整合集羣以及負載均衡的問題,在此做個記錄。

客戶的網站有時候會因爲一個tomcat6的錯誤down掉,又比較難查出示什麼原因,而且是沒什麼規律的。所以狠下心來做了個tomcat6到7的升級,並使用了tomcat7的集羣。

   要說Tomcat7和6的配置確實有些不同,以前我在Server.xml的Engine節點內增加一個Listener就能自動生成一個mod_jk.conf-auto配置文件,包含到apache/conf/httpd.conf裏面,然後修改一下就行了。現在就不同了,以下是我Tomcat6的server.xml配置。

<Listener className="org.apache.jk.config.ApacheConfig" modJk="D:/Apache2.213/modules/mod_jk-1.2.26-httpd-2.2.4.so" />

雖然提示我什麼workers.properties找不到,但是照樣能用。

Tomcat7裏面這招不好用了,寫上這句就會報錯誤。無語了。只能狠下心重新查資料,看了網上的一些文章和tomcat自己帶的文檔。終於搞出來了,下面就跟大家分享一下我的經驗,本人水平確實有限,望大家拍磚。

首先說一下我的服務器端軟件

1.Apache,我採用帶SSL模塊的,因爲我以後還要做CAS配置用,如果不用SSL版本也一樣。httpd-2.2.17-win32-x86-openssl-0.9.8o.msi

2.Tomcat版本是7.0.12,解壓版的,要做集羣,自動安裝服務的有點不爽。

一、配置apache

1.加載鏈接器so文件

安裝就不說了,裝好後,打開apache_home/conf/httpd.conf,找到如下文本:

#LoadModule jk_module modules/mod_jk.so

把它的註釋去掉,從apache官網上找對應的Connector,我這個版本apache對應的是mod_jk-1.2.28-httpd-2.2.3.so。對於這塊不熟的朋友我簡單說一下:其中 1.2.28是Connector的版本,後面的2.2.3是對應的apache版本。其中主要是apache的版本要對應,沒有正好匹配的要找相近的。我把 LoadModule jk_module modules/mod_jk.so改爲: LoadModule jk_module modules/mod_jk-1.2.28-httpd-2.2.3.so。當然你也可以把so文件修改文件名爲 mod_jk.so。當然這個so文件要放在 apache_home/modules裏了,否則得寫絕對路徑了。

這一步就算做好了,重啓apache,如果沒有錯誤說明OK。有錯誤無非2個。一個是文件路徑寫錯了;另一個是so的版本與apache不匹配。

2.增加apche與tomcat的連接

   在httpd.conf文件的末尾增加一句:Include conf/mod_jk.conf

   包含mod_jk的配置文件,當然這個文件我們還得自己建立。

   以下是我的mod_jk.conf內容:

   JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
JkRequestLogFormat "%w %V %T"
JkMount /* controller
Alias /cas "D:/apache-tomcat-7.0.12/webapps/cas"
<Directory "D:/apache-tomcat-7.0.12/webapps/cas">
    #Options FollowSymLinks
    #AllowOverride None
</Directory>

 

Alias /cas "D:/apache-tomcat-7.0.12/webapps/cas"和它下面的配置是我做cas的,不必理會,可以不要。

JkWorkersFile conf/workers.properties指明worker的配置文件名,這也需要自己寫。

JkMount /* controller 中的“controller”是在workers.properties中配置的,目前先這麼寫吧。

其他幾行都是日誌的配置,當時大家最好都加上,因爲配置中隨時有可能失敗,在日誌裏可以查看到底出了什麼錯誤。

JkMount /* controller這句的還以大家應該都明白,相當於以前自動生成配置中的 JkMount /* ajp13

當然這樣配置只是爲了方便,把所有的請求都轉發到tomcat了,實際上肯定不會這麼做的,否則apache只有純轉發的功能了,我們只需要把需要執行java代碼的地址轉發給tomcat,實際上可能這樣配置:

JkMount /*.do controller

JkMount /*.jsp controller

JkMount /yourServletURL controller

我自己是配置一個VirtualHost,在VirtualHost配置這些轉發的。


 以下是我的workers.properties內容


 worker.list=controller
worker.controller.type=lb
worker.controller.sticky_session=1
worker.controller.error_escalation_time=0
worker.controller.max_reply_timeouts=10

# localhost server 1
# ------------------------
worker.jvm1.reference=worker.template
worker.jvm1.port=8009
worker.jvm1.host=localhost
worker.jvm1.lbfactor = 5
worker.jvm1.activation=A


# localhost server 2
worker.jvm2.reference=worker.template
worker.jvm2.port=8019
worker.jvm2.host=localhost
worker.jvm2.lbfactor=1
worker.jvm2.activation=A


worker.template.type=ajp13                   
worker.template.socket_connect_timeout=5000
worker.template.socket_keepalive=true
worker.template.ping_mode=A
worker.template.ping_timeout=10000
worker.template.connection_pool_minsize=0
worker.template.connection_pool_timeout=600
worker.template.reply_timeout=300000
worker.template.recovery_options=3

worker.controller.balance_workers=jvm1,jvm2


具體的那些參數就不細說了,重點是tomcat的端口,默認的tomcat ajp13的端口是8009。我是在一臺機器上配的2個tomcat,所以ajp的端口分別是8009和8019,還有worker.jvm1和 worker.jvm2分別代表2個Tomcat.這個在tomcat的server.xml中也有體現,下面再說這個。

還有就是worker.controller.sticky_session=1這個參數配置爲true或者1,說明需要session複製。


二、配置Tomcat7

打開Tomcat7的server.xml,找到<Server port="8005" shutdown="SHUTDOWN">,其中一個tomcat要把這個端口改掉,還有默認的8009,8080,8443端口,只要一臺機器上部署多個Tomcat,這些端口不能重複的,反正訪問的時候也不會用這些端口訪問,隨便改了。要注意的是<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="GBK"/>,這個東西,port的值要和 workers.properties 中的 worker.jvm1.port、 worker.jvm2.port匹配。

找到<Engine name="Catalina" defaultHost="localhost">,修改爲<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">(第一個tomcat)和<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2">(第二個Tomcat),這裏的 jvmRoute的值就是workers.properties裏的值了,匹配就好。

 

在Engine節點內,增加如下配置:

 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>
          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto"  port="4001" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
          </Channel>

       <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"  filter="/"/>
          <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 className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
      </Cluster>

 

那個註釋掉Deployer不能加,會報個嚴重錯誤(雖然能啓動成功),而且這東西是集羣同步文件的,而且沒有實現。上面這一段配置不用修改,端口、地址之類的不用動,原樣複製就可以。

 

這樣Tomcat就算配置好了。測試一下,需要在應用的 web.xml中 web-app節點內增加

<distributable/> 配置,這樣程序就會知道需要集羣了。在2個tomcat上搞2個一樣的應用試驗一下吧,停止一個tomcat,訪問還是會成功的。

 

需要注意的地方:

 1.配置好mod_jk的日誌文件,有問題隨時看。

2. 如果你用的不是 mod_jk-1.2.28-httpd-2.2.3.so,比如我之前用的 mod_jk-1.2.26-httpd-2.2.4.so,可以用,但是 workers.properties裏某些屬性不支持,這我也是在日誌裏看到的,但是去掉不支持的屬性也能用。

3. 如果程序需要文件上傳,不要上傳到web目錄下,最好配置上傳到單獨的目錄中,這樣集羣中的所有應用纔好共享同一個上傳目錄。否則如果一個tomcat不運行了,另一個tomcat在運行時查找本應用下的上傳文件可能會找不到,因爲可能傳到死掉的那個tomcat應用目錄下了。如果需要用瀏覽器直接訪問這些上傳的文件(不需權限控制),應該在Apache裏給上傳文件的路徑配置一個Directory。確保文件通過web能夠正常訪問。我的配置如下:

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName www.xxx.cn
    ServerAlias xxx.cn
    #Allow from xxx.cn
    ErrorLog logs/xxx.cn-error_log
    CustomLog logs/xxx.cn-access_log common
    DocumentRoot "E:/wwwroot/xxx_a" #主tomcat(第一個)應用根目錄,我的程序叫xxx,部署2個分別較xxx_a,xxx_b
    DirectoryIndex index.do index.jsp

    Alias /html "E:/html" #生成靜態文件的目錄
    <Directory E:/html>
    Options FollowSymLinks
    AllowOverride None
    </Directory>
    Alias /imageupload "D:/imageupload" #圖片上傳的目錄
    <Directory D:/imageupload>
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    Alias /userfiles "E:/wwwroot/userfiles" #FckEditor的上傳目錄
    <Directory E:/wwwroot/userfiles>
    Options FollowSymLinks
    AllowOverride None
    </Directory>

   #禁止訪問的路徑配置,不讓用戶通過瀏覽器訪問WEB-INF
    <Directory E:/wwwroot/xxx_a/WEB-INF/>
        Options FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
    </Directory>

</VirtualHost>

4.如果web應用裏有一些後臺線程或後臺任務之類的東西,最好的方式是單獨做成一個非web應用,獨立運行,這也是servlet規範推薦的方式。不方便的話,需要在web應用中配置一個參數,指定集羣中的某一個實例運行這些線程,不要一個web程序的所有部署 實例 都運行線程,那樣可能出現意想不到的後果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章