tomcat 之 tomcat實例配置
1 概述
本文通過例子,介紹LNMT和LAMT,結合例子介紹如何實現如下的功能
(1) nginx + tomcat cluster, httpd(proxy_http_module)+tomcat cluster, httpd(proxy_ajp_module)+tomcat cluster;
(2) tomcat cluster升級為session cluster, 使用deltaManager;
(3) tomcat cluster將會話保存至memcached中;
2 概念介紹
LNMT:Linux Nginx MySQL Tomcat
Client (http) --> nginx (reverse proxy)(http) --> tomcat (http connector)
tomcat處理靜態資源效率比nginx低,而且消耗更多的資源,所以靜態資源一般有nginx作為web服務器處理
LAMT:Linux Apache(httpd) MySQL Tomcat
httpd的代理模塊有如下三個:
proxy_module
proxy_http_module:適配http協議客戶端;
proxy_ajp_module:適配ajp協議客戶端;
Client (http) --> httpd (proxy_http_module)(http) --> tomcat (http connector)
Client (http) --> httpd (proxy_ajp_module)(ajp) --> tomcat (ajp connector)
Client (http) --> httpd (mod_jk)(ajp) --> tomcat (ajp connector)
2.1 會話保持:
動態內容通常要追蹤用戶的會話,php或者jsp的會話會定期保存在磁盤,所以重新上線的機器,會話可以從磁盤恢復。但是,需要解決單點故障的問題。
(1) session sticky,會話綁定
source_ip:調度粒度粗糙,用於三四層調度
nginx: ip_hash
haproxy: source
lvs: sh
cookie:七層調度,粒度精細
nginx:hash
haproxy: cookie
(2) session cluster:delta session manager,會話集群,通過多播的方式,把會話傳給集群中的其他主機,保證集群中的所有主機都擁有相同的會話信息。這種調度的缺點是,當站點訪問量很大的時候,站點保存的會話會很多,在會話保持期間每一臺主機持有相同的會話,導致了對每臺服務器都造成壓力。
(3) session server:redis(store), memcached(cache)。節點的會話都保存在服務器中,一般是kv存儲,如redis(kv store,持久存儲)或者memcache(kv cache,不能持久存儲),redis和memcache的存儲都在內存中,沒有復雜的約束關系,(不能使用mysql,因為myslq的約束多,數據存取效率低,不過mysql具有事務的強移植).session server 建議配置為冗余模型。
服務器後端冗余,這裏有兩種機制:
客戶端存儲的時候,直接把會話存儲在後端的多臺緩存服務器上。
另一機制,後端存儲服務器自動同步數據。缺點是存在延時。後端服務可能存在故障,可以用keepalive來實現,但是節點太多的時候,keepalive就實現不了,這個時候,可以使用服務註冊(服務發現+)來實現,在服務總線上註冊自己主機的信息。
2.2 Tomcat Cluster(session)
有三個方式
(1) session sticky
(2) session cluster:tomcat delta manager
(3) session server :借助memcached
Tomcat Cluster,有以下的方案構建集群
一個httpd調度用戶請求到tomcat,httpd有多種變化方式,所以有三種方式
(1) httpd + tomcat cluster,
httpd: mod_proxy, mod_proxy_http, mod_proxy_balancer
tomcat cluster:http connector
(2) httpd + tomcat cluster
httpd: mod_proxy, mod_proxy_ajp, mod_proxy_balancer
tomcat cluster:ajp connector
(3) httpd + tomcat cluster,需要額外編譯安裝,現在不流行了,httpd調度目前主要使用前兩種方式,以下將不演示該方法的實現
httpd: mod_jk
tomcat cluster:ajp connector,實現反代和會話保持
(4) nginx + tomcat cluster 一個nginx調度用戶請求到tomcat
3 例子
3.1 環境準備
實驗前首先實現時間同步和主機名解析
環境如下
host 172.18.50.75為www面向客戶端,作為調度器,兩種安裝方法,安裝nginx和httpd,這裏通過兩種方法演示調度器
172.18.50.72 和73,為tomcat server
安裝軟件; 172.18.50.72 和73
yum install java-1.8.0-openjdk-devel yum install tomcat tomcat-lib tomcat-admin-webapps tomcat-docs-webapp tomcat-webapps
172.18.50.72 和73 建議將主機名寫入hosts,如172.18.50.72 node1 ,73為node2 ;解析主機名
準備tomcat虛擬主機test和站點頁面
mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF vim /usr/share/tomcat/webapps/test/index.jsp
#頁面內容如下
<%@ page language="java" %> <html> <head><title>Tomcat7B</title></head> <body> <h1><font color="blue">Tomcat7B.sunny.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("sunny.com","sunny.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
重啟tomcat服務
systemctl restart tomcat
測試
在瀏覽器上測試,輸入http://172.18.50.72:8080/test和 http://172.18.50.73:8080/test可以看到藍色和紅色的相關session內容,到這裏環境環境準備完成
3.2 調度配置
實現調度這裏介紹三種方法
調度器配置參數
BalancerMember:
格式:BalancerMember [balancerurl] url [key=value [key=value ...]]
status:
D:worker被禁用,不會接受任何請求。
S:worker被管理性的停止。
I:worker處於忽略錯誤模式,並將始終被視為可用。
H:worker處於熱備份模式,只有在沒有其他可行的worker時才能使用。
E:worker處於錯誤狀態。
N:worker處於流失模式,只會接受發往自己的現有粘性會話,並忽略所有其他請求。
loadfactor:負載因子,即權重;
lbmethod:
設置調度算法,負載均衡算法三種:
byrequests 為roundrobin,
bybusiness:根據後端的繁忙程度來調度
bytraffic:根據流量來調度,根據流量較空閑來調度
stickysession:
平衡器粘滯的會話名稱。 該值通常設置為類似於JSESSIONID或PHPSESSIONID的值,並且取決於支持會話的後端應用程序服務器。 如果後端應用程序服務器的cookie使用不同的名稱和url編碼的id使用不同的名稱(如servlet容器),請使用| 分開他們。 第一部分是cookie,第二部分是路徑。在Apache HTTP Server 2.4.4及更高版本中可用。
方法一:配置nginx,實現調度器
vim /etc/nginx/conf.d/vhost.conf upstream tcsrvs { server 172.18.50.72:8080; server 172.18.50.73:8080; } server { location / { proxy_pass http://tcsrvs; } }
重啟nginx,在瀏覽器輸入 http:172.18.50.75/test可以查看到不同內容,已經實現調度
或者用curl命令測試調度
for i in {1..10}; do curl -s http://172.18.50.75/test/index.jsp | grep -i tomcat;done
方法二:配置httpd,基於http模塊實現調度
配置如下
vim /etc/httpd/conf.d/http-tomcat.conf <proxy balancer://tcsrvs> BalancerMember http://172.18.50.72:8080 BalancerMember http://172.18.50.73:8080 ProxySet lbmethod=byrequests </Proxy> <VirtualHost *:80> ServerName lb.sunny.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / balancer://tcsrvs/ ProxyPassReverse / balancer://tcsrvs/ <Location /> Require all granted </Location> </VirtualHost>
測試
重啟http,在瀏覽器輸入 http:172.18.50.75/test可以查看到不同內容,已經實現調度
或者用curl命令測試調度
for i in {1..10}; do curl -s http://172.18.50.75/test/index.jsp | grep -i tomcat;done
方法三:配置httpd,基於ajp模塊實現調度, 後端tomcat依靠ajp協議提供服務
vim /etc/httpd/conf.d/ajp-tomcat.conf <proxy balancer://tcsrvs> BalancerMember ajp://172.18.50.72:8009 BalancerMember ajp://172.18.50.73:8009 ProxySet lbmethod=byrequests </Proxy> <VirtualHost *:80> ServerName lb.sunny.com ProxyVia On ProxyRequests Off ProxyPreserveHost On <Proxy *> Require all granted </Proxy> ProxyPass / balancer://tcsrvs/ ProxyPassReverse / balancer://tcsrvs/ <Location /> Require all granted </Location> </VirtualHost>
測試
重啟http,在瀏覽器輸入 http:172.18.50.75/test可以查看到不同內容,已經實現調度
或者用curl命令測試調度
for i in {1..10}; do curl -s http://172.18.50.75/test/index.jsp | grep -i tomcat;done
另外,可以關閉掉後端一臺主機,會發現調度器75已經不會再調度請求到對應的失敗主機上,因為httpd默認有健康檢查功能,移除主機速度快,但是當主機恢復正常後,即被關閉的服務器重新啟動tomcat 8005主進程後,健康檢查就很慎重,要一段時間後才會重新添加恢復的主機為正常
標記後端主機不可用,就不會再次調度到該臺被標記位D的主機,如下例子,則將不會被調度到172.18.50.72這臺機器上
<proxy balancer://tcsrvs> BalancerMember ajp://172.18.50.72:8009 status=D BalancerMember ajp://172.18.50.73:8009 ProxySet lbmethod=byrequests </Proxy>
httpd的balance模塊
httpd的balance模塊有內鍵的狀態管理接口,可以啟用 balancer-manager,內鍵管理接口,啟用內鍵管理器,不要開放給任何人訪問,如指定固定ip 172.18.50.99這臺主機才能訪問該鏈接。在httpd的子配置文件裏添加如下的配置
<Location /balancer-manager> SetHandler balancer-manager ProxyPass ! Require all granted order deny,allow deny from all allow from 172.18.50.99 </Location>
測試,在瀏覽器裏輸入http://172.18.50.75/balancer-manager 查看。同時,該頁面的鏈接部分,點擊進入後可以實現相關的管理配置。
到這裏,調度的方法介紹完成。
3.3 session sticky
基於cookie會話綁定,依賴調度器,需要在調度器上配置
基於ajp協議調度,當後端服務器狀態不變時(基於env=BALANCER_ROUTE_CHANGED這個關鍵字實現),不會重新調度,同一請求會調度到同一機器上
http的配置文件,env這個選項表示當後端服務器發生變化的時候,會話綁定才會變化,否則不變
調度器75上子配置文件配置如下
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED <proxy balancer://tcsrvs> BalancerMember ajp://172.18.50.72:8009 route=Tomcat7B BalancerMember ajp://172.18.50.73:8009 route=Tomcat7C ProxySet lbmethod=byrequests ProxySet stickysession=ROUTEID </Proxy>
virtualhost部分配置不變,見上面調度器的配置
tomcat 72和73上配置如下,只需在engine配置段裏添加jvmRoute的鍵值對即可
vim /usr/share/tomcat/conf/server.xml <Engine name="Catalina" defaultHost="localhost" jvmRoute="tc7b">
測試,在瀏覽器上輸入http://172.18.50.75/test/,當後端的服務器不發生變化,則同一請求始終會被調度到同一臺服務器上,得到的session和內容是一樣的。
httpd基於http協議的調度方法和ajp協議基本一致。更改協議和端口即可。
註意這裏http不支持基於源地址綁定。nginx可以基於源地址進行調度,這裏的調度也可以使用haproxy來實現。
這裏還有另一種配置實現了會話的綁定,如通過proxypass 配置段裏添加stickysession=jsessionid 來構建,但是一般不采用如下的配置,因為有可能jssesionid帶有服務器本身的內容,如節點的標誌,導致hash值每次不一樣,不能實現會話綁定的效果,所以一般不基於這種方式來實現會話綁定,這裏就不做配置,建議使用上面的例子來實現會話的綁定。
3.4 session cluster
session replication cluster方法實現會話集群即節點會變,但是會話id不變的效果
主要在後端服務器把後端的服務器構建成會話集群,每一個節點本地獲取到新的會話或者更改會話值的時候,要通過後端的會話集群信道,將會話同步到後端的所有服務器上
通過多播實現session的傳輸復制到每一臺後端服務器上,每個收到新的會話信息時,會更新自己的會話集,所以後續調度器根據調度算法隨意調度到任意主機,都保存對應的會話信息,可以處理請求,可以返回相應的信息。這裏的會話一般是通過多播發送的給其他主機,即基於多播實現會話擴散。
集群有多種會話管理器
persistent manager(持久會話管理器),默認的會話管理器,會話會被同步到磁盤內,即使關機,會話依然存在。
delta manager(會話管理器)使用多播集群構建replication cluster要通過delta manager會話管理器來實現,這裏可以理解為每一次傳遞都是通過增量傳遞,會話只傳遞更新的部分會話
backup manager (備用會話管理器) 工作邏輯是會話的復制只在有限的主機間復制,如兩臺,而不是全部的主機,調度時只調度到其中一臺,當這臺主機異常,才會調度到另一臺主機
這裏演示基於Delta Manager的會話綁定,不依賴於調度器,即不需要在前端調度器上配置會話綁定的配置,只需配置調度即可。在後端tomcat上配置cluster,是app級別的,如果直接配置在engine中,則對該engine對應的所有app都有效,也可以直接配置在app中,即一般是放在在host中,只對對應的app生效。
tomcat上相關配置介紹如下
(1) 配置啟用集群,將下列配置放置於<engine>或<host>中;多播地址建議不要使用默認的,節點設定為一致 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> #建議放在對應的host段裏 <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> #定義manager,表示調用哪個manager,如這裏使用deltamanager.可以使用會話ha功能,即會話可以同步到其他節點 <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" #綁定在本機正常通信的地址,auto自動找,不建議,綁定的地址為auto時,會自動解析本地主機名,並解析得出的IP地址作為使用的地址;建議直接設定本機ip,如172.18.50.75, port="4000" autoBind="100" selectorTimeout="5000" #挑選器的超時時間 maxThreads="6"/> #最大線程數,表示一共啟用多少線程來接收其他主機傳過來的會話,如集群4臺,這裏就設置為3就足夠了。 # Receiver表示定義一個接收器,接收別人傳過來的多播信息 <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> # Sender是定義如何把會話信息發送給同一集群中的其他節點 <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"/> #Interceptor解析器,解析當什麽時候 </Channel> # Channel是定義集群成員關系 <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> #valve閥門,考慮到jvmRoute <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監聽java集群資源是否發生變化,如果發生變化要如何變得集群的變化。 <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster> 確保Engine的jvmRoute屬性配置正確。 (2) 配置webapps 編輯WEB-INF/web.xml,添加<distributable/>元素;這個要手動添加
例子
編輯tomcat主機,
步驟一,修改配置文件,有兩個地方需要配置
一是engine裏需要添加jvmRoute配置
二是 Cluster配置放在host配置段裏,以下配置只需要調整組播地址和本機的ip,其他地方不需要調整。兩臺tomcat都需要配置
vim /usr/share/tomcat/conf/server.xml <Engine name="Catalina" defaultHost="localhost" jvmRoute="tc7b"> #以下放在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="172.18.50.72" #調整為本機的ip,不使用默認的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>
步驟二
集群會話的app的web.xml裏需要配置<distributable/>這個元素,配置在web.xml的web-app配置段裏即可。一般程序員開發的站點web.xml這個文件肯定是存在的,而且是放在WEB-INF目錄下,不過實驗環境沒有,所以就拷貝公共的web.xml到對應主機目錄下
cp /etc/tomcat/web.xml /usr/share/tomcat/webapps/test/WEB-INF/ vim /usr/share/tomcat/webapps/test/WEB-INF/web.xml <distributable/>
保存後退出。重啟tomcat服務器
測試:在瀏覽器上輸入http://172.18.50.75/test/,可以看到此時請求被調度到不同的機器上,但是,頁面上的session id始終保持不變。則實驗成功。說明在不同的服務器上已經有同一session id。即實現了會話集群即節點會變,但是會話不變。
3.5 session server
借助第三方的工具memcached實現,tomcat cluster將會話保存至memcached中,通過memcached來實現。把memcached當做tomcat的session server,不需要在前端做綁定會話,不需要在tomcat服務器綁定會話。後端的memcache需要做高可用,後端支持兩臺memcache,tomcat服務器開啟雙寫機制,所有要存儲的信息都同時寫入後端的兩臺memcache裏,讀取數據時可以只讀取一臺,當memcache主服務器掛掉,就啟用備用的memcache.支持分布式,空間不夠可以擴容
配置案例的介紹鏈接,如下:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
tomcat自身不直接把會話保存在memcache中,需要借助開發工具來實現。相應的項目官方代碼可以直接從github上搜到。資源鏈接:https://github.com/magro/memcached-session-manager
對tomcat而言,要把會話保存在memcache中,有以下幾種類庫
第一:要使用專門的會話管理工具memcache-session-manager的類庫,如 memcached-session-manager-${version}.jar 和 memcached-session-manager-tc7-${version}.jar(如tomcat是7版本)這個類庫
第二: 會話是保存在內存中,不支持流式化,借助流式化工具實現,流式化工具有如下四種,可以任意用一種,這些是類庫,需要裝入tomcat才能使用
kryo-serializer: msm-kryo-serializer, kryo-serializers-0.34+, kryo-3.x, minlog, reflectasm, asm-5.x, objenesis-2.x
javolution-serializer: msm-javolution-serializer, javolution-5.4.3.1
xstream-serializer: msm-xstream-serializer, xstream, xmlpull, xpp3_min
flexjson-serializer: msm-flexjson-serializer, flexjson
第三:支持適配對應存儲系統的類庫,如要使得tomcat和memcached能通信,要有能適配memcached客戶端的類庫,如 spymemcached-${version}.jar。如果存儲是redis,則要使用jedis-2.9.0.jar.
這裏介紹流式工具為javolution-serializer的部署
例子
步驟一
前端調度器上不需要做綁定的設置,只需要配置調度即可
步驟二
找兩臺服務器172.18.50.62和63,安裝memcached,並啟用memcached服務。
yum -y install memcached systemctl restart memcached
步驟三
後端tomcat 72和73 在如下的路徑放置相關的jar包
/usr/share/tomcat/webapps/test/WEB-INF/lib/路徑下放置兩個類庫
javolution-5.4.3.1.jar
msm-javolution-serializer-2.1.1.jar
/usr/share/tomcat/lib/路徑下放置三個類庫
memcached-session-manager-2.1.1.jar
memcached-session-manager-tc7-2.1.1.jar
spymemcached-2.12.3.jar
編輯配置文件server.xml,放置host配置段裏,如下
vim /usr/share/tomcat/conf/server <Context path="/test" docBase="/usr/share/tomcat/webapps/test" reloadable="true"> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:172.18.50.62:11211,n2:172.18.50.63:11211" failoverNodes="n1" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" /> </Context>
重啟tomcat服務器
測試
在瀏覽器裏輸入http://172.18.50.75/test,不管怎麽調度, session id始終不變,但是網頁上的其他內容已經發生變化,說明實驗成功。
本文出自 “陽光運維” 博客,請務必保留此出處http://ghbsunny.blog.51cto.com/7759574/1982321
tomcat 之 tomcat實例配置