目錄css
JVM的核心組成部分:html
Java編程語言特性:面向對象,多線程,結構化錯誤處理,垃圾收集,動態連接,動態擴展前端
堆:建立的對象都在堆內存中 GC:垃圾收集器,主要收集堆內存中的對象java
JDK:java開發工具箱,提供了JAVA的類庫,開發工具和apinode
JRE:java運行時環境(java runtime environment),運行java代碼,不能開發java代碼mysql
JRE(java runtime environment):包含了JVM和其餘一些簡單功能的JAVA運行環境,適用於只運行java程序時。nginx
JDK(java DevelopmentKit)比JRE包含了更多東西,除了能做爲JAVA運行環境,還提供了不少用於開發的工具適用於開發程序時使用web
JAVA SE是java開發標準版,裏面有JDK,Java EE是企業版,本質上ee只是比se多提供了幾個類庫而已。算法
JVM運行時區域:運行爲多個線程sql
Web Container:
catalina:servlet container
Coyote:http connection
Jasper: JSP Engine
Tomcat 開發語言: Java
Tomcat instance : 運行中的tomcat進程(java進程)
注意:每一個組件都由類來實現,有些組件的實現還不止一種
頂級類組件:server
服務類組件:service
容器類組件:engine,host,context
鏈接器組件:connector
被嵌套類組件:valve, logger,realm
安裝JDK,配置環境變量
[root@localhost ~]# cat /etc/profile.d/jdk.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin:$PATH
安裝Tomcat配置環境變量
[root@localhost ~]# cat /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=$CATALINA_HOME/bin:$PATH
WEB-INF/:當前webapp的私有資源目錄,一般存放當前webapp自用的web.xml
META-INF/:當前webapp的私有資源目錄,一般存放當前webapp自用的context.xml
classes/:此webapp的私有類
lib/: 此webapp的私有類,被打包爲jar格式類
index.jsp:webapp的主頁
webapp歸檔格式:
<server> <service> <connector port="8080"/> #http協議默認端口 <connector port="8009" protocol="AJP/1.3"/> #ajp協議默認端口 <engine> <Host> </Host> <Context /> </engine> </service> </server>
手動添加一個測試應用程序:
建立特定目錄結構
mkdir -p myapp/{lib, classes. WEB-INF, MEAT-INF}
測試文件
[root@localhost myapp]# cat index.jsp <%@ page language="java" %> <%@ page import="java.util.*" %> <html> <head> <title> JSP test page </title> </head> <body> <% out.println("hello world"); %> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <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.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <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> <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" enableLookups="false" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" /> </Realm> <!-- 今後處開始添加如下兩個Host容器做爲虛擬主機 --> <!-- 定義一個在$CATALINA_HOME以外的虛擬主機 --> <Host name="www.longshuai.com" appBase="/www/longshuai" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="/www/longshuai" reloadable="true" /> <Context path="/xuexi" docBase="xuexi" reloadable="true" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="longshuai_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> <!-- 定義一個在$CATALINA_HOME/webapps下的虛擬主機 --> <Host name="www.xiaofang.com" appBase="webapps/xiaofang" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="" reloadable="true" /> <Context path="/xuexi" docBase="xuexi" reloadable="true" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="xiaofang_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> <!-- 默認虛擬主機localhost,可不修改 --> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
除了engine中定義的默認localhost虛擬主機,另外佈置了兩個虛擬主機www.longshuai.com和www.xiaofang.com,它們的程序目錄分別爲/www/longshuai和$CATALINA_HOME/webapps/xiaofang,因此須要提早創建好這兩個目錄。另外,在context中定義了docBase,對於uri路徑/xuexi,它的文件系統路徑分別爲/www/longshuai/xuexi目錄和$CATALINA_HOME/webapps/xiaofang/xuexi,因此也要在上面兩個程序目錄中定義好xuexi目錄。除此以外,還分別爲這3個虛擬主機定義了日誌,它們的路徑爲相對路徑logs,相對於$CATALINA_HOME。
再提供appBase目錄和docBase目錄。
mkdir -p /www/longshuai/xuexi mkdir -p /usr/local/tomcat/webapps/xiaofang/xuexi
再提供測試用的index.jsp文件。內容大體以下,分別複製到如下四個目錄中:
/www/longshuai/
/www/longshuai/xuexi/
/usr/local/tomcat/webapps/xiaofang/
/usr/local/tomcat/webapps/xiaofang/xuexi
並將out.println的輸出內容分別稍做修改,使可以區分讀取的是哪一個index.jsp。
<%@ page language="java" %> <%@ page import="java.util.*" %> <html> <body> <% out.println("hello world from longshuai Root"); %> </body> </html>
定義鏈接器時能夠配置的屬性很是多,但一般定義HTTP鏈接器時必須定義的屬性只有「port」,定義AJP鏈接器時必須定義的屬性只有「protocol」,由於默認的協議爲HTTP。如下爲經常使用屬性的說明:
下面定義了一個多個屬性的SSL鏈接器:
<Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
位於Engine容器中用於接收請求並進行相應處理的主機或虛擬主機
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"> </Host>
經常使用屬性說明:
虛擬主機定義示例:
<Engine name="Catalina" defaultHost="localhost"> <Host name="localhost" appBase="webapps"> <context path="" docBase="ROOT"/> <context path="/bbs" docBase="/web/bbs" reloadable="true" crossContext="true"/> </Host> <Host name="www.template.com" appBase="/web/tem"> <context path="/" docBase="ROOT"/> </Host> </Engine>
主機別名定義:
若是一個主機有兩個或兩個以上的主機名:額外的名稱都可以以別名的形式進行定義,以下:
<Host name="www.template.com" appBase="webapps" unpackWARs="true"> <alias>template.com</alias> </Host>
撇開tomcat做爲servlet容器的行爲。它和apache、nginx的功能大體都能對應上。例如以nginx爲例,如下是nginx提供web服務時的配置結構:
server { listen PORT; server_name www.a.com; # 對應於<host name=www.a.com> location / { # 對應於context path="" root html; # 對應於docBase } location /xuexi { # 對應於context path="/xuexi" root html/xuexi; } }
這兩貨雖然意義很明確,但"潛規則"很嚴重。如下面的配置爲例。
<host name=www.a.com appBase=/www/a > <context path="" docBase=/www/a /> <context path="/xuexi" docBase=/www/a/xuexi /> </host>
appBase是虛擬主機存放webapp的目錄,它能夠是相對路徑,也能夠是絕對路徑。若是是相對路徑,則相對於$CATALINA_HOME,嚴格並準確地說是$CATALINA_BASE。
path是URI的匹配路徑,至關於nginx的location後的路徑。tomcat要求每一個虛擬主機必須配置一個空字符串的path,該條context做爲URI沒法被明確匹配時的默認context,它至關於nginx中location / {}
的做用。
docBase則是每一個webapp的存放目錄(或者是已歸檔的war文件),它能夠是相對路徑,也能夠是絕對路徑,提供相對路徑時它相對於appBase。該目錄通常在appBase的目錄下,但並不規定必定要放在appBase下。對於web服務來講,它至關於nginx的root指令,但對於webapp來講,一個context就至關於一個webapp,而docBase正是webapp的路徑。
"潛規則"在於默認的context如何提供。有如下幾種狀況:
<context path="" docBase=webappPATH>
,此時默認context的處理路徑爲webappPATH。<context path="">
,但卻沒給定docBase屬性,此時該默認context處理路徑爲appBase/ROOT目錄,注意ROOT爲大寫。path=""
的context時,即host容器中沒有明確的path="",此時將隱式定義一個默認context,處理路徑爲appBase/ROOT目錄。context path context name 推斷出的docBase路徑 -------------------------------------------------- /foo /foo foo /foo/bar /foo/bar foo/bar Empty String Empty String ROOT
顯然,沒有給定path=""或缺乏docbase時,都以ROOT做爲目錄。如下是幾個定義示例:
# 虛擬主機中沒有定義任何context,將以appBase下的ROOT做爲默認處理路徑 <Host appBase="webapps"> </Host> # 沒有定義path=""的context,但定義了path非空的context,也將以ROOT做爲默認處理路徑 # 若是下面的Context容器中省略docBase屬性,則推斷出該context的docBase路徑爲appBase/xuexi <Host appBase="webapps"> <Context path="/xuexi" docBase="webappPATH" /> </Host> # 某個context定義了path="",該context將做爲默認context # 但該默認context若是沒有定義docBase,將推斷出其docBase路徑爲appBase/ROOT <Host appBase="webapps"> <Context path="" docBase="webappPATH" /> </Host> # 某個context定義了path="",該context將做爲默認context # 下面的默認context明肯定義了docBase <Host appBase="webapps"> <Context path="" docBase="webappPATH" /> </Host>
舉個直觀的例子,若是某個Host配置以下。
<Host name="www.xiaofang.com" appBase="/www/xiaofang" unpackWARs="true" autoDeploy="true"> <Context path="/xuexi" docBase="xuexi" reloadable="true" /> </Host>
那麼瀏覽器訪問http://www.xiaofang.com:8080/xuexi/
將請求/www/xiaofang/xuexi/index.jsp
。
因爲沒有定義path=""的Context組件,所以瀏覽器訪問http://www.xiaofang.com:8080
將請求/www/xiaofang/ROOT/index.jsp
。注意,是ROOT目錄。
若是加上<Context path="" docBase="" reloadable="true" />
,則訪問http://www.xiaofang.com:8080
將請求/www/xiaofang/index.jsp
。注意,不是ROOT目錄,而是相對於appBase的根目錄,即/www/xiaofang。
儘管本文解釋了一大堆關於appBase和docBase的設置,但通常都會採用大衆所熟知的配置方式:appBase設置爲"webapps",即$CATALINA_HOME/webapps,而docBase設置爲webapps下的webapp應用名。這樣配置不只符合eclipse部署webapp時默認的部署目錄結構(eclipse部署應用時,將WebContent下的內容複製到docBase下,將servlet java源代碼編譯後的class文件複製到WEB-INF/classes目錄下),更利於維護webapp和相關配置。例如:
<Context docBase="MyWeb" path="/MyWeb" reloadable="true" /> <Context docBase="SecondWeb" path="/SecondWeb" reloadable="true" /> <Context docBase="WEB" path="/WEB" reloadable="true" />
但這樣的配置有個缺點,由於項目名稱通常都會帶有大寫字母,使得在瀏覽器訪問時,也要帶有大寫字母。例如輸入http://www.a.com/MyWeb/index.jsp
。所以,可採用另外一種配置方式:設置Host的appBase爲webapps下的某個目錄,而後在path上配置uri匹配路徑。以下:
<Host name="www.xiaofang.com" appBase="webapps/MyWeb" unpackWARs="true" autoDeploy="true"> <Context path="/xuexi" docBase="xuexi" reloadable="true" /> <Context path="" docBase="" reloadable="true" /> </Host>
注意:path不能以「/」結尾
Valve中文意思是閥門,相似於過濾器,它能夠工做於Engine和Host/Context之間、Host和Context之間以及Context和Web應用程序的某資源之間。一個容器內能夠創建多個Valve,並且Valve定義的次序也決定了它們生效的次序。
有多種不一樣的Valve:
其中RemoteHostValve和RemoteAddrValve能夠分別用來實現基於主機名稱和基於IP地址的訪問控制,控制自己能夠經過allow或deny來進行定義,這有點相似於Apache的訪問控制功能。以下面的Valve實現了僅容許本機訪問/probe:
<Context privileged="true" path="/probe" docBase="probe"> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1"/> </Context>
其中相關屬性定義有:
另一個經常使用的Valve爲AccessLogValve,定義方式大體以下:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
其中prefix和suffix表示日誌文件的前綴名稱和後綴名稱。pattern表示記錄日誌時的信息和格式。
流程:
client --> nginx --> reverse_proxy --> http --> tomcat (http connector)
location ~* \.(jsp|do)$ { proxy_pass http://www.template.com:8080; }
client --> http --> httpd --> reverse_proxy --> (http|ajp) --> tomcat(http connector |ajp connector)
反代模塊:
主:proxy_module
子:proxy_module_http, proxy_module_ajp
第三方模塊:jk
ajp協議
httpd要擴展模塊須要藉助apxs,它是httpd的開發包httpd-devel中工具,因此先要安裝httpd-devel。若是是編譯安裝的httpd,則devel包已經裝好,若是是yum安裝,則須要額外安裝httpd-devel包。
yum -y install httpd httpd-devel
httpd虛擬主機反向代理
基於proxy_module_http
<VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / http://192.168.175.3:8080/ ProxyPassReverse / http://192.168.175.3:8080/ <Location /> Require all granted </Location> </VirtualHost>
基於proxy_module_ajp
<VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / ajp://192.168.175.3:8009/ ProxyPassReverse / ajp://192.168.175.3:8009/ <Location /> Require all granted </Location> </VirtualHost>
若是不想把status頁面反代至後端服務器能夠加上 ProxyPass /status !
<VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass /status ! ProxyPass / ajp://192.168.175.3:8009/ ProxyPassReverse / ajp://192.168.175.3:8009/ <Location /> Require all granted </Location> </VirtualHost>
apache指令說明:
若是Proxy指定是以balancer://開頭,即用於負載均衡集羣時,其還能夠接受一些特殊的參數,以下:
lbmethod:apache實現負載均衡的調度算法,默認是byrequests,即基於權重將統計請求個數進行調度,bytraffic則執行基於權重的流量計數調度,bybusyness經過考量每一個後端服務器的當前負載進行調度
maxattempts:放棄請求以前實現故障轉移的次數,默認爲1,其最大值不該該大於總的節點數。
nofailover:取值爲on或off,設置爲on時表示後端服務器故障時,用戶的session將損壞,所以,在後端服務器不支持session複製時可將其設置爲on
stickysession:調度器sticky session的名字,根據web程序語言的不一樣,其值爲JSESSIONID或PHPSESSIONID
上述指令除了能在balancer://或ProxyPass中設定以外,也可使用ProxySet指令直接進行設置,如:
<Proxy balancer://hotcluster> BalancerMember http://www1.template.com:8080 loadfactor=1 BalancerMember http://www2.template.com:8080 loadfactor=2 ProxySet lbmethod=bytraffic </Proxy>
ProxyPassReverse:用於讓apache調整HTTP重定向響應報文中的Location、Content-Location及URI標籤所對應的URL,在反向代理環境中必須使用此指令避免重定向繞過proxy服務器
在http.conf全局配置文件中配置以下內容:
ProxyRequests off <Proxy balancer://lbcluster1> BalancerMember ajp://172.16.100.1:8009 loadfactor=10 route=TomcatA BalancerMember ajp://172.16.100.2:8009 loadfactor=10 route=TomcatB </Proxy> <VirtualHost *:80> ServerAdmin admin@163.com ServerName www.template.com ProxyPass / balancer://lbcluster1/ ProxyPassReverse / balancer://lbcluster1/ </VirtualHost> <Proxy balancer://hotcluster> BalancerMember http://www1.template.com:8080 loadfactor=1 BalancerMember http://www2.template.com:8080 loadfactor=2 ProxySet lbmethod=bytraffic </Proxy>
<Proxy balancer://lbcluster1> BalancerMember http://192.168.175.4:8080 loadfactor=10 route=TomcatA BalancerMember http://192.168.175.5:8080 loadfactor=10 route=TomcatB </Proxy> <VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / balancer://lbcluster1/ ProxyPassReverse / balancer://lbcluster1/ <Location /> Require all granted </Location> </VirtualHost>
若是須要會話綁定,可像以下配置:
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED <Proxy balancer://lbcluster1> BalancerMember http://192.168.175.4:8080 loadfactor=10 route=TomcatA BalancerMember http://192.168.175.5:8080 loadfactor=10 route=TomcatB ProxySet stickysession=ROUTEID </Proxy> <VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / balancer://lbcluster1/ ProxyPassReverse / balancer://lbcluster1/ <Location /> Require all granted </Location> </VirtualHost>
基於ajp實現負載均衡:
#Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED <Proxy balancer://lbcluster1> BalancerMember ajp://192.168.175.4:8009 loadfactor=10 route=TomcatA BalancerMember ajp://192.168.175.5:8009 loadfactor=10 route=TomcatB ProxySet stickysession=ROUTEID </Proxy> <VirtualHost *:80> ServerName www.template.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / balancer://lbcluster1/ ProxyPassReverse / balancer://lbcluster1/ <Location /> Require all granted </Location> </VirtualHost>
配置apache經過mod_jk模塊與tomcat鏈接
mod_jk是ASF的一項目,是一工做於apache端基於AJP協議與tomcat通訊的鏈接器,它是apache的一個模塊,是AJP協議的客戶端(服務端是Tomcat的AJP鏈接器)
apache要使用mod_jk鏈接器,須要在啓動時加載此鏈接器的模塊,爲了便於管理mod_jk模塊相關的配置,這裏使用一個專門的配置文件/etc/httpd/extra/httpd-jk.conf來保存相關指令及其設置,其內容以下:
#Load the mod_jk LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/extra/worker.properties JkLogFile logs/mod_jk.log JkLogLevel debug JkMount /* TomcatA JkMount /status stat1
當前最新穩定版的mod_jk是1.2.42版本。
mod_jk下載地址:http://tomcat.apache.org/download-connectors.cgi。
mod_jk官方手冊:http://tomcat.apache.org/connectors-doc/。
httpd要擴展模塊須要藉助apxs,它是httpd的開發包httpd-devel中工具,因此先要安裝httpd-devel。若是是編譯安裝的httpd,則devel包已經裝好,若是是yum安裝,則須要額外安裝httpd-devel包。
此處爲了方便,httpd使用yum安裝。因此編譯mod_jk的方式以下:
yum -y install httpd httpd-devel tar xf tomcat-connectors-1.2.42-src.tar.gz cd tomcat-connectors-1.2.42-src/native/ ./configure --with-apxs=/usr/bin/apxs --prefix=/usr/local/tomcat/mod_jk make && make install
此處暫先配置httpd與其中一個tomcat(192.168.100.22)鏈接。後文在說明負載均衡時再引入另外一個tomcat。
先提供一個額外的httpd配置文件。
[root@xuexi ~]# cat /etc/httpd/conf.d/mod_jk.conf LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/conf.d/workers.properties JkLogFile logs/mod_jk.log JkLogLevel debug ######### "JkMount /* TomcatA" will send all request to TomcatA ######## JkMount /*.jsp TomcatA JkMount /status/* statA JkUnMount /images/* TomcatA JkUnMount /css/*.* TomcatA JkUnMount /css_js/* TomcatA JkUnMount /*.html TomcatA JkUnMount /*.js TomcatA
mod_jk的配置文件官方手冊:http://tomcat.apache.org/connectors-doc/reference/apache.html。如下是幾個經常使用的指令說明
LoadModule
指令用於裝載mod_jk相關模塊,除此以外還須要在httpd的配置文件中設置其它一些指令來配置其工做屬性。如:JkWorkersFile
用於指定保存了worker相關工做屬性定義(見下文)的配置文件。JkLogFile
用於指定mod_jk模塊的日誌文件。JkLogLevel
用於指定日誌級別(info,error,debug),此外還可使用JkRequestLogFormat自定義日誌信息格式。JkMount
(格式:JkMount )則用於控制URL與Tomcat workers的對應關係。能夠理解爲轉發請求的意思,例如"/status/*"表示url地址後加上/status/可轉發至statA這個worker上。注意,JkMount匹配的URL是相對的。若是JkMount指令放在Location指令中,如<Location /app>
,則JkMount將從/app的後面開始匹配。JkMount和JkUnMount是很重要的指令,mod_jk性能之因此比mod_proxy好,就是由於經過這兩個指令能夠實現動靜分離,使得只將動態請求轉發給tomcat。其中JkMount指定要轉發給tomcat處理的請求,JkUnMount指定明確不轉發給tomcat而是在本地處理的請求。雖然不指定JkUnMount時,也表示不轉發給tomcat,但若是有重疊時,則應該指定JkUnMount。例以下面的例子,除了/myapp/下的js文件,其餘都轉發給tomcat1處理。
JkMount /myapp/* tomcat1 JkUnMount /myapp/*.js tomcat1
對於apache來講,每個後端Tomcat實例中的engine均可以視做一個worker,而每個worker的地址、Connector的端口等信息都須要在apache端指定以即可以識別並使用這些worker。配置這些信息的文件一般爲"workers.properties",其具體路徑是使用前面介紹過的JkWorkersFile指定的。在apache啓動時,mod_jk會掃描此文件獲取每個worker配置信息。如這裏使用/etc/httpd/conf.d/workers.properties
。
workers.properties文件通常由兩類指令組成:一是mod_jk能夠鏈接的各worker名稱列表,二是每個worker的屬性配置信息。詳細的配置方法見官方手冊:http://tomcat.apache.org/connectors-doc/reference/workers.html。
如下是和上述/etc/httpd/conf.d/mod_jk.conf中配置相對應的/etc/httpd/conf.d/workers.properties。
[root@xuexi tomcat]# cat /etc/httpd/conf.d/workers.properties worker.list=TomcatA,statA worker.TomcatA.type=ajp13 worker.TomcatA.host=192.168.100.22 worker.TomcatA.port=8009 worker.TomcatA.lbfactor=1 worker.statA.type = status
關於worker的配置,它們分別遵循以下使用語法。
worker.list = <a comma separated list of worker_name> worker.<worker_name>.<property>=<property value>
其中worker.list指令能夠重複指定屢次。worker_name是Tomcat中engine組件中jvmRoute屬性的值(jvmRoute能夠不指定,此時worker_name僅用於標識worker)。
根據工做機制的不一樣,worker有多種不一樣的類型,每一個worker都須要指定其類型,即設定woker..type項。常見的類型以下:其中ajp13是默認值。
因爲status是狀態監控頁面,因此應該保證其安全性,能夠在httpd的配置文件中加入如下控制列表:
# 注意,必須加上尾隨斜線,由於在mod_jk.conf中已經明確了"/status/*" # For http 2.2 <Location /status/> Order deny,allow Deny from all Allow from 192.168.100.0/24 </Location> # For http 2.4 <Location /status/> Requrie ip 192.168.100 </Location>
除了type屬性外,worker其它常見的屬性有:
除了type屬性外,worker其它常見的屬性有:
另外,在負載均衡模式中專用的屬性還有:
至此,一個基於mod_jk模塊與後端名爲TomcatA的worker通訊的配置已經完成,重啓httpd服務便可生效。
使用mod_jk實現tomcat的負載均衡有一個好處,tomcat上能夠禁用http協議(將監聽此協議的Connector配置刪除便可),防止外界直接經過http請求tomcat。
配置apache,使其支持負載均衡,修改/etc/httpd/conf.d/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 /*.jsp TomcatLB JkMount /status/* statA
編輯/etc/httpd/conf.d/workers.properties,修改成以下內容:爲測試負載效果,不啓用stick_session。
worker.list=TomcatLB,statA worker.statA.type=status worker.TomcatLB.type=lb worker.TomcatLB.sticky_session=false worker.TomcatLB.balance_workers=TomcatA,TomcatB worker.TomcatA.type=ajp13 worker.TomcatA.host=192.168.175.4 worker.TomcatA.port=8009 worker.TomcatA.lbfactor=5 worker.TomcatB.type=ajp13 worker.TomcatB.host=192.168.175.5 worker.TomcatB.port=8009 worker.TomcatB.lbfactor=10
在mod_jk負載均衡中,後端tomcat的engine組件須要添加jvmRoute參數,該參數會爲當前server實例設置全局唯一標識符,所以每個實例的jvmRoute的值均不能相同,且jvmRoute的值必須等於balance_workers的成員值。對於上面的配置,Engine應該以下設置:此處還修改了name,但這不是要求要修改的。
<!-- 在tomcatA上設置 --> <Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA"> <!-- 在tomcatB上設置 --> <Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatB">
添加index.jsp,內容以下:
<%@ 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>
默認爲StandardManager
持久會話管理器(PersistentManager)
FileStore:保存至文件中的示例
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true"> <Store className="org.apache.catalina.session.FileStore" directory="/data/tomcat-sessions" /> </Manager>
JDBC:保存至JDBCStore中的示例
<Manager className="org.apache.catalina.session.PersistenManager" saveOnRestart="true"> <Store className="org.apache.catalina.session.JDBCStore" driverName="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mydb?user=jb;password=pw" /> </Manager>
DeltaManager:經過多播同步session
配置參考https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html
分別在server.xml HOST標籤中添加以下:
<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="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.MessageDispatchInterceptor"/> </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.ClusterSessionListener"/> </Cluster>
注意:爲須要使用session cluster的webapps 開啓 session distribution功能
在WEB-INF/web.xml中添加 <distributable />
tomcat實現的session集羣,與負載均衡器無關
BackupManager:兩兩作成一個集羣
session集羣示例配置文件:
<?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"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- 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" /> <!-- 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 Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS 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/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the APR/native implementation which always uses OpenSSL for TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeyFile="conf/localhost-rsa-key.pem" certificateFile="conf/localhost-rsa-cert.pem" certificateChainFile="conf/localhost-rsa-chain.pem" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" 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="jvm1"> --> <Engine name="Catalina" defaultHost="node2.template.com" jvmRoute="TomcatA"> <!--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 "%r" %s %b" /> </Host> <Host name="node2.template.com" appBase="/data/webapps" autoDeploy="true"> <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="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.MessageDispatchInterceptor"/> </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.ClusterSessionListener"/> </Cluster> <Context path="" docBase="ROOT" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs" prefix="node2_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
TomcatB
<?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"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- 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" /> <!-- 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 Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS 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/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the APR/native implementation which always uses OpenSSL for TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeyFile="conf/localhost-rsa-key.pem" certificateFile="conf/localhost-rsa-cert.pem" certificateChainFile="conf/localhost-rsa-chain.pem" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" 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="jvm1"> --> <Engine name="Catalina" defaultHost="node1.template.com" jvmRoute="TomcatB"> <!--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 "%r" %s %b" /> </Host> <Host name="node1.template.com" appBase="/data/webapps" autoDeploy="true"> <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="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.MessageDispatchInterceptor"/> </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.ClusterSessionListener"/> </Cluster> <Context path="" docBase="ROOT" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs" prefix="node1_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>