Tomcat
一、Tomcat相关概念
Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。由于Tomcat本身也内含了一个HTTP服务器,它也可以被视作一个单独的Web服务器。但是,不能将Tomcat和Apache HTTP服务器混淆,Apache HTTP服务器是一个用C语言实现的HTTPWeb服务器;这两个HTTP web server不是捆绑在一起的。Apache Tomcat包含了一个配置管理工具,也可以通过编辑XML格式的配置文件来进行配置。Tomcat是Java 2 EE技术体系的不完整实现。
- JDK:java工具箱
- JRE:java运行时环境
- JVM:C语言研发,java虚拟机
- ajp:AJP13是定向包协议,httpd支持此协议,nginx不支持
- jsp:java server page
- jasper:负责将.jsp 转换为 .java
- applet:Applet或Java小应用程序是一种在Web环境下,运行于客户端的Java程序组件
- servlet:全称Java Servlet, 是用Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态Web内容,将.java转换成字节码
二、安装Tomcat
1、yum包安装
# yum install java-1.8.0-openjdk
# yum install tomcat tomcat-webapps tomcat-admin-webapps tomcat-docs-webapp
# java -version #查看java版本信息
# tomcat version #查看tomcat版本信息
启动服务:
# systemctl start tomcat
# ss -tnl
LISTEN 0 1 ::ffff:127.0.0.1:8005 #管理端口,建议关闭
LISTEN 0 100 :::8009 #AJP协议默认监听端口
LISTEN 0 100 :::8080 #HTTP协议默认监听端口
tomcat的目录结构:
配置文件目录:/etc/tomcat/
主配置文件:server.xml
webapps存放位置:/var/lib/tomcat/webapps/
环境配置文件:/etc/sysconfig/tomcat
2、官方发行版安装
安装JDK:
下载地址:http://www.oracle.com/technetwork/java/javase/downloads/
# rpm -ivh jdk-8u25-linux-x64.rpm
# ll /usr/java/ #默认安装路径
lrwxrwxrwx 1 root root 16 Jul 17 19:46 default -> /usr/java/latest
drwxr-xr-x 9 root root 268 Jul 17 19:46 jdk1.8.0_25
lrwxrwxrwx 1 root root 21 Jul 17 19:46 latest -> /usr/java/jdk1.8.0_25
# vim /etc/profile.d/java.sh #将java环境变量加入系统环境变量
export JAVA_HOME=/usr/java/latest
export PATH=$JAVA_HOME/bin:$PATH
# . /etc/profile.d/java.sh
安装Tomcat:
下载地址:http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.32/bin/apache-tomcat-8.5.32.tar.gz
# useradd tomcat
# tar xf apache-tomcat-8.5.32.tar.gz -C /usr/local/
# cd /usr/local/
local]# ln -sv apache-tomcat-8.5.32/ tomcat
local]# cd tomcat/
tomcat]# chgrp -R tomcat ./*
tomcat]# chown -R tomcat logs/ temp/ work/
tomcat]# chmod g+rx conf/
tomcat]# chmod g+r conf/*
# vim /etc/profile.d/tomcat.sh #配置环境变量
export CATALINA_BASE=/usr/local/tomcat
export PATH=$CATALINA_BASE/bin:$PATH
# . /etc/profile.d/tomcat.sh
# su - tomcat -c 'catalina.sh start'
# ls -1 /usr/local/tomcat/
bin:脚本及启动时用到的类
conf:配置文件目录
lib:库文件,Java类库,jar
logs:日志文件目录
temp:临时文件目录
webapps:webapp的默认目录
work:工作目录
# catalina.sh --help
commands:
debug #调试模式启动
jpda start #jpda的debug模式启动
run #前台启动
start #后台启动
stop #关闭
stop n #n秒后关闭
stop -force #强制关闭
stop n -force #n秒后强制关闭
configtest #测试配置文件语法
version #查看相关版本信息
# catalina.sh version
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/latest
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/8.5.32
Server built: Jun 20 2018 19:50:35 UTC
Server number: 8.5.32.0
OS Name: Linux
OS Version: 3.10.0-862.el7.x86_64
Architecture: amd64
JVM Version: 1.8.0_25-b17
JVM Vendor: Oracle Corporation
三、manager、host-manager和docs
依赖包:
- tomcat-webapps
- tomcat-admin-webapps
- tomcat-docs-webapp
1、配置:manager管理webapps应用程序
# vim /etc/tomcat/tomcat-users.xml
<role rolename="manager-gui"/>
<user username="admin" password="adminpass" roles="manager-gui"/>
# systemctl restart tomcat
2、配置:host-manager管理虚拟主机
# vim /etc/tomcat/tomcat-users.xml
<role rolename="admin-gui"/>
<user username="admin" password="admin" roles="manager-gui,admin-gui"/>
# systemctl restart tomcat
3、docs获取离线文档
四、Tomcat的配置参数
- server.xml:主配置文件
- web.xml:每个webapp只有“部署”后才能被访问,它的部署方式通常由web.xml进行定义,其存放位置为WEB-INF/目录中;此文件为所有的webapps提供默认部署相关的配置
- context.xml:每个webapp都可以专用的配置文件,它通常由专用的配置文件context.xml来定义,其存放位置为WEB-INF/目录中;此文件为所有的webapps提供默认配置
- tomcat-users.xml:用户认证的账号和密码文件
- catalina.policy:当使用-security选项启动tomcat时,用于为tomcat设置安全策略
- catalina.properties:Java属性的定义文件,用于设定类加载器路径,以及一些与JVM调优相关参数
- logging.properties:日志系统相关的配置
1、tomcat的核心组件:server.xml
配置文件框架:
<Server>
<Service>
<connector/>
<Engine>
<Host>
<Context>
<Valve/>
</Context/>
</Host>
</Engine>
</Service>
</Server>
每一个组件都由一个Java“类”实现,这些组件大体可分为以下几个类型:
- 顶级组件:Server
- 服务类组件:Service
- 连接器组件:http, https, ajp(apache jserv protocol)
- 容器类:Engine, Host, Context
- 被嵌套类:valve, logger, realm, loader, manager, ...
- 集群类组件:listener, cluster, ...
2、Tomcat的常用组件配置:
- Server:代表tomcat instance,即表现出的一个java进程;监听在8005端口,只接收“SHUTDOWN”。各server监听的端口不能相同,因此,在同一物理主机启动多个实例时,需要修改其监听端口为不同的端口;
- Service:用于实现将一个或多个connector组件关联至一个engine组件;
- Connector组件:负责接收请求,常见的有三类http/https/ajp;
port="8080" 监听的端口
protocol="HTTP/1.1" 协议
connectionTimeout="20000" 连接超时时间,单位ms,2秒
address:监听的IP地址;默认为本机所有可用地址;
maxThreads:最大并发连接数,默认为200;
enableLookups:是否启用DNS查询功能;
acceptCount:等待队列的最大长度;
secure:安全相关;
sslProtocol:加密传输相关;
- Engine组件:Servlet实例,即servlet引擎,其内部可以一个或多个host组件来定义站点; 通常需要通过defaultHost属性来定义默认的虚拟主机;
name=
defaultHost="localhost"
jvmRoute=
- Host组件:位于engine内部用于接收请求并进行相应处理的主机或虚拟主机
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
appBase:此Host的webapps的默认存放目录,指存放非归档的web应用程序的目录或归档的WAR文件目录路径;可以使用基于$CATALINA_BASE变量所定义的路径的相对路径;
autoDeploy:在Tomcat处于运行状态时,将某webapp放置于appBase所定义的目录中时,是否自动将其部署至tomcat;
- Context组件:相当于nginx中的alias的功能
<Context path="/PATH" docBase="/PATH/TO/SOMEDIR" reloadable=""/>
path:url路径
docBase:网页文件目录路径
- Valve组件:
定义访问日志:org.apache.catalina.valves.AccessLogValve
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
定义访问控制:org.apache.catalina.valves.RemoteAddrValve
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="172\.16\.100\.67"/>
3、组件配置示例:
- 配置示例:Host组件
[root@node1 ~]# vim /etc/tomcat/server.xml
<Engine>
...
<Host name="node1.dongfei.tech" appBase="/web/apps" unpackWARs="true" autoDeploy="true"/>
</Engine>
[root@node1 ~]# mkdir -pv /web/apps/ROOT/
[root@node1 ~]# vim /web/apps/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
[root@node1 ~]# systemctl restart tomcat
测试访问:http://node1.dongfei.tech:8080/
- 配置示例:Context组件
[root@node1 ~]# vim /etc/tomcat/server.xml
<Engine>
...
<Host name="node1.dongfei.tech" appBase="/web/apps" unpackWARs="true" autoDeploy="true">
<Context path="/testapp" docBase="/web/testapp" reloadable=""/>
</Host>
</Engine>
[root@node1 ~]# systemctl restart tomcat
[root@node1 ~]# mkdir -pv /web/testapp/ROOT
[root@node1 ~]# vim /web/testapp/index.jsp
...
测试访问:http://node1.dongfei.tech:8080/testapp/
- 配置示例:Valve组件
[root@node1 ~]# vim /etc/tomcat/server.xml
<Host name="node1.dongfei.tech" appBase="/web/apps" unpackWARs="true" autoDeploy="true">
<Context path="/testapp" docBase="/web/testapp" reloadable="">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1_test_access_" suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Context>
</Host>
[root@node1 ~]# systemctl restart tomcat
[root@node1 ~]# tail /var/log/tomcat/node1_test_access_2018-07-17.log
192.168.0.8 - - [17/Jul/2018:22:59:30 +0800] "GET /testapp/ HTTP/1.1" 200 334
3、JSP WebAPP的组织结构:
- index.jsp:主页;
- WEB-INF/:当前webapp的私有资源路径;通常用于存储当前webapp的web.xml和context.xml配置文件;
- META-INF/:类似于WEB-INF/;
- classes/:类文件,当前webapp所提供的类;
- lib/:类文件,当前webapp所提供的类,被打包为jar格式;
4、webapp归档格式:
- .war:webapp
- .jar:EJB的类打包文件;
- .rar:资源适配器类打包文件;
- .ear:企业级webapp;
五、部署(deploy)webapp
- deploy:将webapp的源文件放置于目标目录(网页程序文件存放目录),配置tomcat服务器能够基于web.xml和context.xml文件中定义的路径来访问此webapp;将其特有的类和依赖的类通过class loader装载至JVM;
- undeploy:反部署,停止webapp,并从tomcat实例上卸载webapp;
- start:启动处于停止状态的webapp;
- stop:停止webapp,不再向用户提供服务;其类依然在jvm上;
- redeploy:重新部署;
部署可分为自动部署和手动部署;手动部署又有冷部署和热部署:
- 冷部署:把webapp复制到指定的位置,而后才启动tomcat;
- 热部署:在不停止tomcat的前提下进行部署;部署工具有manager、ant脚本、tcd(tomcat client deployer)等;
示例:手动提供一测试类应用,并冷部署
[root@node1 ~]# mkdir -pv /var/lib/tomcat/webapps/test/{classes,lib,WEB-INF}
[root@node1 ~]# vim /var/lib/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<% out.println("hello world");
%>
</body>
</html>
访问:http://192.168.0.10:8080/test/
六、NT:nginx | httpd + tomcat
1、nginx和Tomcat通过http/https协议工作
配置Tomcat:
[root@tomcat ~]# mkdir -pv /data/webapp/ROOT/
[root@tomcat ~]# vim /data/webapp/ROOT/index.jsp #提供jsp测试页
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
[root@tomcat ~]# vim /data/webapp/ROOT/test.html #提供静态测试页
static page
[root@tomcat ~]# vim /etc/tomcat/server.xml #修改Tomcat配置,如下
<?xml version='1.0' encoding='utf-8'?>
<Server port="-1" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<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 address="127.0.0.1" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- <Connector address="127.0.0.1" port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
<Engine name="Catalina" defaultHost="node1.dongfei.tech">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<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>
<Host name="node1.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
[root@tomcat ~]# systemctl start tomcat
配置nginx:
[root@tomcat ~]# vim /etc/nginx/conf.d/nginx_tomcat.conf
server {
listen 80;
server_name node1.dongfei.tech;
index index.jsp index.html;
location / {
root "/data/webapp/ROOT/";
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
}
[root@tomcat ~]# nginx
测试访问:
2、httpd和Tomcat通过http/https协议工作
[root@tomcat ~]# httpd -M |grep proxy
proxy_module (shared) #代理模块
proxy_ajp_module (shared) #适配ajp协议客户端
proxy_balancer_module (shared)
proxy_connect_module (shared)
proxy_express_module (shared)
proxy_fcgi_module (shared)
proxy_fdpass_module (shared)
proxy_ftp_module (shared)
proxy_http_module (shared) #适配http协议客户端
proxy_scgi_module (shared)
proxy_wstunnel_module (shared)
配置Tomcat:如上
配置httpd:
[root@tomcat ~]# vim /etc/httpd/conf.d/http_tomcat.conf
<VirtualHost *:80>
ServerName node1.dongfei.tech
ProxyRequests Off #关闭正向代理
ProxyVia On
ProxyPreserveHost On #将请求头HOST发送给后端主机
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:8080/
<Location />
Require all granted
</Location>
</VirtualHost>
[root@tomcat ~]# systemctl start httpd
3、http和Tomcat通过ajp协议工作
配置Tomcat:
[root@tomcat ~]# vim /etc/tomcat/server.xml
<Connector address="127.0.0.1" port="8009" protocol="AJP/1.3" redirectPort="8443" />
[root@tomcat ~]# systemctl restart tomcat
配置httpd:
[root@tomcat ~]# vim /etc/httpd/conf.d/http_tomcat.conf
<VirtualHost *:80>
ServerName node1.dongfei.tech
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / ajp://127.0.0.1:8009/
<Location />
Require all granted
</Location>
</VirtualHost>
[root@tomcat ~]# systemctl restart httpd
七、nntm的会话保持实现
- session sticky:会话绑定
- source_ip:基于源地址做会话绑定;nginx: ip_hash,haproxy: source,lvs: sh
- cookie:基于cookie做会话绑定;nginx:hash,haproxy: cookie
1、httpd + nginx + tomcat cluster:基于cookie实现会话绑定
前端httpd调度器:
[root@Director ~]# httpd -M |grep balancer
proxy_balancer_module (shared)
[root@Director ~]# vim /etc/httpd/conf.d/httpd-tomcat.conf
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<proxy balancer://tcsrvs>
BalancerMember http://192.168.0.10:80 route=TomcatA loadfactor=1
BalancerMember http://192.168.0.11:80 route=TomcatB loadfactor=2
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:80>
ServerName www.dongfei.tech
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
[root@Director ~]# systemctl start httpd
tomcat-node-1:
[root@tomcat-node-1 ~]# vim /etc/nginx/conf.d/nginx_tomcat.conf
server {
listen 80 default_server;
server_name node1.dongfei.tech;
index index.jsp index.html;
location / {
root "/data/webapp/ROOT/";
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
}
[root@tomcat-node-1 ~]# vim /etc/tomcat/server.xml
<Server port="-1" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector address="127.0.0.1" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="node1.dongfei.tech" jvmRoute="TomcatA">
<Host name="node1.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
[root@tomcat-node-1 ~]# vim /data/webapp/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
[root@tomcat-node-1 ~]# systemctl start nginx tomcat
tomcat-node-2:
[root@tomcat-node-2 ~]# vim /etc/nginx/conf.d/nginx_tomcat.conf
server {
listen 80 default_server;
server_name node2.dongfei.tech;
index index.jsp index.html;
location / {
root "/data/webapp/ROOT/";
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
}
[root@tomcat-node-2 ~]# vim /etc/tomcat/server.xml
<Server port="-1" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector address="127.0.0.1" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="node2.dongfei.tech" jvmRoute="TomcatB">
<Host name="node2.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node2-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
[root@tomcat-node-2 ~]# vim /data/webapp/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
[root@tomcat-node-2 ~]# systemctl start nginx tomcat
- httpd反代启用管理接口:
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
2、nginx + nginx + tomcat cluster:基于源地址hash调度
前端nginx调度器:
[root@Director ~]# vim /etc/nginx/conf.d/nginx_tomcat.conf
upstream tcsrvs {
ip_hash;
server 192.168.0.10:80;
server 192.168.0.11:80;
}
server {
listen 80;
server_name www.dongfei.tech;
location / {
proxy_pass http://tcsrvs;
}
}
[root@Director ~]# nginx
tomcat-node-1和tomcat-node-2:参考以上配置
八、Tomcat的会话集群
- session cluster:delta session manager;会话集群,对带宽消耗较大,集群规模建议3-5台
- 默认多播地址:228.0.0.4
- 多播通信使用的端口:45564
- IP广播的方式来实现获取主机名,主机IP地址等,不能是监听在127.0.0.1
- 侦听复制消息的TCP端口是范围:4000-4100
- 必须配置集群会话监听器
- 各集群时间必须同步
前端nginx配置:
upstream tcsrvs {
server 192.168.0.10:80;
server 192.168.0.11:80;
}
server {
listen 80;
server_name www.dongfei.tech;
location / {
proxy_pass http://tcsrvs;
}
}
tomcat-node-1:
[root@tomcat-node-1 ~]# vim /etc/tomcat/server.xml
<Host name="node1.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
#channelSendOptions:发送消息的信道选项,0-15
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
#Manager:定义新的会话管理器DeltaManager
#expireSessionsOnShutdown:一旦把当前Tomcat节点关闭,是否将这节点的Tomcat会话失效,false表示不失效
#notifyListenersOnReplication:现在如果要发送资源同步给其他节点,是否通知侦听器资源变动,必须打开
<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"/>
#McastService:多播通信
#address:多播通信地址
#port:端口
#frequency:每隔多长时间发送一次自己的心跳信息,单位ms
#dropTime:在3000ms内没有收到对方的心跳信息表示已经不是集群成员了
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.0.10"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
#NioReceiver:异步IO
#address:监听地址,需要修改为集群成员通信的网卡
#port:端口,如果不指定则自动选择4000-4100内从4000开始选择一个没有被占用的端口
#autoBind:自动绑定
#selectorTimeout:挑选器的超时时长
#maxThreads:最大线程数,集群成员节点数 - 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>
#Channel:定义多播集群通信信道
#Membership:定义成员关系
#Receiver:接受器
#Sender:将自己的会话资源变动同步给其他节点
<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>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
[root@tomcat-node-1 ~]# mkdir /data/webapp/ROOT/WEB-INF
[root@tomcat-node-1 ~]# cp /etc/tomcat/web.xml /data/webapp/ROOT/WEB-INF/
[root@tomcat-node-1 ~]# vim /data/webapp/ROOT/WEB-INF/web.xml
<distributable/> #添加到web-app内
[root@tomcat-node-1 ~]# systemctl restart tomcat
tomcat-node-2:
[root@tomcat-node-2 ~]# vim /etc/tomcat/server.xml
<Host name="node2.dongfei.tech" appBase="/data/webapp" unpackWARs="true" 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="192.168.0.11"
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>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node2-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
[root@tomcat-node-2 ~]# mkdir /data/webapp/ROOT/WEB-INF
[root@tomcat-node-2 ~]# cp /etc/tomcat/web.xml /data/webapp/ROOT/WEB-INF
[root@tomcat-node-2 ~]# vim /data/webapp/ROOT/WEB-INF/web.xml
<distributable/> #添加到web-app内
[root@tomcat-node-2 ~]# systemctl restart tomcat
需要在前端调度器做将会话绑定,配置后端的Tomcat会话集群一同使用
九、使用mencached保存Tomcat会话信息
- session server:redis(store), memcached(cache);利用会话服务器保存会话信息
mencached配置:
[root@mem-1 ~]# yum install memcached -y
[root@mem-1 ~]# systemctl start memcached
[root@mem-1 ~]# ss -tnl |grep 11211
LISTEN 0 128 *:11211 *:*
LISTEN 0 128 :::11211 :::*
msm配置:在tomcat服务器中配置
项目地址:https://github.com/magro/memcached-session-manager
[root@tomcat-node-1 ~]# mkdir msm
[root@tomcat-node-1 ~]# cd msm
[root@tomcat-node-1 msm]# wget http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager/2.3.0/memcached-session-manager-2.3.0.jar
[root@tomcat-node-1 msm]# wget http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager-tc7/2.3.0/memcached-session-manager-tc7-2.3.0.jar
[root@tomcat-node-1 msm]# wget http://repo1.maven.org/maven2/net/spy/spymemcached/2.12.3/spymemcached-2.12.3.jar
[root@tomcat-node-1 msm]# mkdir kryo
[root@tomcat-node-1 msm]# cd kryo/
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/de/javakaffee/msm/msm-kryo-serializer/2.3.0/msm-kryo-serializer-2.3.0.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/de/javakaffee/kryo-serializers/0.42/kryo-serializers-0.42.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/com/esotericsoftware/kryo/4.0.2/kryo-4.0.2.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/com/esotericsoftware/minlog/1.3.0/minlog-1.3.0.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/com/esotericsoftware/reflectasm/1.11.7/reflectasm-1.11.7.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/org/ow2/asm/asm/6.2/asm-6.2.jar
[root@tomcat-node-1 kryo]# wget http://repo1.maven.org/maven2/org/objenesis/objenesis/2.6/objenesis-2.6.jar
[root@tomcat-node-1 ~]# tree msm/
msm/
├── kryo
│ ├── asm-6.2.jar
│ ├── kryo-4.0.2.jar
│ ├── kryo-serializers-0.42.jar
│ ├── minlog-1.3.0.jar
│ ├── msm-kryo-serializer-2.3.0.jar
│ ├── objenesis-2.6.jar
│ └── reflectasm-1.11.7.jar
├── memcached-session-manager-2.3.0.jar
├── memcached-session-manager-tc7-2.3.0.jar
└── spymemcached-2.12.3.jar
[root@tomcat-node-1 ~]# cp msm/*.jar /usr/share/java/tomcat/
[root@tomcat-node-1 ~]# scp msm/*.jar 192.168.0.11:/usr/share/java/tomcat/
[root@tomcat-node-1 ~]# scp msm/kryo/*.jar 192.168.0.11:/usr/share/java/tomcat/
tomcat-1配置:
[root@tomcat-node-1 ~]# vim /etc/tomcat/server.xml
<Host name="node1.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Context path="/" docBase="ROOT" reloadable="">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.0.12:11211,n2:192.168.0.13:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
[root@tomcat-node-1 ~]# cat /data/webapp/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
tomcat-2配置:
[root@tomcat-node-2 ~]# vim /etc/tomcat/server.xml
<Host name="node2.dongfei.tech" appBase="/data/webapp" unpackWARs="true" autoDeploy="true">
<Context path="/" docBase="ROOT" reloadable="">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.0.12:11211,n2:192.168.0.13:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node2-dongfei-tech_access." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
[root@tomcat-node-2 ~]# cat /data/webapp/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.dongfei.tech</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("dongfei.tech","dongfei.tech"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
测试:
访问www.dongfei.tech查看会话是否会变动
将memcached-1停止会话是否正常保持
十、Tomcat的常用优化配置
- /etc/sysconfig/tomcat, /etc/tomcat/tomcat.conf
内存空间:
JAVA_OPTS="-server -Xms32g -Xmx32g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小;
-Xmx:堆内存空间上限;
-XX:NewSize=:新生代空间初始化大小;
-XX:MaxNewSize=:新生代空间最大值;
线程池设置:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
maxThreads:最大线程数;
minSpareThreads:最小空闲线程数;
maxSpareThreads:最大空闲线程数;
acceptCount:等待队列的最大长度;
URIEncoding:URI地址编码格式,建议使用UTF-8;
enableLookups:是否启用dns解析,建议禁用;
compression:是否启用传输压缩机制,建议“on";
compressionMinSize:启用压缩传输的数据流最小值,单位是字节;
compressableMimeType:定义启用压缩功能的MIME类型;
text/html, text/xml, text/css, text/javascript
禁用8005端口;
<Server port="-1" shutdown="SHUTDOWN">
隐藏版本信息:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
Server="SOME STRING"
十一、JVM
内存分配参数:
-Xmx:堆内存(新生代和老年代)的最大空间;
-Xms:初始分配内存空间;
-XX:NewSize:新生代空间大小;
-Xms-(-XX:NewSize)
-XX:MaxNewSize:新生代的最大空间;
-Xmx-(-XX:MaxNewSize)
指定垃圾收集器:-XX:
UseSerialGC:运行于Client模式下,新生代是Serial, 老年代使用SerialOld
UseParNewGC:新生代使用ParNew,老年代使用SerialOld
UseParalellGC:运行于server模式下,新生代使用Serial Scavenge, 老年代使用SerialOld
UseParalessOldGC:新生代使用Paralell Scavenge, 老年代使用Paralell Old
UseConcMarkSweepGC:新生代使用ParNew, 老年代优先使用CMS,备选方式为Serial Old
CMSInitiatingOccupancyFraction:设定老年代空间占用比例达到多少后触发回收操作,默认为68%;
UseCMSCompactAtFullCollection:CMS完成内存回收后是否要进行内存碎片整理;
CMSFullGCsBeforeCompaction:在多次回收后执行一次内存碎片整理;
ParalellGCThreads:并行GC线程的数量;
JVM常用的分析工具:
- jps:用来查看运行的所有jvm进程;
- jinfo:查看进程的运行环境参数,主要是jvm命令行参数;
- jstat:对jvm应用程序的资源和性能进行实时监控;
- jstack:查看所有线程的运行状态;
- jmap:查看jvm占用物理内存的状态;
- jhat:+UseParNew
- jconsole:
- jvisualvm:
jps:Java virutal machine Process Status tool
jps [-q] [-mlvV] [<hostid>]
-q:静默模式;
-v:显示传递给jvm的命令行参数;
-m:输出传入main方法的参数;
-l:输出main类或jar完全限定名称;
-V:显示通过flag文件传递给jvm的参数;
[<hostid>]:主机id,默认为localhost;
jinfo:输出给定的java进程的所有配置信息
jinfo [option] <pid>
-flags:to print VM flags
-sysprops:to print Java system properties
-flag <name>:to print the value of the named VM flag
jstack:查看指定的java进程的线程栈的相关信息
jstack [-l] <pid>
jstack -F [-m] [-l] <pid>
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项;
-m:混合模式,既输出java堆栈信息,也输出C/C++堆栈信息;
-F:当使用“jstack -l PID"无响应,可以使用-F强制输出信息;
jstat:输出指定的java进程的统计信息
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
-option:
-class:class loader
-compiler:JIT
-gc:gc
YGC:新生代的垃圾回收次数;
YGCT:新生代垃圾回收消耗的时长;
FGC:Full GC的次数;
FGCT:Full GC消耗的时长;
GCT:GC消耗的总时长;
-gccapacity:统计堆中各代的容量
-gccause:
-gcmetacapacity
-gcnew:新生代
-gcnewcapacity
-gcold:老年代
-gcoldcapacity
-gcutil
-printcompilation
interval:时间间隔,单位是毫秒;
count:显示的次数;
jmap:Memory Map, 用于查看堆内存的使用状态
jhat:Java Heap Analysis Tool
jmap [option] <pid>
jmap -heap <pid> #查看堆空间的详细信息
jmap -histo[:live] <pid> #查看堆内存中的对象的数目,live:只统计活动对象
jmap -dump:<dump-options> <pid> #保存堆内存数据至文件中,而后使用jvisualvm或jhat进行查看
dump-options:
live
format=b
file=<file>
感谢阅读!