自2006年後Sun分拆Java技術爲三個方向:Java 2 SE(標準版) Java 2 EE(企業版) Java 2 ME(移動端)
css
TOMCAT是Java 2 EE技術體系的不完整實現,不少API仍然不能和J2EE相比擬,因爲Sun在後TOMCAT算是Apache基金會中和apache並驅前行的頂級項目,最新的Servlet 和JSP 規範老是能在Tomcat 中獲得體現。html
但TOMCAT並不是惟一的選擇,由於Tomcat 技術先進、性能穩定,並且免費,於是深受Java 愛好者的喜好並獲得了部分軟件開發商的承認,成爲目前比較流行的JAVA應用服務器。前端
商業實現:java
WebSphere, WebLogic, Oc4j, Glassfish, Geronimo, JOnAS, JBoss, ...node
開源實現:linux
Tomcat, Jetty, Resin, ...nginx
其中JSP在Tomcat中運行由jasper將.jsp內容自動轉化爲java代碼並加載入類庫git
.jsp -->jasper--> .java --> javac --> .class --> jvm ## 注意:基於jasper將靜態輸出的數據轉爲java代碼進行輸出,結果爲servlet規範的代碼;
今天主要爲了實現Tomcat的會話保持,也就是會話粘性,其實實現Tomcat Cluster或者TOmcat+memcached以前就有不少方法,但大致上分爲github
代理端會話粘性:若其中一個代理出現問題,會話粘性單點失效web
nginx: ip_hash
haproxy: source
lvs: sh
集羣會話同步:Tocmat會話兩兩互爲同步,單並不適合大流量,Tomcat性能降低
Tomcat: delta session manager
會話共享:高效,但配置較爲麻煩依賴於第三方插件,淡然還有不少方案,只是這裏不一一推薦
Tomcat+Memcached/Redis
今天主要研究Tomcat+Memcached,基本環境部署階段各個節點應先進行時間同步
--> 基本環境:
192.168.2.128 node1 Nginx
192.168.2.129 node2 Tomcat1
192.168.2.130 node3 Tomcat2
本次環境涉及到的軟件包與插件雲地址:https://pan.baidu.com/s/1ZL4gLbOdL2F56sDlmpFBwg 提取碼:j3m7
安裝Tomcat
安裝Tomcat以前首先安裝jdk環境,jdk分爲openjdk和Oracle jdk,OracleJDK做爲openjdk的穩定功能收錄版
yum安裝方式:
yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel ##java-1.8.0-openjdk-devel中包含了一些jvm狀態分析工具,好比jps和jstat yum install tomcat tomcat-lib tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp
Tar包安裝:
1. 安裝JDK:
[root@node2 ~]# rpm -ivh jdk-8u201-linux-x64.rpm [root@node2 profile.d]# cat /etc/profile.d/jdk.sh export JAVA_HOME=/usr/java/default export PATH=$JAVA_HOME/bin:$PATH [root@node2 profile.d]# . /etc/profile.d/jdk.sh
2. 安裝Tomcat:
[root@node2 ~]# tar xf apache-tomcat-7.0.92.tar.gz -C /usr/local/ [root@node2 local]# ln -s apache-tomcat-7.0.92 tomcat [root@node2 profile.d]# cat tomcat.sh export TOMCAT_HOME=/usr/local/tomcat export PATH=$TOMCAT_HOME/bin:$PATH [root@node2 profile.d]# . /etc/profile.d/tomcat.sh
3. 配置Tomcat,編寫jsp
[root@node2 ~]# mkdir -pv /usr/local/tomcat/webapps/test/{classes,lib,META-INF,WEB-INF} [root@node2 ~]# cat /usr/local/tomcat/webapps/test/index.jsp <%@ page language="java" %> <html> <head><title>TomcatB</title></head> <body> <h1><font color="blue">TomcatB.ifan.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("ifan.com","ifan.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
4. 檢查配置文件並啓動服務:
[root@node2 test]# catalina.sh configtest [root@node2 test]# catalina.sh start
檢查端口:8080 8009 8005(啓動較慢)
分別訪問192.168.2.129:8080和192.168.2.130:8080以及http://url:8080/test正常便可
因爲與TOMCAT默認通信的方式有兩種:
http協議(默認8080端口)支持nginx,apache等http協議前端服務器
ajp協議(默認8009端口)僅Apache支持,若是不使用則能夠關閉
另外的8005端口爲Tomcat的管理端口,聽說還有jk的連接方式,不過這個項目好像已經被apache基金會廢棄了,不在研究
安裝NGINX:
[root@node1 ~]# yum install nginx -y [root@node1 ~]# cat /etc/nginx/conf.d/http-tomcat.conf
配置NGINX服務:
[root@node1 ~]# cat /etc/nginx/conf.d/nginx_tomcat.conf upstream tcsrv { # ip_hash; ##這裏採用Tomcat Cluster的會話複製來實現就再也不使用ip_hash,使用基本輪訓便可 server 192.168.2.129:8080 weight=1; server 192.168.2.130:8080 weight=1; } server{ listen 80; server_name http.ilinux.io; proxy_set_header X-Forwarded-For $remote_addr; ##將用戶客戶端真實IP傳遞給Tomcat,httpd2.4無需配置透傳,Tomcat自動得到的就是真實IP location / { proxy_pass http://tcsrv; } }
配置ubuntu本地hosts:
ifan@ifan-PC:~$ cat /etc/hosts
127.0.0.1localhost
0.0.0.0 account.jetbrains.com
127.0.1.1 ifan-PC
192.168.2.128 http.ilinux.io ajp.ilinux.io
測試訪問:
http://http.ilinux.io 可以輪訓看到TomcatA和B便可
Tomcat Cluster集羣會話同步配置:
拓撲圖:
1. 在開始以前咱們首先備份一下配置文件:
[root@node2 ~]# cp /usr/local/tomcat/conf/server.xml{,.bak}
2. 編輯集羣內每臺tomcat主配置文件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" <!-- auto須要將本機主機名在本機的hosts內作ip映射,不然會bind錯誤 --> port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <!-- 最大線程數,能夠理解爲集羣服務器總數爲N,則該值爲N-1 --> <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>
3. 在test項目單獨複製web.xml並在web-app標籤內配置<distributable/>
[root@node2 ~]# cp /usr/local/tomcat/conf/web.xml /usr/local/tomcat/webapps/test/WEB-INF/ [root@node2 ~]# vim /usr/local/tomcat/webapps/test/WEB-INF/web.xml <web-app> ... <distributable/> ... web-app/>
4. 配置tomcat主機對本機主機名hosts解析
[root@node2 ~]# cat /etc/hosts 192.168.2.129 node2 [root@node2 ~]# cat /etc/hosts 192.168.2.130 node3
5. 檢測配置,並啓動服務:
[root@node2 ~]# catalina.sh configtest [root@node2 ~]# catalina.sh start;tailf /usr/local/tomcat/logs/catalina.2019-02-22.log
6. 再次訪問http://http.ilinux.io/test,能夠留意到Session ID 是一致的,這就說明當前端HA/NGINX/LVS不管如何調度到集羣中任何主機,那麼會話都是持續保持的
這就是Tomcat自身集羣實現的Session共享功能,可是因爲這種Tomcat自己性能就比較低,集羣自己實現相互複製就更是雪上加霜,因此不建議在併發時或者集羣數量多時使用
這裏建議使用旁掛式Memcache/Redis方案
咱們緊接着上述實驗來實現Nginx+Tomcat+Memcached
環境:
192.168.2.128 node1 Nginx
192.168.2.129 node2 Tomcat1+Memcached
192.168.2.130 node3 Tomcat2+Memcached
實現這種旁掛式須要Tomcat鏈接Memcached的擴展,這裏藉助第三方的插件來實現,
訪問全球最大同×××流社區github,具體連接:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
拓撲圖:
這種原理能夠理解爲
客戶端請求到達前端nginx調度器並分配到後端某tomcat節點時,tomcat會優先使用本機內存保存session,當一個請求結束後,tomcat會經過第三方組件(kryo,javolution,xstream,flexjson)把session序列化併發送到memcached節點上存放做備份,第二次請求時,若是本地有session就直接返回,第二次請求結束,把session修改後的信息更新到後端的memcached服務器,以這樣的方式來保持本地的session與memcached上的session同步。當這個tomcat節點宕機時,那麼用戶的下一次請求就會被前端的負載均衡器路由到另外一個tomcat節點上,而這個節點上並無這個用戶的session信息,這個節點就從memcached服務器上去讀取session,並把session保存到本地的內存,當請求結束,session又被修改,再送回到memcached進行存放備份
當後端配置了多臺memcached時,tomcat在更新session信息時會同時向多個memcached節點更新session,當一個memcached節點故障時,tomcat能夠從選擇一個正常工做的memcached節點讀取session信息來發送給用戶的瀏覽器,讓其重置session信息,這樣,memcached也達到了高可用的目的;
在開始以前首先進行序列化器的選擇,我這裏使用javolution,插件能夠在github上去下載;
複製插件到Tomcat的lib目錄中:
[root@node1 msm]# scp *.jar root@192.168.2.129:/usr/local/tomcat/lib/ [root@node1 msm]# scp *.jar root@192.168.2.130:/usr/local/tomcat/lib/ javolution-5.5.1.jar memcached-session-manager-2.1.1.jar memcached-session-manager-tc7-2.1.1.jar msm-javolution-serializer-2.1.1.jar spymemcached-2.11.6.jar
而後備份集羣server.xml文件:
[root@node2 ~]# mv /usr/local/tomcat/conf/server.xml{,.cluster}
還原Tomcat配置文件爲初始文件,並在Host標籤中添加如下信息:
[root@node2 ~]# cp /usr/local/tomcat/conf/server.xml.bak /usr/local/tomcat/conf/server.xml [root@node2 ~]# vim /usr/local/tomcat/conf/server.xml ... <Context path="/test" docBase="test" reloadable="true"> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="m1:192.168.2.129:11211,m2:192.168.2.130:11211" failoverNodes="m1" <!-- 當m2節點失效時,使用m1節點 --> requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" <!-- 如下後綴不進行會話保持 --> transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"/> </Context> ...
配置完成後,檢測配置並重啓Tomcat便可
再次查看是否可以會話共享
這樣便可實現了旁掛式session共享,當後端memcached出現故障時會馬上將使用另一臺memcached,各個Tomcat節點再將本地的session保存到新的memcached
最後說一下關於插件和Tomcat有一些是不兼容的,這裏也貼出個人配置信息,若是和個人tomcat不匹配則可能須要去https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration下載其餘版本
[root@node4 ~]# catalina.sh version Server version: Apache Tomcat/7.0.92 Server built: Nov 9 2018 11:07:44 UTC Server number: 7.0.92.0 OS Name: Linux OS Version: 3.10.0-327.el7.x86_64 Architecture: amd64 JVM Version: 1.8.0_201-b09 JVM Vendor: Oracle Corporation