Apache + Tomcat + mod_jk實現集群服務及session共享


實現效果:用apache 分發請求到tomcat中的對應的項目 

原理:

環境說明:

操作系統:win7   64位

Javajdk: 1.7 
Apache:httpd-2.2.25-win32-x86-no_ssl.msi    (本地安裝路徑:D:\Program Files (x86)\Apache2.2\)
Tomcat: 7.0.42  ( http://tomcat.apache.org/download-70.cgi ),如果在同一台機器上模擬,下載zip版本. 實例中展示了2個節點
mod_jk: mod_jk1.2.30_x64:  ( http://tomcat.apache.org/download-connectors.cgi )

安裝步驟:

1.安裝jdk
2.安裝Apache2.2,使用默認設置,並且安裝路徑中不要空格.
3.解壓tomcat
4.拷貝mod_jk.so到Apache安裝路徑的modules文件夾下

 

配置步驟

 

修改Apache配置:

 

關於修改涉及到的文件httpd.conf和workers.properties文件可以下載一份mod_jk的源碼包參看

 

   1.修改Apache配置文件httpd.conf(筆者路徑:D:\Program Files (x86)\Apache2.2\conf\httpd.conf), 在最后一行末尾添加:

 

include "D:\Program Files (x86)\Apache2.2\conf\mod_jk.conf"
2. 在httpd.conf 同目錄下新建mod_jk.conf文件
#指定模塊路徑
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so
#指定 workers.properties文件路徑
JkWorkersFile conf/workers.properties
#指定哪些請求交給tomcat處理,"controller"為在workers.propertise里指定的負載分配控制器名
JkMount /* controller

#指定jk的日志輸出文件
JkLogFile logs/mod_jk.log
#指定日志級別,我這里設置的警告
JkLogLevel warn
#包含標准的mod_jk行為 (默認)
#info
#包含錯誤信息
#error
#用來配置log文件的日期/時間格式. 使用strftime()的格式化字符串,默認是[%a %b %d %H:%M:%S %Y]
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"    

#Options Description(選項的說明)
# %b 發送的字節, 不包括 HTTP headers (CLF format)
# %B 發送的字節, 不包括 HTTP headers
# %H 協議
# %m 請求方式(get/post)
# %p 服務器響應請求的規范端口.
# %q 查詢字符串 (如果存在以?開頭,否則是空串)
# %r 請求的第一行.
# %s HTTP狀態碼
# %T 請求間隔, 處理請求耗費的時間 秒.微秒
# %U 請求的url路徑,不包含查詢字符串.
# %v 響應請求的規范服務器名字
# %V 根據UseCanonicalName設置的服務器名字.
# %w Tomcat worker 名字
#JkRequestLogFormat 設置個人用戶請求的log格式.
JkRequestLogFormat "%w %V %T"

3.在httpd.conf同目錄下新建 workers.properties文件

#這里可以配置任意多個Tomcat,此處配置了2個Tomat服務器.
#host和port根據自己實際配置.實例配置的是本機兩個tomcat,分別使用不同的端口.避免沖突
#如果Tomcat不再同一機器上,沒必要改端口的。


#server 列表
worker.list=controller,status,tomcat1,tomcat2 

#========tomcat1========

worker.tomcat1.port=9988  #ajp13 端口號,在tomcat下server.xml配置,默認8009
worker.tomcat1.host=192.168.0.47        #tomcat的主機地址,如不為本機,請填寫ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor=1  #server的加權比重,值越高,分得的請求越多
  

#========tomcat2========

worker.tomcat2.port=9999        #ajp13 端口號,在tomcat下server.xml配置,默認8009
worker.tomcat2.host=192.168.0.47        #tomcat的主機地址,如不為本機,請填寫ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1        #server的加權比重,值越高,分得的請求越多 



#========controller,負載均衡控制器========
worker.controller.type=lb


#指定此負載平衡器負責的Tomcat應用節點。

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

#此處指定集群是否需要會話復制,如果設為true,則表明為會話粘性,不進行會話復制,當某用戶的請求第一次分發到哪台
#Tomcat后,后繼的請求會一直分發到此Tomcat服務器上處理;如果設為false,則表明需求會話復制。
worker.controller.sticky_session=false
#描述是用於httpd自身狀態監控的status
worker.status.type=status

4.在httpd.conf同目錄下新建 uriworkermap.properties文件(未測試是否對集群有影響)

/*=controller                       
/jkstatus=status                   
!/*.gif=controller                  
 !/*.jpg=controller 
!/*.png=controller 
!/*.css=controller 
!/*.js=controller 
!/*.htm=controller 
!/*.html=controller

 修改Tomact配置:(tomcat 6.0.36  可以實現集群  ,但是session沒有共享。原因未找到)(tomcat 7.0.42 實現集群及session共享)

 

以 tomcat 7.0.42  為實例

1.修改分發tomcat對應的service.xml文件,保證Apache對應的 workers.properties中的AJP13的connector的port. 

<!-- 定義一個AJP 1.3 連接端口為9988 ,默認值為8009,這里我們改成我們自己定義的9988端口 --> <Connector port="9988" protocol="AJP/1.3" redirectPort="8443" />

2.增加jvmRoute的值,保證同workers.properties里邊配置的值一致

<!--增加jvmRoute,值為在Apache中配置的list集群結點中的值,這里定義為tomcat1結點--> <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

3.去掉默認注釋掉的集群配置

<!--取消集群結點相關的注釋,該句默認值注釋掉的,我們需要配置集群所以去掉注釋,讓其起作用--> <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

 

4.實例中我們的兩個tomcat結點在同一台機器上,所以還需要保證protocol="HTTP/1.1"的端口不一致.不然本地的兩個tomcat會起沖突

下面為筆者實例中解決同一台機器上多個tomcat服務器之間端口沖突做的修改.

 

實例測試

   1.在web.xml文件中增加

<distributable/>

2.編寫測試jsp代碼 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.text.SimpleDateFormat"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Tomcat集群測試</title>
  </head>
  
  <body> 服務器信息: <%
      String dtm = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); System.out.println("["+request.getLocalAddr()+":"+ request.getLocalPort()+"]" + dtm); out.println("<br>["+request.getLocalAddr()+":" +request.getLocalPort()+"]" + dtm+"<br>"); %> session分發: <% session.setAttribute("name","dennisit"); System.out.println("[session分發] session id:"+session.getId()); out.println("<br>[session分發] session id: " + session.getId()+"<br>"); %>
  </body>
</html>

3.測試負載均衡與session分發

將項目部署到每個集群結點中,即實例中的tomcat_node1和tomcat_node2,依次移動Apache和tomcat服務器,tomcat服務器之間的啟動順序隨意.這里Apache端口使用默認的80.

上面是在FireFox中運行項目后刷新3次執行的效果,可以看到2個tomcat分發結點之間輪流負載.而且兩台服務器上的session值是一樣的.說明session分發成功.

兩台Tomcat服務器日志打印輸出結果:

錯誤解決:

    (1)apache 服務器無法加載jk代理

                        原因:apache 和 mod_jk  版本差異導致。解決辦法,將mod_jk.so替換為 mod_jk-1.2.31-httpd-2.2.3.so。

    (2)apache 服務器無法啟動

                      原因:httpd.conf  配置文件有誤。首次安裝可以啟動。你改動有誤。

 其他

     附上tomcat  6   與tomcat  7   server.xml  對比代碼:

tomcat  6  

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -->
<!-- Note:  A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html -->
<Server port="8005" shutdown="SHUTDOWN">

  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />


  <!-- 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">
  
    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
    -->
    
    
    <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="9008" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    -->           
    <!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation -->
    <!--
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="9988" enableLookups="false" protocol="AJP/1.3" redirectPort="8443" />

    <!--For clustering-->
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<!--    <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster" managerClassName="org.apache.catalina.cluster.session.DeltaManager" expireSessionsOnShutdown="false" useDirtyFlag="true" notifyListenersOnReplication="true">

            <Membership className="org.apache.catalina.cluster.mcast.McastService" mcastAddr="228.0.0.4" mcastPort="45564" mcastFrequency="500" mcastDropTime="3000"/>

            <Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener" tcpListenAddress="auto" tcpListenPort="4001" tcpSelectorTimeout="100" tcpThreadCount="6"/>

            <Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter" replicationMode="pooled" ackTimeout="15000" waitForAck="true"/>

            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
                  
            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/>
                     
            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
        </Cluster>


          
-->


    <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">         
    --> 
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

      <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->        

      <!-- The request dumper valve dumps useful debugging information about the request and response data received and sent by Tomcat. Documentation at: /docs/config/valve.html -->
      <!--
      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
      -->

      <!-- 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"/>

      <!-- Define the default virtual host Note: XML Schema validation will not work with Xerces 2.2. -->
      <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
      <!-- <context docBase= "e:\webapps\tomcat_apche" path="/tomcat_apche"  debug="0" reloadable="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 -->
        <!--
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
        -->

      </Host>
    </Engine>
  </Service>
</Server>
View Code

tomcat  6  死活沒弄出來session 共享  即使加上各位大神的如下代碼。(無意冒犯,就事說事。)

http://www.linuxidc.com/Linux/2012-08/69311p2.htm

tomcat  7

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -->
<!-- Note:  A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html -->
<Server port="8005" shutdown="SHUTDOWN">
  <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <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">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="9008" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    -->
    <!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation -->
    <!--
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="9988" protocol="AJP/1.3" redirectPort="8443" />


    <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie : -->
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
   
    <!--<Engine name="Catalina" defaultHost="localhost">-->

      <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) -->
      <!-- -->
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
     

      <!-- 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>
View Code

比較不錯的大牛參考博文:

     Apache+Tomcat負載均衡兩種session共享方式的設置:http://blog.sina.com.cn/s/blog_5f53615f0100p4fj.html

     Apache + Tomcat + mod_jk實現集群服務:http://www.linuxidc.com/Linux/2015-02/114231.htm

     Apache2+Tomcat7+mod_jk2.2.3集群負載均衡配置(目前最強悍)

 
         
 
  
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM