Apache 如何反向代理tomcat並且實現Session保持


簡介

LAMT=Linux+Apache+MySQL+Tomcat;

Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器,屬於輕量級應用服務器;

在中小型系統和並發訪問用戶不是很多的場合下被普遍使用,是開發和調試JSP 程序的首選;

 

架構需求

Tomcat實現JSP動態請求解析的基本架構

說明:由后端Tomcat負責解析動態jsp請求,但為了提高響應性能,在同一主機內配置Apache做反向代理,轉發所有請求至tomcat即可;

完整的LNMT架構設計

wKiom1NrqReyIsVnAAXyNugPRuA080.jpg

說明:本篇博客主要講解單台Haproxy到后端多台Tomcat服務器的實現;

 

安裝配置

Tomcat安裝配置

 

安裝配置

Tomcat安裝配置

安裝JDK

復制代碼
rpm -ivh jdk-7u9-linux-x64.rpm
vi /etc/profile.d/java.sh
    export JAVA_HOME=/usr/java/latest
    export PATH=$JAVA_HOME/bin:$PATH
. /etc/profile.d/java.sh
復制代碼

安裝Tomcat

tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/
cd /usr/local/
ln -sv apache-tomcat-7.0.42/ tomcat
vi /etc/profile.d/tomcat.sh
    export CATALINA_HOME=/usr/local/tomcat
    export PATH=$CATALINA_HOME/bin:$PATH
. /etc/profile.d/tomcat.sh
# 編寫服務腳本
 vim /etc/rc.d/init.d/tomcat
#!/bin/sh
# Tomcat init script for Linux.
#
# chkconfig: 2345 96 14
# description: The Apache Tomcat servlet/JSP container.
# JAVA_OPTS='-Xms64m -Xmx128m'
JAVA_HOME=/usr/java/latest
CATALINA_HOME=/usr/local/tomcat
export JAVA_HOME CATALINA_HOME

case $1 in
start)
exec $CATALINA_HOME/bin/catalina.sh start ;;
stop)
exec $CATALINA_HOME/bin/catalina.sh stop;;
restart)
$CATALINA_HOME/bin/catalina.sh stop
sleep 2
exec $CATALINA_HOME/bin/catalina.sh start ;;
configtest)
exec $CATALINA_HOME/bin/catalina.sh configtest ;;
*)
exec $CATALINA_HOME/bin/catalina.sh * ;;
esac
==========
chmod +x /etc/init.d/tomcat

配置Tomcat

vim /usr/local/tomcat/conf/server.xml

<?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="8080" 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="8009" protocol="AJP/1.3" redirectPort="8443" /> # 這里我們只啟用AJP協議


<!-- 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="TomcatB">

<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.101.69.4" # 指定集群組播地址 port="45564" # 端口 # 兩個節點群集組播地址一定要一直 frequency="500" dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" 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>
<!--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>

# tomcat session 復制集群 : 以上"灰色"的內容定義在Engine容器中,則表示對所有主機均啟動用集群功能。如果定義在某Host中,則表示僅對此主機啟用集群功能。此外,需要注意的是,Receiver中的address="auto"一項的值最好改為當前主機集群服務所對應的網絡接口的IP地址.

route add -net  228.101.64.4   netmask 255.255.255.255 dev eth0  #添加相對應的組播路由; 

此外,所有啟用集群功能的web應用程序,其web.xml中都須添加<distributable/>才能實現集群功能。如果某web應用程序沒有自己的web.xml,也可以通過復制默認的web.xml至其WEB-INF目錄中實現

 cp /usr/local/tomcat/conf/web.xml  /usr/local/tomcat/webapps/testapp/WEB-INF/

# vim web.xml
  95   <distributable/>
# 創建應用程序相關目錄
cd /usr/local/tomcat/webapps/
mkdir -pv testapp/WEB-INF/{classes,lib}
cd testapp
vi index.jsp
<%@ page language="java" %>
<html>
  <head><title>Tomcat1</title></head># 在Tomcat2主機上替換為Tomcat2
  <body>
    <h1><font color="red">Tomcat1.lnmmp.com</font></h1>#  在Tomcat2主機上替換為,color修改為blue
    <table align="centre" border="1">
      <tr>
        <td>Session ID</td>
    <% session.setAttribute("lnmmp.com","lnmmp.com"); %>
        <td><%= session.getId() %></td>
      </tr>
      <tr>
        <td>Created on</td>
        <td><%= session.getCreationTime() %></td>
     </tr>
    </table>
  </body>
</html>





 

server.xml文件中可定義的元素非常多,包括Server, Service, Connector, Engine, Cluster, Host, Alias, Context, Realm, Valve, Manager, Listener, Resources, Resource, ResourceEnvRef, ResourceLink, WatchedResource, GlobalNameingResources, Store, Transaction, Channel, Membership, Transport, Member, ClusterListener等 下面簡單介紹幾個常用組件: 1、Server組件 如上面示例文件中定義的: <Server port=”8005” shutdown=”SHUTDOWN”> 這會讓Tomcat6啟動一個server實例(即一個JVM),它監聽在8005端口以接收shutdown命令。各Server的定義不能使用同一個端口,這意味着如果在同一個物理機上啟動了多個Server實例,必須配置它們使用不同的端口。這個端口的定義用於為管理員提供一個關閉此實例的便捷途徑,因此,管理員可以直接telnet至此端口使用SHUTDOWN命令關閉此實例。不過,基於安全角度的考慮,這通常不允許遠程進行。 Server的相關屬性: className: 用於實現此Server容器的完全限定類的名稱,默認為org.apache.catalina.core.StandardServer; port: 接收shutdown指令的端口,默認僅允許通過本機訪問,默認為8005; shutdown:發往此Server用於實現關閉tomcat實例的命令字符串,默認為SHUTDOWN; 2、Service組件: Service主要用於關聯一個引擎和與此引擎相關的連接器,每個連接器通過一個特定的端口和協議接收入站請求交將其轉發至關聯的引擎進行處理。困此,Service要包含一個引擎、一個或多個連接器。 如上面示例中的定義: <Service name=”Catalina”> 這定義了一個名為Catalina的Service,此名字也會在產生相關的日志信息時記錄在日志文件當中。 Service相關的屬性: className: 用於實現service的類名,一般都是org.apache.catalina.core.StandardService。 name:此服務的名稱,默認為Catalina; 3、Connector組件: 進入Tomcat的請求可以根據Tomcat的工作模式分為如下兩類: Tomcat作為應用程序服務器:請求來自於前端的web服務器,這可能是Apache, IIS, Nginx等; Tomcat作為獨立服務器:請求來自於web瀏覽器; Tomcat應該考慮工作情形並為相應情形下的請求分別定義好需要的連接器才能正確接收來自於客戶端的請求。一個引擎可以有一個或多個連接器,以適應多種請求方式。 定義連接器可以使用多種屬性,有些屬性也只適用於某特定的連接器類型。一般說來,常見於server.xml中的連接器類型通常有4種: 1) HTTP連接器 2) SSL連接器 3) AJP 1.3連接器 # 這里我們使用的是AJP1.3連接器;這個連接器只支持AJP協議; 4) proxy連接器 如上面示例server.xml中定義的HTTP連接器: <Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort="8443"/> 定義連接器時可以配置的屬性非常多,但通常定義HTTP連接器時必須定義的屬性只有“port”,定義AJP連接器時必須定義的屬性只有"protocol",因為默認的協議為HTTP。以下為常用屬性的說明: 1) address:指定連接器監聽的地址,默認為所有地址,即0.0.0.02) maxThreads:支持的最大並發連接數,默認為200; 3) port:監聽的端口,默認為0; 4) protocol:連接器使用的協議,默認為HTTP/1.1,定義AJP協議時通常為AJP/1.35) redirectPort:如果某連接器支持的協議是HTTP,當接收客戶端發來的HTTPS請求時,則轉發至此屬性定義的端口; 6) connectionTimeout:等待客戶端發送請求的超時時間,單位為毫秒,默認為60000,即1分鍾; 7) enableLookups:是否通過request.getRemoteHost()進行DNS查詢以獲取客戶端的主機名;默認為true; 8) acceptCount:設置等待隊列的最大長度;通常在tomcat所有處理線程均處於繁忙狀態時,新發來的請求將被放置於等待隊列中; 下面是一個定義了多個屬性的SSL連接器: <Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
4、Engine組件: Engine是Servlet處理器的一個實例,即servlet引擎,默認為定義在server.xml中的Catalina。Engine需要defaultHost屬性來為其定義一個接收所有發往非明確定義虛擬主機的請求的host組件。如前面示例中定義的: <Engine name="Catalina" defaultHost="localhost"> 常用的屬性定義: defaultHost:Tomcat支持基於FQDN的虛擬主機,這些虛擬主機可以通過在Engine容器中定義多個不同的Host組件來實現;但如果此引擎的連接器收到一個發往非非明確定義虛擬主機的請求時則需要將此請求發往一個默認的虛擬主機進行處理,因此,在Engine中定義的多個虛擬主機的主機名稱中至少要有一個跟defaultHost定義的主機名稱同名; name:Engine組件的名稱,用於日志和錯誤信息記錄時區別不同的引擎; Engine容器中可以包含Realm、Host、Listener和Valve子容器。 5、Host組件: 位於Engine容器中用於接收請求並進行相應處理的主機或虛擬主機,如前面示例中的定義: <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
      </Host> 常用屬性說明: 1) appBase:此Host的webapps目錄,即存放非歸檔的web應用程序的目錄或歸檔后的WAR文件的目錄路徑;可以使用基於$CATALINA_HOME的相對路徑; 2) autoDeploy:在Tomcat處於運行狀態時放置於appBase目錄中的應用程序文件是否自動進行deploy;默認為true; 3) unpackWars:在啟用此webapps時是否對WAR格式的歸檔文件先進行展開;默認為true; 虛擬主機定義示例: <Engine name="Catalina" defaultHost="localhost">
  <Host name="localhost" appBase="webapps">
    <Context path="" docBase="ROOT"/>
    <Context path="/bbs" docBase="/web/bss" reloadable="true" crossContext="true"/>
  </Host>
  
  <Host name="mail.magedu.com" appBase="/web/mail">
    <Context path="" docBase="ROOT"/>
  </Host>
</Engine> 主機別名定義: 如果一個主機有兩個或兩個以上的主機名,額外的名稱均可以以別名的形式進行定義,如下: <Host name="www.magedu.com" appBase="webapps" unpackWARs="true">
  <Alias>magedu.com</Alias>
</Host>
6、Context組件: Context在某些意義上類似於apache中的路徑別名,一個Context定義用於標識tomcat實例中的一個Web應用程序;如下面的定義: <!-- Tomcat Root Context -->
    <Context path="" docBase="/web/webapps"/>
    
    <!-- buzzin webapp -->
    <Context path="/bbs" docBase="/web/threads/bbs" reloadable="true">
    </Context>
    
    <!-- chat server -->
      <Context path="/chat" docBase="/web/chat"/>
      
    <!-- darian web -->
    <Context path="/darian" docBase="darian"/> 在Tomcat6中,每一個context定義也可以使用一個單獨的XML文件進行,其文件的目錄為$CATALINA_HOME/conf/<engine name>/<host name>。可以用於Context中的XML元素有Loader,Manager,Realm,Resources和WatchedResource。 常用的屬性定義有: 1) docBase:相應的Web應用程序的存放位置;也可以使用相對路徑,起始路徑為此Context所屬Host中appBase定義的路徑;切記,docBase的路徑名不能與相應的Host中appBase中定義的路徑名有包含關系,比如,如果appBase為deploy,而docBase絕不能為deploy-bbs類的名字; 2) path:相對於Web服務器根路徑而言的URI;如果為空“”,則表示為此webapp的根路徑;如果context定義在一個單獨的xml文件中,此屬性不需要定義; 3) reloadable:是否允許重新加載此context相關的Web應用程序的類;默認為false; 7、Realm組件: 一個Realm表示一個安全上下文,它是一個授權訪問某個給定Context的用戶列表和某用戶所允許切換的角色相關定義的列表。因此,Realm就像是一個用戶和組相關的數據庫。定義Realm時惟一必須要提供的屬性是classname,它是Realm的多個不同實現,用於表示此Realm認證的用戶及角色等認證信息的存放位置。 JAASRealm:基於Java Authintication and Authorization Service實現用戶認證; JDBCRealm:通過JDBC訪問某關系型數據庫表實現用戶認證; JNDIRealm:基於JNDI使用目錄服務實現認證信息的獲取; MemoryRealm:查找tomcat-user.xml文件實現用戶信息的獲取; UserDatabaseRealm:基於UserDatabase文件(通常是tomcat-user.xml)實現用戶認證,它實現是一個完全可更新和持久有效的MemoryRealm,因此能夠跟標准的MemoryRealm兼容;它通過JNDI實現; 下面是一個常見的使用UserDatabase的配置: <Realm className=”org.apache.catalina.realm.UserDatabaseRealm” resourceName=”UserDatabase”/> 下面是一個使用JDBC方式獲取用戶認證信息的配置: <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99" driverName="org.gjt.mm.mysql.Driver" connectionURL="jdbc:mysql://localhost/authority" connectionName="test" connectionPassword="test" userTable="users" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles" roleNameCol="role_name" />
8、Valve組件: Valve類似於過濾器,它可以工作於Engine和Host/Context之間、Host和Context之間以及Context和Web應用程序的某資源之間。一個容器內可以建立多個Valve,而且Valve定義的次序也決定了它們生效的次序。Tomcat6中實現了多種不同的Valve: AccessLogValve:訪問日志Valve ExtendedAccessValve:擴展功能的訪問日志Valve JDBCAccessLogValve:通過JDBC將訪問日志信息發送到數據庫中; RequestDumperValve:請求轉儲Valve; RemoteAddrValve:基於遠程地址的訪問控制; RemoteHostValve:基於遠程主機名稱的訪問控制; SemaphoreValve:用於控制Tomcat主機上任何容器上的並發訪問數量; JvmRouteBinderValve:在配置多個Tomcat為以Apache通過mod_proxy或mod_jk作為前端的集群架構中,當期望停止某節點時,可以通過此Valve將用記請求定向至備用節點;使用此Valve,必須使用JvmRouteSessionIDBinderListener; ReplicationValve:專用於Tomcat集群架構中,可以在某個請求的session信息發生更改時觸發session數據在各節點間進行復制; SingleSignOn:將兩個或多個需要對用戶進行認證webapp在認證用戶時連接在一起,即一次認證即可訪問所有連接在一起的webapp; ClusterSingleSingOn:對SingleSignOn的擴展,專用於Tomcat集群當中,需要結合ClusterSingleSignOnListener進行工作; RemoteHostValve和RemoteAddrValve可以分別用來實現基於主機名稱和基於IP地址的訪問控制,控制本身可以通過allow或deny來進行定義,這有點類似於Apache的訪問控制功能;如下面的Valve則實現了僅允許本機訪問/probe: <Context path="/probe" docBase="probe">
    <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1"/>
  </Context> 其中相關屬性定義有: 1) className:相關的java實現的類名,相應於分別應該為org.apache.catalina.valves.RemoteHostValve或org.apache.catalina.valves.RemoteAddrValve; 2) allow:以逗號分開的允許訪問的IP地址列表,支持正則表達式,因此,點號“.”用於IP地址時需要轉義;僅定義allow項時,非明確allow的地址均被deny; 3) deny: 以逗號分開的禁止訪問的IP地址列表,支持正則表達式;使用方式同allow; 9、GlobalNamingResources 應用於整個服務器的JNDI映射,此可以避免每個Web應用程序都需要在各自的web.xml創建,這在web應用程序以WAR的形式存在時尤為有用。它通常可以包含三個子元素: 1) Environment; 2) Resource; 3) ResourceEnvRef; 10、WatchedResource WatchedResource可以用於Context中監視指定的webapp程序文件的改變,並且能夠在監視到文件內容發生改變時重新裝載此文件。 11、Listener Listener用於創建和配置LifecycleListener對象,而LifecycleListener通常被開發人員用來創建和刪除容器。 11、Loader Java的動態裝載功能是其語言功能強大表現之一,Servlet容器使用此功能在運行時動態裝載servlet和它們所依賴的類。Loader可以用於Context中控制java類的加載。 12、Manager Manger對象用於實現HTTP會話管理的功能,Tomcat6中有5種Manger的實現: 1) StandardManager Tomcat6的默認會話管理器,用於非集群環境中對單個處於運行狀態的Tomcat實例會話進行管理。當Tomcat關閉時,這些會話相關的數據會被寫入磁盤上的一個名叫SESSION.ser的文件,並在Tomcat下次啟動時讀取此文件。 2) PersistentManager 當一個會話長時間處於空閑狀態時會被寫入到swap會話對象,這對於內存資源比較吃緊的應用環境來說比較有用。 3)DeltaManager 用於Tomcat集群的會話管理器,它通過將改變了會話數據同步給集群中的其它節點實現會話復制。這種實現會將所有會話的改變同步給集群中的每一個節點,也是在集群環境中用得最多的一種實現方式。 4)BackupManager 用於Tomcat集群的會話管理器,與DeltaManager不同的是,某節點會話的改變只會同步給集群中的另一個而非所有節點。 5)SimpleTcpReplicationManager Tomcat4時用到的版本,過於老舊了。 13、Stores PersistentManager必須包含一個Store元素以指定將會話數據存儲至何處。這通常有兩種實現方式:FileStore和JDBCStore。 14、Resources 經常用於實現在Context中指定需要裝載的但不在Tomcat本地磁盤上的應用資源,如Java類,HTML頁面,JSP文件等。 15、Cluster 專用於配置Tomcat集群的元素,可用於Engine和Host容器中。在用於Engine容器中時,Engine中的所有Host均支持集群功能。在Cluster元素中,需要直接定義一個Manager元素,這個Manager元素有一個其值為org.apache.catalina.ha.session.DeltaManager或org.apache.catalina.ha.session.BackupManager的className屬性。同時,Cluster中還需要分別定義一個Channel和ClusterListener元素。 15.1、Channel 用於Cluster中給集群中同一組中的節點定義通信“信道”。Channel中需要至少定義Membership、Receiver和Sender三個元素,此外還有一個可選元素Interceptor。 15.2、Membership 用於Channel中配置同一通信信道上節點集群組中的成員情況,即監控加入當前集群組中的節點並在各節點間傳遞心跳信息,而且可以在接收不到某成員的心跳信息時將其從集群節點中移除。Tomcat6中Membership的實現是org.apache.catalina.tribes.membership.McastService。 15.3、Sender 用於Channel中配置“復制信息”的發送器,實現發送需要同步給其它節點的數據至集群中的其它節點。發送器不需要屬性的定義,但可以在其內部定義一個Transport元素。 15.4 Transport 用於Sender內部,配置數據如何發送至集群中的其它節點。Tomcat6有兩種Transport的實現: 1) PooledMultiSender 基於Java阻塞式IO,可以將一次將多個信息並發發送至其它節點,但一次只能傳送給一個節點。 2)PooledParallelSener 基於Java非阻塞式IO,即NIO,可以一次發送多個信息至一個或多個節點。 15.5 Receiver 用於Channel定義某節點如何從其它節點的Sender接收復制數據,Tomcat6中實現的接收方式有兩種BioReceiver和NioReceiver。

webapp體系結構:
wenapp有特定的組織格式:是一種層次目錄結構;通常包含了servlet代碼文件、jsp頁面文件、類文件、部署描述符文件等等,一般會打包成歸檔格式;
/:web應用程序的根目錄
/WEB-INF:此webapp的私有資源根目錄。通常web.xml和context.xml均放置在次目錄;
/WEB-INF:classes:此webapp自有類:
/WEB-INF:此webapp自有能夠被打包為jar格式的類;

 
         

webapp的歸檔格式:
EJB類歸檔的擴展名為.jar
web應用程序的歸檔擴展名為.war
資源適配器的擴展名.rar
企業級應用程序的擴展名.ear
web服務的擴展名為.ear或.war

 

 

Tomcat的連接器分為兩類:HTTP連接器和Web服務器連接器: Tomcat的HTTP連接器有三種: 1) 基於java的HTTP/1.1連接器,這也是Tomcat6默認使用的連接器,即Coyote;它是Tomcat作為standalone模式工作時所用到的連接器,可直接響應來自用戶瀏覽器的關於JSP、servlet和HTML的請求;此連接器是一個Java類,定義在server.xml當中,默認使用8080端口; 2) Java開發的高性能NIO HTTP/1.1連接器,它支持非阻塞式IO和Comnet,在基於庫向tomcat發起請求時,此連接器表現不俗;但其實現不太成熟,有嚴重bug存在; 3) C/C++開發的native APR HTTP/1.1連接器;在負載較大的場景中,此連接器可以提供非常好的性能;APR即Apache Portable Runtime,它是一個能讓開發者采用與平台無關的風格的方式來開發C/C++代碼本地庫,它能夠很好的跨Windows, Linux和*nix平台工作。此連接器從三個主要方面優化了系統性能並提升了系統的伸縮能力:(1)使用sendfile()內核模式調用發送大的靜態文件;(2) 僅使用一個native code保持大量的連接;(3) 使用能夠加速SSL請求處理的OpenSSL本地代碼; 啟用APR連接器的條件: 1) 將連接器的protocol屬性設定為org.apache.coyote.http11.Http11AprProtocol; 2) APR的庫文件已經在系統庫文件的搜索路徑內;
AJP(Apache JServ Protocol):
AJP(Apache JServ Protocol): AJP是面向數據包的基於TCP/IP的協議,它在Apache和Tomcat的實例之間提供了一個專用的通信信道。目前常用AJP協議的版本是1.3,它主要有以下特征: 1) 在快速網絡有着較好的性能表現,支持數據壓縮傳輸; 2) 支持SSL,加密及客戶端證書; 3) 支持Tomcat實例集群; 4) 支持在apache和tomcat之間的連接的重用;
配置apache通過mod_jk模塊與Tomcat連接:
yum -y install httpd-devel # rpm -ql httpd-devel | grep apxs /usr/sbin/apxs 配置apache通過mod_jk模塊與Tomcat連接 mod_jk是ASF的一個項目,是一個工作於apache端基於AJP協議與Tomcat通信的連接器,它是apache的一個模塊,是AJP協議的客戶端(服務端是Tomcat的AJP連接器)。 [root@www.magedu.com ~]# tar xf tomcat-connectors-1.2.37-src.tar.gz [root@www.magedu.com ~]# cd tomcat-connectors-1.2.37-src/native/ [root@www.magedu.com ~]# ./configure --with-apxs=/usr/bin/apxs [root@www.magedu.com ~]# make && make install apache要使用mod_jk連接器,需要在啟動時加載此連接器模塊。為了便於管理與mod_jk模塊相關的配置,這里使用一個專門的配置文件/etc/httpd/extra/httpd-jk.conf來保存相關指令及其設置。其內容如下: [root@localhost conf.d]# pwd
/etc/httpd/conf.d [root@localhost conf.d]# ls mod_dnssd.conf mod_jk.conf mod_proxy.conf.back README welcome.conf workers.properties ### [root@localhost conf.d]# cat mod_jk.conf LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/conf.d/workers.properties JkLogFile logs/mod_jk.log JkLogLevel notice JkMount /* lbcA JkMount /status/ statA ########################################################################## 這里有配置文件可以直接復制使用,只需要更改IP即可 [root@localhost conf.d]# cat workers.properties worker.list=lbcA,statA worker.TomcatA.type=ajp13 worker.TomcatA.port=8009 worker.TomcatA.host=172.16.249.58 worker.TomcatA.lbfactor=1 worker.TomcatB.type=ajp13 worker.TomcatB.port=8009 worker.TomcatB.host=172.16.249.203 worker.TomcatB.lbfactor=1 worker.lbcA.type=lb worker.lbcA.sticky_session=0 worker.lbcA.balance_workers=TomcatA,TomcatB worker.statA.type = status

 

除了需要使用LoadModule指令在apache中裝載模塊外,mod_jk還需要在apache的主配置文件中設置其它一些指令來配置其工作屬性。如JkWorkersFile則用於指定保存了worker相關工作屬性定義的配置文件,JkLogFile則用於指定mod_jk模塊的日志文件,JkLogLevel則可用於指定日志的級別(info, error, debug),此外還可以使用JkRequestLogFormat自定義日志信息格式。而JkMount(格式: JkMount  <URL to match>  <Tomcat worker name>)指定則用於控制URL與Tomcat workers的對應關系。 為了讓apache能使用/etc/httpd/extra/httpd-jk.conf配置文件中的配置信息,需要編輯/etc/httpd/httpd.conf,添加如下一行: Include /etc/httpd/extra/httpd-jk.conf 對於apache代理來說,每一個后端的Tomcat實例中的engine都可以視作一個worker,而每一個worker的地址、連接器的端口等信息都需要在apache端指定以便apache可以識別並使用這些worker。約定俗成,配置這些信息的文件通常為workers.properties,其具體路徑則是使用前面介紹過的JkWorkersFile指定的,在apache啟動時,mod_jk會掃描此文件獲取每一個worker的配置信息。比如,我們這里使用/etc/httpd/extra/workers.properties。 workers.properties文件一般由兩類指令組成:一是mod_jk可以連接的各worker名稱列表,二是每一個worker的屬性配置信息。它們分別遵循如下使用語法。 worker.list = < a comma separated list of worker names > worker. <worker name> .<property> = <property value> 其中worker.list指令可以重復指定多次,而worker name則是Tomcat中engine組件jvmRoute參數的值。如: worker.TomcatA.host=172.16.100.1 根據其工作機制的不同,worker有多種不同的類型,這是需要為每個worker定義的一項屬性woker.<work name>.type。常見的類型如下: ◇ ajp13:此類型表示當前worker為一個運行着的Tomcat實例。 ◇ lb:lb即load balancing,專用於負載均衡場景中的woker;此worker並不真正負責處理用戶請求,而是將用戶請求調度給其它類型為ajp13的worker。 ◇ status:用戶顯示分布式環境中各實際worker工作狀態的特殊worker,它不處理任何請求,也不關聯到任何實際工作的worker實例。具體示例如請參見后文中的配置。 worker其它常見的屬性說明: ◇ host:Tomcat 7的worker實例所在的主機; ◇ port:Tomcat 7實例上AJP1.3連接器的端口; ◇ connection_pool_minsize:最少要保存在連接池中的連接的個數;默認為pool_size/2; ◇ connection_pool_timeout:連接池中連接的超時時長; ◇ mount:由當前worker提供的context路徑,如果有多個則使用空格格開;此屬性可以由JkMount指令替代; ◇ retries:錯誤發生時的重試次數; ◇ socket_timeout:mod_jk等待worker響應的時長,默認為0,即無限等待; ◇ socket_keepalive:是否啟用keep alive的功能,1表示啟用,0表示禁用; ◇ lbfactor:worker的權重,可以在負載均衡的應用場景中為worker定義此屬性; 另外,在負載均衡模式中,專用的屬性還有: ◇balance_workers:用於負載均衡模式中的各worker的名稱列表,需要注意的是,出現在此處的worker名稱一定不能在任何worker.list屬性列表中定義過,並且worker.list屬性中定義的worker名字必須包含負載均衡worker。具體示例請參見后文中的定義。 ◇ method:可以設定為R、T或B;默認為R,即根據請求的個數進行調度;T表示根據已經發送給worker的實際流量大小進行調度;B表示根據實際負載情況進行調度。 ◇sticky_session:在將某請求調度至某worker后,源於此址的所有后續請求都將直接調度至此worker,實現將用戶session與某worker綁定。默認為值為1,即啟用此功能。如果后端的各worker之間支持session復制,則可以將此屬性值設為0。 根據前文中的指定,這里使用/etc/httpd/extra/workers.properties來定義一個名為TomcatA的worker,並為其指定幾個屬性。文件內容如下: worker.list=TomcatA,stat1 worker.TomcatA.port=8009 worker.TomcatA.host=172.16.100.1 worker.TomcatA.type=ajp13 worker.TomcatA.lbfactor=1 worker.stat1.type = status 至此,一個基於mod_jk模塊與后端名為TomcatA的worker通信的配置已經完成,重啟httpd服務即可生效。

 

配置基於mod_jk的負載均衡 1、  為了避免用戶直接訪問后端Tomcat實例,影響負載均衡的效果,建議在Tomcat 7的各實例上禁用HTTP/1.1連接器。 2、為每一個Tomcat 7實例的引擎添加jvmRoute參數,並通過其為當前引擎設置全局惟一標識符。如下所示。需要注意的是,每一個實例的jvmRoute的值均不能相同。 <Engine name=”Standalone” defaultHost=”localhost” jvmRoute=” TomcatA ”> 而后去配置apache,修改/etc/httpd/extra/httpd-jk.conf為如下內容: LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/extra/workers.properties JkLogFile logs/mod_jk.log JkLogLevel debug JkMount /* lbcluster1 JkMount /jkstatus/ stat1 編輯/etc/httpd/extra/workers.properties,添加如下內容: worker.list = lbcluster1,stat1 worker.TomcatA.type = ajp13 worker.TomcatA.host = 172.16.100.1 worker.TomcatA.port = 8009 worker.TomcatA.lbfactor = 5 worker.TomcatB.type = ajp13 worker.TomcatB.host = 172.16.100.2 worker.TomcatB.port = 8009 worker.TomcatB.lbfactor = 5 worker.lbcluster1.type = lb worker.lbcluster1.sticky_session = 1 worker.lbcluster1.balance_workers = TomcatA, TomcatB worker.stat1.type = status 演示效果,在TomcatA上某context中(如/test),提供如下頁面 <%@ page language="java" %> <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">TomcatA </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("abc","abc"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html> 演示效果,在TomcatB上某context中(如/test),提供如下頁面 <%@ page language="java" %> <html> <head><title>TomcatB</title></head> <body> <h1><font color="blue">TomcatB </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("abc","abc"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>

 

配置apache通過模塊與Tomcat連接:


要使用mod_proxy與Tomcat實例連接,需要apache已經裝載mod_proxy、mod_proxy_http、mod_proxy_ajp和proxy_balancer_module(實現Tomcat集群時用到)等模塊:

# httpd -D DUMP_MODULES | grep proxy httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain for ServerName
proxy_module (shared) proxy_balancer_module (shared) proxy_ftp_module (shared) proxy_http_module (shared) proxy_ajp_module (shared) proxy_connect_module (shared) Syntax OK # pwd
/etc/httpd/conf.d [root@localhost conf.d]# cat mod_proxy.conf ProxyVia on ProxyRequests off ProxyPreserveHost on <Proxy balancer://lb>
BalancerMember http://172.16.249.203:8080 loadfactor=1 route=TomcatA
BalancerMember http://172.16.249.58:8080 loadfactor=1 route=TomcatB
</Proxy> ProxyPass / balancer://lb/ stickysession=JSESSIONID 
ProxyPassReverse / balancer://lb/

<Location /> Order Allow,Deny Allow from all </Location>

 

關於如上apache指令的說明: ProxyPreserveHost {On|Off}:如果啟用此功能,代理會將用戶請求報文中的Host:行發送給后端的服務器,而不再使用ProxyPass指定的服務器地址。如果想在反向代理中支持虛擬主機,則需要開啟此項,否則就無需打開此功能。 ProxyVia {On|Off|Full|Block}:用於控制在http首部是否使用Via:,主要用於在多級代理中控制代理請求的流向。默認為Off,即不啟用此功能;On表示每個請求和響應報文均添加Via:;Full表示每個Via:行都會添加當前apache服務器的版本號信息;Block表示每個代理請求報文中的Via:都會被移除。 ProxyRequests {On|Off}:是否開啟apache正向代理的功能;啟用此項時為了代理http協議必須啟用mod_proxy_http模塊。同時,如果為apache設置了ProxyPass,則必須將ProxyRequests設置為Off。 ProxyPass [path] !|url  [key=value key=value ...]]:將后端服務器某URL與當前服務器的某虛擬路徑關聯起來作為提供服務的路徑,path為當前服務器上的某虛擬路徑,url為后端服務器上某URL路徑。使用此指令時必須將ProxyRequests的值設置為Off。需要注意的是,如果path以“/”結尾,則對應的url也必須以“/”結尾,反之亦然。 另外,mod_proxy模塊在httpd 2.1的版本之后支持與后端服務器的連接池功能,連接在按需創建在可以保存至連接池中以備進一步使用。連接池大小或其它設定可以通過在ProxyPass中使用key=value的方式定義。常用的key如下所示: ◇ min:連接池的最小容量,此值與實際連接個數無關,僅表示連接池最小要初始化的空間大小。 ◇ max:連接池的最大容量,每個MPM都有自己獨立的容量;都值與MPM本身有關,如Prefork的總是為1,而其它的則取決於ThreadsPerChild指令的值。 ◇ loadfactor:用於負載均衡集群配置中,定義對應后端服務器的權重,取值范圍為1-100。 ◇ retry:當apache將請求發送至后端服務器得到錯誤響應時等待多長時間以后再重試。單位是秒鍾。 如果Proxy指定是以balancer://開頭,即用於負載均衡集群時,其還可以接受一些特殊的參數,如下所示:
◇lbmethod:apache實現負載均衡的調度方法,默認是byrequests,即基於權重將統計請求個數進行調度,bytraffic則執行基於權重的流量計數調度,bybusyness通過考量每個后端服務器的當前負載進行調度。 ◇ maxattempts:放棄請求之前實現故障轉移的次數,默認為1,其最大值不應該大於總的節點數。 ◇ nofailover:取值為On或Off,設置為On時表示后端服務器故障時,用戶的session將損壞;因此,在后端服務器不支持session復制時可將其設置為On。 ◇ stickysession:調度器的sticky session的名字,根據web程序語言的不同,其值為JSESSIONID或PHPSESSIONID。 上述指令除了能在banlancer://或ProxyPass中設定之外,也可使用ProxySet指令直接進行設置,如:
<Proxy balancer://hotcluster>
BalancerMember  http://www1.magedu.com:8080 loadfactor=1
BalancerMember  http://www2.magedu.com:8080 loadfactor=2
ProxySet  lbmethod=bytraffic </Proxy> ProxyPassReverse:用於讓apache調整HTTP重定向響應報文中的Location、Content-Location及URI標簽所對應的URL,在反向代理環境中必須使用此指令避免重定向報文繞過proxy服務器。

 

 

測試:

配置apache通過mod_jk模塊與Tomcat連接時還能夠監控后端server 的狀態信息
JkLogFile logs/mod_jk.log
JkLogLevel notice
JkMount /* lbcA JkMount /status/ statA # 



免責聲明!

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



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