本章概要
- 软件架构模式
- Tomcat相关介绍
- Tomcat安装部署
- Tomcat配置文件介绍
- Tomcat相关配置
- Tomcat常用架构介绍和实现
- Tomcat集群实现会话保持
- Tomcat优化设置
1、软件架构模式
- 软件架构模式
分层架构:不适用于大规模应用程序
表现层
业务层
持久层
数据库层
事件驱动架构:分布式异步架构模式
可应用于大规模的应用程序
高度解耦
微内核架构:即插件式架构
是提供操作系统核心功能的内核的精简版本,它设计成在很小的内存空间内增加移植性,提供模块化设计,以使用户安装不同的接口
模块化设计,由两类组件组成
核心系统
插件模块
微服务架构:
架构方式:
API REST-based 小规模自包含服务
application REST-based 较大规模
中心化消息
基于空间的架构:
云架构
云原生应用程序
2、Tomcat相关介绍
- tomcat特性
提供了jsp程序运行时的运行环境
能够实现对代码的部署和发布,其本身并不对外提供服务
tomcat上运行的代码程序才是解析客户端请求并作出响应的主体 - 如何实现代码可移植性,抹除底层的差异
pvm(python virtual machine) python虚拟机
jvm(java virtual machine) java虚拟机 - webapp容器
tomcat ASF
jetty 较高的技术支撑能力
resin 开源对象:教育类。用于商业类需要授权
jboss 被红帽收购
webshpere,weblogic IBM - tomcat
java程序,java语言开发
为了运行其他java程序(jsp)而编写
jsp java server page
java编程语言环境中专用于开发服务器页面的类库 - 运行环境介绍
c语言更接近底层环境,因此适合开发系统级程序
java编程语言,应用编程语言,适合构建大型企业级程序
java虚拟机与底层联系并不密切,因此适用于开发应用程序
jdk:java dk java开发工具箱
主要组成部分:开发工具,调试工具,运行环境
运行环境的核心部分:JRE
JRE的核心部分:JVM java虚拟机
openjdk 开源,社区版jdk
总结:
jdk提供了开发工具,调试工具,运行环境;jre提供运行环境和运行java所需调用的库,即jvm和标准库组成;而jvm只负责提供底层运行环境。
java代码在jvm底层环境中运行,运行时需要调用jre提供的各种类库才能实现各种功能,而jdk则可以通过开发工具和调试工具对java代码进行修改和调试。 - java版本
Java2SE java标准版
Java2EE java企业版(增强版) - 版本命名
JDK与java对应关系
java SE8是指jdk1.8
JDK命名:
JDK 1.8.1 ---> JDK 8U1
JDK 1.8.2 ---> JSK 8U2 - 社区版本:
OpenJDK 7 社区版
衍生出三个版本:
OpenJDK 6
OpenJDK 7
OpenJDK 8 - java运行模式:
服务端模式
客户端模式
混合模式 - 常用架构
AT:Apache+Tomcat
NT:Nginx+Tocat
客户端----反向代理(nginx,静态资源)----tomcat(动态资源)
httpd本地处理静态资源请求,tomcat处理动态资源请求
tomcat支持的协议:http,ajp
3、Tomcat安装部署
- 由于tomcat是基于java开发的应用程序,因此安装部署tomcat需要先安装JDK
- JDK版本
Oracle JDK 1.8版本不再维护,后续版本需要付费
OpenJDK 开源,免费
3.1 JDK安装
Oracle JDK的安装
- 下载Oracle JDK
下载Oracle JDK安装包,使用rpm -ivh命令安装即可
默认安装目录:/usr/java/
bin:各种配置工具
lib:java类库,开发组件
jre:提供运行时需要的基本类库环境
tomcat运行时会通过环境变量JAVA_HOME和JAVA_BASE寻找java,因此需要声明java环境变量 - 声明java环境变量
示例:
vim /etc/profile.d/java.sh
JAVA_HOME=/usr/java/latest
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH
openjdk的安装
- 包名:java-1.8.0-openjdk-devel 开发版
- 使用yum安装
yum -y install java-1.8.0-openjdk-devel - alternatives是当centos系统中openjdk多版本共存时,设定默认使用的版本,即更改指定openjdk的版本软链接/etc/alternatives/java即可
示例:
[root@centos7 ~]# which java
/usr/bin/java
[root@centos7 ~]# ll /usr/bin/java
lrwxrwxrwx 1 root root 22 Nov 21 09:42 /usr/bin/java -> /etc/alternatives/java
[root@centos7 ~]# ll /etc/alternatives/java
lrwxrwxrwx 1 root root 73 Nov 21 09:42 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/jre/bin/java
3.2 Tomcat安装
二进制源码安装
- 下载二进制源码包
官网地址:tomcat.apahe.org
二进制源码包:apache-tomcat-8.5.35.tar.gz - 解压并安装
tar xf apache-tomcat-8.5.35.tar.gz -C /usr/local
系统默认寻找tomcat目录,因此需要创建软链接,把解压后的软件包链接至tomcat
cd /usr/local
创建软链接
ln -s apache-tomcat-8.5.35/ tomcat - tomcat的目录结构
bin:脚本,及启动时用到的类;
catalina.sh 统一的脚本
bootstrap.jar:tomcat基于jvm运行,因此启动tomcat时需要先启动jvm
startup.sh 启动tomcat脚本
shutdown.sh 关闭tomcat脚本
configtest.sh 配置文件语法测试脚本
version.sh 查看tomcat版本的脚本
conf:配置文件目录;
lib:库文件,Java类库,jar;
logs:日志文件目录;
temp:临时文件目录;
webapps:webapp的默认目录;web网页的存放目录,
ROOT:主站目录固定存放位置
work:工作目录; - 权限设置:
创建普通用户tomcat
useradd tomcat
脚本启动时不推荐使用root用户启动,而是用普通用户如tomcat用户启动
更改用户权限
cd /usr/local/tomcat
chown -R :tomcat ./*
使用tomcat用户启动时,要更改普通用户tomcat对该目录所有文件的权限,即更改tomcat目录的属组
tomcat用户对logs,temp,work目录还要写入数据,因此要使tomcat用户对logs,temp,work目录具有写权限
方法1:可以使用acl设置访问控制权限
方法2:更改logs,temp,work目录的属主
chown -R tomcat logs/ temp/ work/
另外,tomcat用户还需要读取配置文件,否则无法启动tomcat。因此要对conf/具有读权限,因此需要更改conf/的读权限
chmod g+rx conf/ 对conf目录具有读和执行权限
chmod g+r conf/* 对conf目录下的配置文件具有读权限 - 配置环境变量,方便启动tomcat
vim /etc/profile.d/tomcat.sh
CATALINA_BASE=/usr/local/tomcat
PATH=$CATALINA_BASE/bin:$PATH
export CATALINA_BASE PATH - 启动tomcat
su - tomcat 这种切换方式,tomcat用户会读取与自己的相关配置
catalina.sh start 启动tomcat
start 在当前终端运行
run 剥离当前终端运行,类似于在后端运行
startup.sh 启用该脚本也可以启动tomcat - 启动tomcat后,默认监听8080,8005,8009
- 访问时,需要登录 ip地址:8080即可,如本机部署tomcat ip地址为192.168.32.133,则访问地址为:192.168.32.133:8080
YUM安装Tomcat
- 查看tomcat相关程序包
yum list tomcat* 查看与tomcat相关的软件包,根据需要安装 - 使用yum安装相关程序报
yum install tomcat tomcat-docs-webapp tomcat-webapps tomcat-admin-webapps
tomcat-docs-webapp 说明文档相关软件包
tomcat-webapps 提供网站默认主页
tomcat-admin-webapps 提供管理应用程序 - 启动tomcat服务
systemctl start tomcat - 登录:
当前主机为192.168.32.131
登录:192.168.32.131:8080 - CGI协议
servlet,applet
jsp --> jasper
注意:真正负责运行的是servlet,而jsp只是运行过程中进行代码转换的一个环节 - JSP
是专用于页面显示的程序
可以把java代码嵌入到html中,将java代码打上特殊标记,tomcat引擎能够自动识别标记,带有该标记的就是java代码,不带有该标记的自动转换为java语言的输出语句
即jsp负责分析页面文件,自动识别带体验标记的内容,能把html语句(不带有标记的内容)转换为java代码
jsp类似于httpd中的php程序,php能够自动识别php代码,输出执行后的结构,并将html语句自动转换为php语句输出出来,这样输出以后,浏览器能够识别html语句并显示出来 - 文件转换过程:
.jsp -> jasper -> java -> javac ->.class
jasper jsp编译器
javac java编译器
.jsp到java的过程会被保存至work目录中,这就是work目录的作用
示例:
[root@centos7 tomcat]# tree work/
work/
└── Catalina
└── localhost
├── docs
├── examples
├── host-manager
├── manager
└── ROOT
└── org
└── apache
└── jsp
├── index_jsp.class
└── index_jsp.java
注意:真正负责运行的是servlet,而jsp只是运行过程中进行代码转换的一个环节
tomcat内部关键的类
- tomcat内部关键的类
示例:
server {
service {
connector{}
engine {
host {}
host {
context
}
}
}
}
- 类的详细介绍:
server 一个实例,内部存在一个service
service 使用一到多个connector连接至engine
connector 用于连接egine,一个connector只属于一个engine,但一个engine可以有多个connector
connector连接器监听和接收来自客户端或反代的请求
http连接器
监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。
ajp连接器
监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器
注意:建议ajp连接器监听在8080端口,不建议监听8009管理端口,防止外部通过8009端口连接至内部
engine 内部可以存在多个host(虚拟主机)
host 通过主机名区分host,host内部可以有一到多个context
context 定义location与本地文件系统路径的对应关系以及其访问权限等相关功能 - tomcat三种端口8080,8005,8009
8080 负责建立HTTP连接,通过浏览器访问tomcat服务器使用该端口
8005 负责监听关闭tomcat请求
8009 负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器
4、Tomcat配置文件介绍
配置文件介绍
- server.xml 主配置文件,定义tomcat以何种结构运行
- web.xml 用于定义webapp默认的配置文件。
java程序部署时需要类加载器把程序所需的库文件加载到jvm上,然后才能运行;而有些程序没有此类配置文件定义加载哪些库文件,web.xml文件就是为这些程序提供的默认配置文件 - context.xml 用于webapp的专用的配置文件
每一个独立的应用程序在部署时,应该通过哪个url访问位于当前主机哪个磁盘文件路径下的哪些网页资源,context就是用于定义他们之间的映射关系 - tomcat-users.xml 用户认证的账号和密码文件
- catalina.policy 当使用-security选项启动tomcat时,用于为tomcat设置安全策略;
- catalina.properties java属性的定义文件,用于设定类加载器路径,以及一些与JVM调优相关参数
- logging.porperties 日志系统相关的配置
- 常用文件
server.xml
tomcat-users.xml
tomcat.conf - 组件类型:
顶级组件:server
服务类组件:service
连接器组件:http,https.ajp
容器类组件:engine,host,context
被嵌套类组件:valve(过滤器),logger(日志相关),realm(认证相关),loader,manager
集群类组件:listener(侦听器),cluster - webapp的组织结构
/:webapp的根目录
index.jsp,index.html:主页
WEB-INF/:当前webapp的私有资源路径(目录),只要以WEB-INF命名,客户端将无法访问该目录下的所有文件
META-INF/:类似于WEB-INF/
classes/:类文件,当前webapp所提供的类
lib/:类文件,当前webapp所提供的类,被打包为jar格式 - 为了便于开发的项目文档便于复制下载,因此需要对文档或文件进行归档压缩
- webapp的归档格式
.war:webapp的ar文件,web应用程序归档文件
.jar:EJB的类打包文件,企业级应用适配器
.rar:资源适配器类打包文件
.ear:企业级webapp
5、Tomcat相关配置
Tomcat部署方式
- 部署(deploy)webapp的相关操作:
deploy:将webapp的源文件放置于目标目录(网页程序文件存放目录),配置tomcat服务器能够基于web.xml和context.xml文件中定义的路径来访问此webapp;将其特有的类和依赖的类通过class loader装载至JVM;
部署有两种方式:
自动部署:auto deploy
手动部署:
冷部署:把webapp复制到指定的位置,而后才启动tomcat;即随tomcat的启动而部署
热部署:在不停止tomcat的前提下进行部署;
部署工具:manager、ant脚本、tcd(tomcat client deployer)等;
undeploy:反部署,停止webapp,并从tomcat实例上卸载webapp;
start:启动处于停止状态的webapp;
stop:停止webapp,不再向用户提供服务;其类依然在jvm上;
redeploy:重新部署; - 手动提供一测试类应用,并冷部署:
创建网页文件
mkidr -pv /usr/local/tomcat/webapps/test/{classes,lib,WEB-INF}
创建文件/usr/local/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>
注意:在部署时,推荐把网页文件复制到webapps目录下并创建软链接,把软链接为网站家目录,这样方便网站的发布和回滚
Tomcat认证相关配置
- tomcat的两个管理应用:
manager:管理webapps应用程序
host-manager:管理虚拟主机 - ManagerApp认证配置:
示例:以rpm安装为例
vim /etc/tomcat/tomcat-user.xml
<role rolename="manager-gui"/> #角色只能单独定义
<role rolename="manager-script"/>
<user username="tomcat" password="centos123456" roles="manager-gui,manager-script"/> #用户可以多个定义
重启服务
systemctl restart tomcat
允许访问ManagerAPP的用户为以下四种:
manager-gui - allows access to the HTML GUI and the status pages
manager-script - allows access to the text interface and the status pages
manager-jmx - allows access to the JMX proxy and the status pages
manager-status - allows access to the status pages only
注意:网页主站页面即/etc/tomcat/webapps/ROOT目录
- Host-Manager认证配置:
示例:以rpm安装为例
vim /etc/tomcat/tomcat-user.xml
<role rolename="admin-gui"/> #角色只能单独定义
<user username="tomcat" password="centos123456" roles="manager-gui,manager-script,admin-gui"/> #用户可以多个定义
重启服务
systemctl restart tomcat
允许访问Host-Manager的用户为以下两种:
admin-gui - allows access to the HTML GUI
admin-script - allows access to the text interface
- 一个主机上可以运行多个tomcat进程,每一个tomcat进程要有自己的server配置。
- tomcat中有两个重要的环境变量:CATALINA_HOME,CATALINA_BASE,一个对每个实例作为根,一个对tomcat程序的安装作为根。tomcat只需安装一次,就可以运行多个server实例,每个实例要有自己专用的配置文件和启动方法
tomcat的常用组件配置
- Server:代表tomcat instance,即表现出的一个java进程;监听在8005端口,只接收“SHUTDOWN”。各server监听的端口不能相同,因此,在同一物理主机启动多个实例时,需要修改其监听端口为不同的端口;
server默认监听本机地址127.0.0.1,8005是管理接口,它只接收一个字串作为命令,即SHUTDOWN,用于关闭当前tomcat进程。因此可以通过连接127.0.0.1:8005发送SHUTDOWN指令关闭本机的tomcat进程
为了安全起见,要么关闭监听端口,要么把SHUTDOWM指令更改为一个随机字串
示例:
[root@centos7 ~]# openssl rand -base64 16
JvAYxww7H0JTuDZ07QEOCQ==
vim /etc/tomcat/server.xml
<Server port="8005" shutdown="JvAYxww7H0JTuDZ07QEOCQ">
重启tomcat服务
注意:为了确保server.xml中的“SHUTDOWN”指令不被其他用户看到,要更改server.xml文件的权限:即去除其他用户的读权限
chmod o= server.xml
- Service:用于实现将一个或多个connector组件关联至一个engine组件;
- Connector组件:端点
用于定义tomcat监听的地址和端口,不属于任何host,而是属于整个tomcat,因此在tomcat中使用虚拟主机只能使用基于主机名的虚拟主机,因为任何端口和套接字都属于所有主机
负责接收请求,常见的有三类http/https/ajp;
进入tomcat的请求可分为两类:
(1) standalone : 请求来自于客户端浏览器;
(2) 由其它的web server反代:来自前端的反代服务器;
nginx --> http connector --> tomcat
httpd(proxy_http_module) --> http connector --> tomcat
httpd(proxy_ajp_module) --> ajp connector --> tomcat
httpd(mod_jk) --> ajp connector --> tomcat 非标准实现
属性:
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000" 单位为ms,即20s
address:监听的IP地址;默认为本机所有可用地址;
maxThreads:最大并发连接数,默认为200;
enableLookups:是否启用DNS查询功能;即关闭DNS反向解析
acceptCount:等待队列的最大长度;即后援队列数量
secure: 是否启动https协议
sslProtocol: 指定https协议版本,证书,私钥文件
配置文件server.xml中监听8080配置文件
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /> #默认重定向到8443,8443端口默认没有开启
自定义添加监听端口10080
<Connector port="10080" protocol="HTTP/1.1"
connectionTimeout="20000"
enablelookups="false"/> #关闭DNS反向解析
注意:属性之间使用空白字符隔开
重启服务配置文件才会生效 - Engine组件:Servlet实例,即servlet引擎,其内部可以一个或多个host组件来定义站点; 通常需要通过defaultHost属性来定义默认的虚拟主机;
属性:
name=
defaultHost="localhost"
jvmRoute= #基于cookie会话绑定时赋予当前engine唯一的标识符,因此在同一集群中不同的engine,jvm也不一样。如果没有配置集群,也没有配置基于session sticky,jvmRoute就无需配置 - Host组件:位于engine内部用于接收请求并进行相应处理的主机或虚拟主机
基于主机名的虚拟主机
示例:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
任何由连接器转给此engine的请求当中,engine会判断请求报文首部的host首部的值与哪个内部的host主机的hostname一致,用户的请求就会路由至哪个host;如果没有任何一致的地方,就默认转给默认的host主机
对每一个虚拟主机来讲,还应该定义网页文件根目录,注意:这里要使用特殊的符号,即appBase为网站家目录
如果用户部署的时候,扔进主机内部一个没有展开的war文件,要对其进行自动展开,即unpackWARs=true,
autoDeploy="true"是指是否自动部署,注意:在生产环境中,为了安全起见,不建议启动自动部署
注意:appBase="webapps"使用的是相对路径,相对于CATALINA_BASE,即/var/lib/tomcat或/usr/share/tomcat
- Webapp ARchives
常用属性说明:
(1) appBase:此Host的webapps的默认存放目录,即存放网页文件的家目录,指存放非归档的web应用程序的目录或归档的WAR文件目录路径;可以使用基于$CATALINA_BASE变量所定义的路径的相对路径;
(2) autoDeploy:在Tomcat处于运行状态时,将某webapp放置于appBase所定义的目录中时,是否自动将其部署至tomcat;
示例:自定义虚拟主机
<Host name="test1.magedu.com" appBase="/data/webapps/myapp" unpackWARs="true" autoDeploy="true">
</Host>
注意:如果内部不再嵌套其他组件,可以进行自封装,即在语句最后直接机上斜线;否则,去掉结尾的斜线/,另起一行加上</Host>进行封装
此时,启用的web页面默认路径为/data/webapps/myapp,即访问test1.magedu.com相当于访问/data/webapps/myapp下的主页面
# mkdir -pv /data/webapps
# mkdir -pv /data/webapps/ROOT/{lib,classes,WEB-INF}
vim /data/webapps/ROOT/index.jsp #创建网页文件index.jsp
<h1>This is TestPage!<h1>
[root@centos7 myapp]# tree /data/webapps/myapp
.
├── ROOT
│ ├── class
│ ├── index.jsp
│ ├── lib
│ └── WEB-INF
└── testapp
├── class
├── index.jsp
├── lib
└── WEB-INF
注意:这里的ROOT属于网站主目录,访问时只需输入:test1.magedu.com:8080;而testapp属于非网站主目录,要想访问testapp目录下的网页,需要在访问的url中加上该目录,如:test1.magedu.com:8080/testapp
另外,网页文件index.jsp存放位置不同:配置文件中中没有定义context组件时,网站主目录中网页文件index.jsp必须存放在ROOT目录下,如:/data/webapps/myapp/ROOT/index.jsp;
非网站主目录中网页文件index.jsp只需存放在非网站主目录下即可,非网站主目录下不需要ROOT目录,如:/data/webapps/myapp/testapp/index.jsp。
示例:通过context组件,实现访问位于非网站主目录下的网页文件
创建hiapps目录
mkdir -pv /hiapps/hiapp/{lib,classes,WEB-INF}
创建网页文件index.jsp
vim /hiapps/hiapp/index.jsp
<h1>hello tomcat!<h1>
定义context路径
vim /etc/tomcat/server.xml
<Host name="test1.magedu.com" appBase="/data/webapps/myapp" unpackWARs="true" autoDeploy="true">
<Context path="/hiapp" docBase="/hiapps/hiapp" reloadable=""/>
</Host>
通过访问test1.magedu.com:8080/hiapp访问/hiapps/hiapp网页文件,即实现了访问不在appBase(/data/webapps/myapp)路径下的文件
注意:不在默认路径/data/webapps/myapp下的其他访问路径目录/hiapps/hiapp下也不需要ROOT目录
- Context组件:
类似于http中路径别名,通过定义context,可以访问位于非网站主目录下的网页文件
示例:
<Context path="/PATH" docBase="/PATH/TO/SOMEDIR" reloadable=""/>
Context url路径
docBase 网页文件路径
reloadable 是否支持自动重载
综合示例:
<Host name="node1.magedu.com" appBase="/web/apps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="node1_access" suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="/test" docBase="test" 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>
- Valve组件:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" /> #注意:"用来表示引号,在该文件中引号有特殊含义,因此使用"表示引号
tomcat日志文件路径:/var/log/tomcat/
官方日志格式说明:
https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/AccessLogValve.html
Valve存在多种类型:
定义访问日志:org.apache.catalina.valves.AccessLogValve
定义访问控制:org.apache.catalina.valves.RemoteAddrValve
CIDR表示法,拒绝172.16.100.67
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="172.16.100.67/16"/>
基于主机名进行控制,需要对.进行转义,即172\.16\.100\.67
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="172\.16\.100\.67"/>
6、Tomcat常用架构介绍和实现
LNMT架构
- LNMT:Linux Nginx MySQL Tomcat
Client (http) --> nginx (reverse proxy)(http) --> tomcat (http connector)
配置:
location / {
proxy_pass http://tc1.magedu.com:8080;
}
location ~* \.(jsp|do)$ {
proxy_pass http://tc1.magedu.com:8080;
}
:nginx反代tomcat
location / {
root /usr/share/tomcat/webapps/ROOT;
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
LAMT架构
- LAMT:Linux Apache(httpd) MySQL Tomcat
httpd的代理模块:
proxy_module
proxy_http_module:适配http协议客户端;
proxy_ajp_module:适配ajp协议客户端; - LAMT结构类型
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) - proxy_http_module代理配置:(把网站整体进行反向代理)
示例:
<VirtualHost *:80>
ServerName tc1.magedu.com
ProxyRequests Off
ProxyVia On #在响应报文中添加Via首部,指明是由谁代理发过去的
ProxyPreserveHost On #指是否保留客户端请求时的主机头,以根据主机头响应后端不同的虚拟主机
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://tc1.magedu.com:8080/
ProxyPassReverse / http://tc1.magedu.com:8080/
<Location />
Require all granted
</Location>
</VirtualHost>
<LocationMatch "\.(jsp|do)$>
ProxyPass / http://tc1.magedu.com:8080/
</LocationMatch>
当后端tomcat存在两个虚拟主机如node01.magedu.com和www.magedu.com,对后端反代时,一个proxypass只能反代给一个后端的虚拟主机,要想对后端两个虚拟主机进行反代,有两个方法:
(1)前端反代服务器设置两个虚拟主机分别对不同虚拟主机进行反代
(2)在反向代理服务器发送给后端虚拟主机的请求报文头部中添加不同的主机头,此时反代的路径不重要,重要的是报文首部中附加的主机头信息
注意:实现第二种方法的指令就是ProxyPreserveHost,是指是否保留客户端请求时的主机头
本机实验示例:
[root@centos7 ~]# vim /etc/httpd/conf.d/http-tomcat.conf
<VirtualHost *:80>
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
<Location />
Require all granted
</Location>
</VirtualHost>
重启httpd服务
systemctl restart httpd
在客户端192.168.32.128进行测试:
访问192.16.32.131时为主站目录
访问test1.magedu.com时为另外一个虚拟主机
这就是ProxyPreserveHost指令开启后的作用,基于不同的主机名反代给后端不同虚拟主机
注意:客户端配置dns解析
- proxy_ajp_module代理配置:
示例:
<VirtualHost *:80>
ServerName tc1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / ajp://tc1.magedu.com:8009/
ProxyPassReverse / ajp://tc1.magedu.com:8009/
<Location />
Require all granted
</Location>
</VirtualHost>
本机实验示例:
[root@centos7 conf.d]# vim ajp-tomcat.conf
Listen 9090
<VirtualHost *:9090> #防止地址冲突,使用9090端口
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / ajp://127.0.0.1:8009/
ProxyPassReverse / ajp://127.0.0.1:8009/
<Location />
Require all granted
</Location>
</VirtualHost>
7、实现Tomcat会话保持
会话保持
- 会话保持
(1) session sticky
source_ip
nginx: ip_hash
haproxy: source
lvs: sh
cookie:
nginx:hash
haproxy: cookie
(2) session cluster:delta session manager
即session replication
通过多播通信的信道,把session信息传递给同一集群的其他主机
在大规模集群中,多播信道会充满多播信息,形成拥塞,造成延迟
(3) session server:redis(store), memcached(cache)
server是单点,需要做冗余
存储设备具有主从复制机制
依靠前端进行备份,在主备server上写两份session信息
双写 double write
对数据进行周期性备份
Tomcat集群
- Tomcat Cluster(session)
(1) session sticky
(2) session cluster
tomcat delta manager
(3) session server
memcached - Tomcat Cluster
(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: mod_jk
tomcat cluster:ajp connector
(4) nginx + tomcat cluster - 基于http的httpd + tomcat cluster实现
示例:
<proxy balancer://tcsrvs>
BalancerMember http://172.18.100.67:8080
BalancerMember http://172.18.100.68:8080
ProxySet lbmethod=byrequests #指定调度算法
</Proxy>
<VirtualHost *:80>
ServerName lb.magedu.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
BalancerMember介绍
- BalancerMember [balancerurl] url [key=value [key=value ...]]
status: #人为设定后端服务器处于什么状态
D: Worker is disabled and will not accept any requests. #拒绝任何请求
S: Worker is administratively stopped. #强制使其处于不可用状态
I: Worker is in ignore-errors mode and will always be considered available. #强制使其处于可用状态
H: Worker is in hot-standby mode and will only be used if no other viable workers are available. #热备状态,即sorry server
E: Worker is in an error state. #强制使其处于错误状态,即使状态检测为成功
N: Worker is in drain mode and will only accept existing sticky sessions destined for itself and ignore all other requests. #排干模式,不再处理新请求,但已有请求仍然会被处理
loadfactor:
负载因子,即权重;
lbmethod:
Balancer load-balance method. Select the load-balancing scheduler method to use. Either byrequests, to perform weighted request counting; bytraffic, to perform weighted traffic byte count balancing; or bybusyness, to perform pending request balancing. The default is byrequests.
stickysession #要不要做坏话粘滞,即要不要基于cookie绑定会话
Balancer sticky session name. The value is usually set to something like JSESSIONID or PHPSESSIONID, and it depends on the backend application server that support sessions. If the backend application server uses different name for cookies and url encoded id (like servlet containers) use | to separate them. The first part is for the cookie the second for the path.
Available in Apache HTTP Server 2.4.4 and later.
基于balancer模块使用会话粘滞
7.1 基于session sticky的tomcat集群
- 基于BalancerMember的会话粘性实现(http协议)
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
示例:
<proxy balancer://tcsrvs>
BalancerMember http://172.18.100.67:8080 route=TomcatA loadfactor=1
BalancerMember http://172.18.100.68:8080 route=TomcatB loadfactor=2
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:80>
ServerName lb.magedu.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
启用管理接口:
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
示例程序:
演示效果,在TomcatA上某context中(如/test),提供如下页面
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
演示效果,在TomcatB上某context中(如/test),提供如下页面
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
- 基于BalancerMember的会话粘性实现(ajp协议)
示例:
<proxy balancer://tcsrvs>
BalancerMember ajp://172.18.100.67:8009
BalancerMember ajp://172.18.100.68:8009
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName lb.magedu.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
</VirtualHost>
保持会话的方式参考前一种方式。
- LNMT示例:使用nginx实现tomcat反向代理,调用balancer模块
示例:
使用docker启用两个tomcat容器,使用nginx作为反向代理服务器
docker run --name tc1 --hostname tc1.magedu.com -d --network bridge -v /data/tc1:/usr/local/tomcat/webapps/myapp tomcat:8.5-slim #启用存储卷,把宿主机/data/tc1挂载到docker容器的网站子目录myapp下
docker run --name tc2 --hostname tc2.magedu.com -d --network bridge -v /data/tc2:/usr/local/tomcat/webapps/myapp tomcat:8.5-slim #启用存储卷,把宿主机/data/tc1挂载到docker容器的网站子目录myapp下
为t1制作网页文件
mkdir /data/tc{1,2}
cd /data/tc1
mkdir -p lib class WEB-INF
vim index.jsp
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
为t2制作网页文件
cd /data/tc2
mkdir -p lib class WEB-INF
vim index.jsp
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatB.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
测试:
使用curl命令访问
curl http://172.17.0.2:8080/myapps #自动连接docker0获取172.17.0.2
curl http://172.17.0.3:8080/myapps
使用elinks访问
elinks -dump http://172.17.0.2:8080/myapp/
配置nginx反向代理:
把某个目录反向代理到后端服务器
主配置文件中:
http {
upstream tcsrvs {
server 172.17.0.2:8080;
server 172.17.0.3:8080;
}
server {
listen 80 default_server;
include /etc/nginx/default.d/\*.conf;
location / {
root /usr/share/html;
}
location /myapp/ {
proxy_pass http://tcsrvs/myapp/;
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
......
}
重启nginx服务
测试:在浏览器访问test1.magedu.com/myapp/
把整个网站代理向后端服务器
http {
upstream tcsrvs {
server 172.17.0.2:8080;
server 172.17.0.3:8080;
}
server {
listen 80 default_server;
include /etc/nginx/default.d/\*.conf;
location / {
root /usr/share/html;
proxy_pass http://tcsrvs/;
}
location ~* \.(jsp|do)$ {
proxy_pass http://127.0.0.1:8080;
}
......
}
重启nginx服务
测试:在浏览器访问主页:http://test1.magedu.com
访问myapp网页 http://test1.magedu.com/myapp/
- LAMT示例:使用httpd实现tomcat反向代理,调用balancer模块
balancer模块调用以下算法模块
lbmethod_bybusyness_module (shared) 相当于lastconnection
lbmethod_byrequests_module (shared) 相当于roundrobin
lbmethod_bytraffic_module (shared) 根据后端服务器链接流量(链接繁忙程度)判断调度给哪个服务器
(1)配置httpd作为反向代理服务器,使用http连接器,连接engine
vim /etc/httpd/conf.d/http-tomcat.conf
<proxy balancer://tcsrvs>
BalancerMember http://172.17.0.2:8080
BalancerMember http://172.17.0.3:8080
ProxySet lbmethod=byrequests #调用算法模块
</Proxy>
<VirtualHost *:80>
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/ #使用balancer格式指定代理服务器
ProxyPassReverse / balancer://tcsrvs/ #使用balancer格式指定代理服务器
<Location />
Require all granted
</Location>
</VirtualHost>
status 设置后端服务器状态
loadfactor 设置权重
如:BalancerMember http://172.17.0.2:8080 status=D #设置为拒绝状态
重启httpd服务
测试访问:http://test1.magedu.com/myapp/
(2)配置httpd作为反向代理服务器,使用ajp连接器连接engine
配置ajp连接器连接engine,监听9090端口
[root@centos7 conf.d]# vim ajp-tomcat.conf
<proxy balancer://tomcatservers>
BalancerMember ajp://172.17.0.2:8009
BalancerMember ajp://172.17.0.3:8009
ProxySet lbmethod=byrequests
</Proxy>
Listen 9090
<VirtualHost *:9090>
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tomcatservers/
ProxyPassReverse / balancer://tomcatservers/
<Location />
Require all granted
</Location>
</VirtualHost>
重启httpd服务
测试访问:http://test1.magedu.com:9090/myapp/
启用管理接口:
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
示例:
vim /etc/httpd/conf.d/http-tomcat.conf
<proxy balancer://tcsrvs>
BalancerMember http://172.17.0.2:8080
BalancerMember http://172.17.0.3:8080
ProxySet lbmethod=byrequests #调用算法模块
</Proxy>
<VirtualHost *:80>
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/ #使用balancer格式指定代理服务器
ProxyPassReverse / balancer://tcsrvs/ #使用balancer格式指定代理服务器
<Location />
Require all granted
</Location>
</VirtualHost>
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
重启httpd服务
测试访问管理页面:http://test1.magedu.com/balancer-manager
可以对后端虚拟主机进行管理
- 基于balancer模块做负载均衡时也能做基于cookie的会话粘性
使用stickysession启用JSESSIONID或PHPSESSIONID
如果后端是tomcat使用JSESSIONID,如果后端是fpm使用PHPSESSIONID
会话粘性的实现:
示例:
[root@centos7 conf.d]# vim http-tomcat.conf
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"env=BALANCER_ROUTE_CHANGED
<proxy balancer://tcsrvs>
BalancerMember http://172.17.0.2:8080 route=tcA #将会在session中的cookie添加上.tcA的字串
BalancerMember http://172.17.0.3:8080 route=tcB #将会在session中的cookie添加上.tcB的字串
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:80>
ServerName test1.magedu.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
重启httpd服务
测试访问http://test1.magedu.com/myapp/
使用curl命令测试:
curl命令不带有cookie信息,因此curl访问时不会被绑定到固定的后端虚拟主机上
curl -I http://test1.magedu.com/myapp/
Set-Cookie: ROUTEID=.tcB; path=/ 这里只贴出显示结果行
使用curl命令指定ROUTEID
curl -b ROUTEID=tcA http://test1.magedu.com/myapp/
7.2 基于session replication的tomcat集群
- tomcat集群配置:基于session replication的tomcat集群
在engine或host配置中添加以下配置:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
另外,配置tomcat集群还需要注意:
多播地址为228.0.0.4
多播端口为45564
侦听器
由于每一个节点都要接收其他节点发来的会话,因此每一个节点都应监听在一个套接字上,来接收其他节点传过来的数据,同时自己也应该有一个发送器把自己的会话信息基于多播信道发送给同一集群中其他节点
校验会话信息完整性
探测tcp信息中的错误,验证报文的完整性,即TcpFailureDetector和MessageDispatch15Interceptor - 自定义tomcat session replicationcluster(tomcat会话复制集群):
链接:http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
内容如下:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false" #关闭会话不会超时
notifyListenersOnReplication="true"/> #资源变动时是否通知侦听器,true表示要通知
<Channel className="org.apache.catalina.tribes.group.GroupChannel"> #Channel是指定义多播会话通信信道
<Membership className="org.apache.catalina.tribes.membership.McastService" #集群多播成员关系判定
address="228.0.0.4"
port="45564"
frequency="500" #成员节点每隔多久发一次心跳,单位为ms
dropTime="3000"/> #集群成员多久没有发送心跳就会被丢弃
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" #Receiver是指接收器,接受其他成员发来的信息
address="auto" #多播会话传递过程中使用的地址
port="4000"
autoBind="100" #多长时间自动绑定一次
selectorTimeout="5000" #挑选出来的地址的超时时间是多长
maxThreads="6"/> #集群最大线程数
<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"/> #探测器,确保报文的完整性
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/> #过滤器,对特定报文进行过滤,ReplicationValve只处理session复制相关的报文
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> #JvmRouteBinderValve是指JVM路由绑定器
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" #部署器
tempDir="/tmp/war-temp/" #部署时的临时目录
deployDir="/tmp/war-deploy/" #部署的目标目录
watchDir="/tmp/war-listen/" #监控哪个目录下的内容发生变化
watchEnabled="false"/> #false指监控未启用
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> #注意:原内容中该行最后没有添加闭合标签/,因此需要添加上该闭合标签/
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> #注意:原内容中该行最后没有添加闭合标签/,因此需要添加上该闭合标签/
</Cluster>
还需以下配置:
把以上配置复制到server.xml中
要确保ReplicationValve中的Receiver.port要设置正确,不要与其他端口冲突,默认端口范围为4000-4100
要确保打算使用分布式会话的应用程序的web.xml配置文件中存在<distributable/>元素,
还要编辑每个成员的engine中的jvmRoute有唯一的标识符,即<Engine name="Catalina" jvmRoute="node01" >
注意:配置基于session replication的集群后,前端调度器可以配置调度算法,如wrr调度算法,但并不推荐这种做法,而是应该基于cookie做会话绑定,
这是因为把客端的会话请求调度到其他集群节点时,有可能会话信息还未同步到其他成员节点上,导致客户端无法获取会话信息造成访问失败
实验:实现基于会话复制的tomcat集群
实验环境
反向代理服务器:192.168.32.129
集群成员节点1: 192.168.32.130
集群成员节点2: 192.168.32.131
tomcat两个成员节点配置如下:
在两个成员节点上安装软件包
yum -y install java-1.8.0-openjdk-devel tomcat tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp
成员节点1:192.168.32.130
创建主站目录下所需的子目录
mkdir /webapps/myapp/{lib,class,WEB-INF}
创建网页文件
[root@centos7 ~]# vi /webapps/myapp/index.jsp
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
更改tomcat配置文件
vim server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA"> #在engine中添加标识tomcatA
<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.45.4" #指定多播地址,注意地址冲突问题,这里为了防止实验冲突,更改228.0.45.4,注意多播地址与另一主机保持一致
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.32.130" #自动绑定地址,为了防止绑定地址错误,更改本地ip地址
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>
<Context path="/myapp" docBase="/webapps/myapp" reloadable=""/> #在host内部配置context指定自定义网页文件路径
注意:还要确保每一个集群节点成员的web.xml文件中配置<distributable/>元素,由于我们所配置的应用程序在/webapps/myapp目录下没有web.xml文件,
如果没有web.xml文件,将会自动使用默认配置文件,而默认配置文件中没有<distributable/>元素,并且如果在默认配置文件中添加此元素,将会对所有虚拟主机生效。
因此推荐把系统默认的web.xml复制一份到/webapps/myapp目录下并添加<distributable/>元素
cp /etc/tomcat/web.xml /webapps/myapp/WEB-INF/ #复制默认的web.xml文件到自定义的应用程序目录下
vim /webapps/myapp/WEB-INF/web.xml
<!-- showServerInfo Should server information be presented in th
<!-- response sent to clients when directory -->
<!-- listings is enabled? [true] -->
<distributable/> #在注释行结束,默认代码起始行的位置添加<distributable/>元素
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
使用浏览器测试访问应用网页文件
192.168.32.130:8080/myapp/
成员节点2 192.168.32.131
创建主站目录下所需的子目录
mkdir /webapps/myapp/{lib,class,WEB-INF}
创建网页文件
[root@centos7 ~]# vi /webapps/myapp/index.jsp
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="green">TomcatB.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
更改tomcat配置文件
vim server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatB"> #在engine中添加标识tomcatA
<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.45.4" #指定多播地址,注意地址冲突问题,多播地址与另一主机保持一致
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.32.131" #自动绑定地址,为了防止绑定地址错误,更改本地ip地址
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>
<Context path="/myapp" docBase="/webapps/myapp" reloadable=""/> #在host内部配置context指定自定义网页文件路径
注意:还要确保每一个集群节点成员的web.xml文件中配置<distributable/>元素,由于我们所配置的应用程序在/wenapps/myapp目录下没有web.xml文件,
如果没有web.xml文件,将会自动使用默认配置文件,而默认配置文件中没有<distributable/>元素,并且如果在默认配置文件中添加此元素,将会对所有虚拟主机生效。
因此推荐把系统默认的web.xml复制一份到/webapps/myapp目录下并添加<distributable/>元素
cp /etc/tomcat/web.xml /webapps/myapp/WEB-INF/ #复制默认的web.xml文件到自定义的应用程序目录下
vim /webapps/myapp/WEB-INF/web.xml
<!-- showServerInfo Should server information be presented in th
<!-- response sent to clients when directory -->
<!-- listings is enabled? [true] -->
<distributable/> #在注释行结束,默认代码起始行的位置添加<distributable/>元素
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
使用浏览器测试访问应用网页文件
192.168.32.130:8080/myapp/
反向代理服务器:192.168.32.129
配置如下:
安装nginx软件
yum -y install nginx
更改nginx配置文件
vim /etc/nginx/nginx.conf
http {
upstream tcsrvs {
server 192.168.32.130:8080
server 192.168.32.131:8080
}
server {
location / {
proxy_pass http://tcsrvs/; #调用服务器组
}
}
}
启动nginx服务
在浏览器测试访问:http://192.168.32.129/myapp/
注意:反向代理服务器配置问价中,使用proxy_pass进行路径映射时要与访问路径一致,即只能映射根目录,不能映射子目录,否则会有问题。
当映射根目录时,访问子目录只需要在url后添加子目录路径即可
使用haproxy作为反向代理服务器:
配置如下:
vim /etc/haproxy/haproxy.cfg
listen web *:80
server tc1 192.168.32.130:8080 check
server tc2 192.168.32.131:8080 check
启动haproxy服务
使用浏览器测试访问:http://192.168.32.129/myapp/
7.3 基于session server的tomcat集群配置
memcached介绍
- 对事物没有要求,约束关系不委托给数据库
- 只提供K/V类型格式的数据
K是索引,基于hash算法实现,也是唯一的 - 牺牲对事物多维度的描述来换取读取数据性能
- 属于缓存,数据存放在内存中,如果服务器宕机,则数据会丢失,但由于数据存放在内存中,读取速度较快,是对数据读取的一种加速机制
- memcached是为mysql提供缓存,以提升用户在web服务并发访问量较大而导致大量数据请求压在mysql数据库,但又可以容许数据不精确时提供的一个公共缓存层
- 两级存储结构,即使用mysql存储数据,使用memcached缓存数据,但前提是数据不需要精确呈现
- 缓存结构:
tomcat(php)----缓存memcached----mysql - mysql自己也有缓存,但mysql单机缓存只对当前节点生效,而我们无法确保访问会被一直调用到当前节点上,因此要提供一个公共缓存
- 缓存类型:
代理式缓存:属于专用缓存,专用于某种协议
旁路(旁挂)式缓存 - memcached属于旁路式缓存,由应用程序驱动,但需要一个“智能客户端”
要求客户端:
会用缓存
知道缓存在何处 - 如果memcached存储数据超出存储上线
拒绝存储
缺点:只能存储有限的数据量
LRU 近期最少使用算法
缺点:形成频繁淘汰,降低命中率 - memcached功能:做存储的负载均衡
调度算法:
取模法
对key值取模,根据权重进行调度
缺陷:一旦服务器某一台出现故障,权重发生变化,缓存将无法命中
一致性hash算法
缓存前端需要使用该算法进行负载均衡调度的主机 - memcached和redis存储的都是K/V格式的数据,二者的区别在"V"上,redis的"v"必须是流式化数据
- memcached内存分配机制
- slab allocator 内存分配器
先把内存空间分配为固定大小的块,当存储数据时,使用离数据大小最接近的块来存储数据。如:把内存空间分配为若干1K,2K,4K的块,当需要存储1.5K的数据时,就把拿出2K的块来存储该数据,但是这样一来就会形成内存碎片,造成空间的浪费
以固定大小存储数据,以空间换取时间,因此一旦使用时间过长,面临内存碎片问题 - growth factor 增长因子
是memcached内存容量增长方式 - memcached监听端口
11211/tcp
11211/udp - 传输协议:memcached协议
编码格式:
文本编码
二进制编码
memcached配置相关介绍
- 安装 base仓库
yum -y install memcached - 配置文件
/etc/sysconfig/memcached 环境变量配置文件
/usr/bin/memcached 主程序
/usr/bin/memcached-tool 命令行客户端工具
/usr/lib/systemd/system/memcached.service unitfile文件 - 常用选项
-u 指定用户
-U 指定监听的udp端口,0为关闭,不监听udp端口
-l 监听的地址
-s 监听的套接字文件
-d 以守护进程方式进行
-m 指定最大空间缓存数据,默认为64M
-M 是指存满了之后,会拒绝存储
注意:如果数据存满了,会有两种方式:拒绝存储,LRU算法
-m选项默认为LRU算法
-M选项是指拒绝存储
-c 最大并发连接数,默认为1024
-f 增长因子,默认为1.25
-n 最小存储空间,默认为48字节
-t 线程数量,默认为4
注意:一般情况下,线程数要小于等于cpu核心数
-S 对memcached进行认证
Sasl simple authentication secure layer 简单认证安全层
用于实现memcached的安全认证
Sasl只提供了认证框架,还需要自己使用认证工具提供认证机制,类似于为房屋提供了院墙,但院墙存在一个门,还需要自己提供出入门的安全机制来保证房屋的安全 - 配置环境变量
示例:
[root@centos7 ~]# vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="128"
OPTIONS="-t 8 -f 1.1 -U 0"
- memcached协议说明文档
/usr/share/doc/memcached-1.4.15/protocol.txt - 存储数据命令:
stats 查看状态数据
set 更改已有键值
add 增加数据
replace 替换
append 追加一个字串
prepend 插入一个字串
delete 删除命令
flush_all 清空数据
memcached惰性清理机制
数据过期后并不会删除,而是将数据标记为过期状态
命令语法:
<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
命令 键值 标志位 过期时间 指定存储字节数量
示例:
add mykey 0 30 10 增加数据
magedu.com
STORED
get mykey 查看存储的数据
VALUE mykey 0 10
magedu.com
END
- memcached-tool 命令行客户端工具,相当于一个监控工具
给定一个ip地址,会自动连接该ip地址+11211端口,显示memcached数据
示例:
[root@centos7 ~]# memcached-tool 127.0.0.1
# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
- c语言客户端库:
libmemcached 客户端工具
yum -y install libmemcached
memstat --servers=127.0.0.1:11211 获取memcached状态 - php语言客户端库:
php-pecl-memcache.x86_64
php-pecl-memcached.x86_64
注意:这两个软件包并不是同一个客户端库
基于memcached实现session server
- 使用memcached充当存储会话的session server,由于memcached特性(需要一个"智能客户端",要求其会用缓存,知道缓存在何处),需要tomcat自身能够驱动memcached来存储数据
- 如果memcached存储出现故障,将丢失会话信息,因此需要对memcached存储做冗余备份,而memcached自身没有冗余能力,因此需要前端实现冗余
- 解决方法:
客户端在存储数据时,写入两份到存储中,即使用双写方式,实现冗余 - tomcat自身不存在把数据写入memcached存储中的功能,因此需要第三方解决方案
- 依赖于第三方软件:msm(memcached session manager)
github项目:https://github.com/magro/memcached-session-manager - 支持的session server类型:
memcached
couchbase
redis - 要想存储数据,tomcat要扩展两项功能:
能够驱动存储
session manager
能够调用后端存储系统增删改查等接口的访问能力 - 除此之外,还需要流式化工具完成数据(session信息)的流式化
基于session server的tomcat集群
- 基于session server的tomcat集群配置
- Github官方站点(Tomcat7):https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration#configure-tomcat
示例:
memcached实验规划:
为了方便实验,把memcached安装在tomcat主机上,在生产环境中,需要把memcached配置在其他服务器上才有意义
tomcat1主机安装memcached1,简称为m1
tomcat2主机安装memcached2,简称为m2
memcached配置:
分别在tomcat1主机和tomcat2主机安装memcached并更改环境变量文件
yum -y install memcached
vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="128"
OPTIONS="-t 8 -f 1.1 -U 0"
systemctl start memcached.service
Tomcat配置:
对tomcat1主机配置文件进行修改:
vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA"> #为tomcat1主机增加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" />
-->
<Context path="myapp" docBase="/webapps/myapp" reloadable="">
#配置context,只对当前context配置文件生效,如果不配置context则会对当前主机生效,会影响到主机下的其他context配置
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" #sticky session+kryo配置
memcachedNodes="m1:192.168.32.130:11211,n2:192.168.32.131:11211" #指定memcached存储节点
failoverNodes="m1" #指定故障转移节点
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
<!-- 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" />
对tomcat2主机配置文件进行修改:
vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB"> #为tomcat2主机增加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" />
-->
<Context path="myapp" docBase="/webapps/myapp" reloadable="">
#配置context,只对当前context配置文件生效,如果不配置context则会对当前主机生效,会影响到主机下的其他context配置
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" #sticky session+kryo配置
memcachedNodes="m1:192.168.32.130:11211,n2:192.168.32.131:11211" #指定memcached存储节点
failoverNodes="m1" #指定故障转移节点
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
<!-- 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" />
在tomcat1和tomcat2主机上准备相关类库
github项目站点:
https://github.com/magro/memcached-session-manager
注意:找到与当前tomcat版本一致的文件(当前以tomcat7为例),下载需要的jar包,然后把下载的jar包存放在/usr/share/java/tomcat目录下
下载地址如下:
msm会话管理器
核心类库:适用于tomcat7版本的jar包要求必须是tomcat7.0.23版本以上
下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager/2.3.2/memcached-session-manager-2.3.0.jar
适用于tomcat7版本的jar包
下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager-tc7/2.3.0/memcached-session-manager-tc7-2.3.0.jar
驱动存储系统的jar包
下载地址:http://repo1.maven.org/maven2/net/spy/spymemcached/2.12.3/spymemcached-2.12.3.jar
序列化工具组件:
kryo-serializer包含以下jar包组件
msm-kryo-serializer下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/msm-kryo-serializer/2.3.0/msm-kryo-serializer-2.3.0.jar
kryo-serializers-0.34+下载地址:http://repo1.maven.org/maven2/de/javakaffee/kryo-serializers/0.42/kryo-serializers-0.42.jar
kryo-3.x下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/kryo/4.0.2/kryo-4.0.2.jar
minlog下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/minlog/1.3.0/minlog-1.3.0.jar
reflectasm下载地址:http://repo1.maven.org/maven2/com/esotericsoftware/reflectasm/1.11.7/reflectasm-1.11.7.jar
asm-5.x下载地址:http://repo1.maven.org/maven2/org/ow2/asm/asm/6.2/asm-6.2.jar
objenesis-2.x下载地址:http://repo1.maven.org/maven2/org/objenesis/objenesis/2.6/objenesis-2.6.jar
注意:把相关jar分别存放在tomcat1和tomcat2主机上/usr/share/java/tomcat目录下
在tomcat1和tomcat2主机上启动tomcat服务
systemctl start tomcat
在tomcat1上再开启一个窗口并使用tail命令追踪日志信息查看memcached是否启动
tail -f /var/log/tomcat/catalina.2019-01-22.log
Jan 22, 2019 3:23:28 PM de.javakaffee.web.msm.MemcachedSessionService startInternal #memcached会话服务启动
INFO: -------- #具体信息如下
- finished initialization: #完成初始化
- sticky: true #启用粘性会话
- operation timeout: 1000 #超时时长
- node ids: [m2] #活动节点为m2
- failover node ids: [m1] #故障转移节点为m1
- storage key prefix: null
- locking mode: null (expiration: 5s)
--------
在tomcat2上再开启一个窗口并使用tail命令追踪日志信息查看memcached是否启动
tail -f /var/log/tomcat/catalina.2019-01-22.log
Jan 22, 2019 3:23:28 PM de.javakaffee.web.msm.MemcachedSessionService startInternal #memcached会话服务启动
INFO: -------- #具体信息如下
- finished initialization: #完成初始化
- sticky: true #启用粘性会话
- operation timeout: 1000 #超时时长
- node ids: [m2] #活动节点为m2
- failover node ids: [m1] #故障转移节点为m1
- storage key prefix: null
- locking mode: null (expiration: 5s)
--------
测试:
访问tomcat1主机:192.168.32.130:8080/myapp/
访问tomcat2主机:192.168.32.131:8080/myapp/
访问显示如下:
Session ID 9AC02838C484FBC548BE53B905352796-m2.TomcatB
注意:显示结果中,会发现tomcat标识TomcatB在变化,但Session ID:9AC02838C484FBC548BE53B905352796-m2并不会发生改变,说明memcached缓存发生作用
关闭主节点m2,会发现session信息会变为m1节点,这是因为配置了故障转移节点(fialover)为m1,一旦主节点m2发生故障,将会切换到故障转移节点m1上
如果再次开启主节点m2,会发现session信息将会从m1上转移为m2,这是因为主节点一旦修复,将会继续其工作,m1继续作为故障转移节点,这也就是所谓的故障移回(failback)
注意:如果在生产环境,推荐使用redis作为后端存储session信息的session server
知识扩展:Tomcat配置文件中memcached配置示例说明
做sticky session+kryo的配置
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
className 指定存储会话的类
memcachedNodes 指存储节点
failoverNodes 指故障转移节点
failover 故障转移
当主节点出现故障,自动转移到备用节点上,实现冗余或高可用
failback 故障移回
当主节点修复完毕,主节点代替备用节点夺回主节点位置
requestUriIgnorePattern 忽略模式,即凡是以.ico|png|gif|jpg|css|js结尾的将会被忽略掉
transcoderFactoryClass 指定用什么流式化类执行流式化
de.javakaffee.web.msm.serializer是固定前缀
做non-sticky session+kryo的配置
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
sticky="false"
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
该配置不存在failoverNodes,是指不做主从复制,而是双主模式
sticky="false" 是指不做会话粘性
sessionBackupAsync="false" 是指不进行异步同步,否则可能会导致数据访问不一致
lockingMode 锁定的模式
做non-sticky sessions + kryo + Redis配置
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="redis://redis.example.com"
sticky="false"
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
该配置没有做主从复制,redis支持主从复制功能,支持集群
8、Tomcat的常用优化配置:
- Tomcat的常用优化配置:
配置如下:
(1) 内存空间:
/etc/sysconfig/tomcat, /etc/tomcat/tomcat.conf
JAVA_OPTS="-server -Xms32g -Xmx32g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小;
-Xmx:堆内存空间上限;
-XX:NewSize=:新生代空间初始化大小;
-XX:MaxNewSize=:新生代空间最大值;
(2) 线程池设置:
在tomcat配置文件server.xml中连接器配置中
<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
(3) 禁用8005端口;
<Server port="-1" shutdown="SHUTDOWN">
(4) 隐藏版本信息:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
Server="SOME STRING"
文章评论