自2006年后Sun分拆Java技术为三个方向:Java 2 SE(标准版) Java 2 EE(企业版) Java 2 ME(移动端)
TOMCAT是Java 2 EE技术体系的不完整实现,很多API仍然不能和J2EE相比拟,由于Sun在后TOMCAT算是Apache基金会中和apache并驱前行的顶级项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。
但TOMCAT并非唯一的选择,因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的JAVA应用服务器。
商业实现:
WebSphere, WebLogic, Oc4j, Glassfish, Geronimo, JOnAS, JBoss, ...
开源实现:
Tomcat, Jetty, Resin, ...
其中JSP在Tomcat中运行由jasper将.jsp内容自动转化为java代码并加载入类库
.jsp -->jasper--> .java --> javac --> .class --> jvm ## 注意:基于jasper将静态输出的数据转为java代码进行输出,结果为servlet规范的代码;
今天主要为了实现Tomcat的会话保持,也就是会话粘性,其实实现Tomcat Cluster或者TOmcat+memcached之前就有很多方法,但大体上分为
代理端会话粘性:若其中一个代理出现问题,会话粘性单点失效
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" %>TomcatB TomcatB.ifan.com
Session ID | <% session.setAttribute("ifan.com","ifan.com"); %><%= session.getId() %> |
Created on | <%= session.getCreationTime() %> |
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标签内添加以下信息
port="45564" frequency="500" dropTime="3000"/> port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
3. 在test项目单独复制web.xml并在web-app标签内配置
[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/>
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 [email protected]:/usr/local/tomcat/lib/ [root@node1 msm]# scp *.jar [email protected]:/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 ...... requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"/>
配置完成后,检测配置并重启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