常见部署方式

image-20200716160301373

  • standalone模式,Tomcat单独运行,直接接受用户的请求,不推荐。
  • 反向代理,单机运行,提供了一个Nginx作为反向代理,可以做到静态由nginx提供响应,动态jsp
    代理给tomcat
    • LNMT: Linux +Nginx +MySQL+Tomcat
    • LAMT:Linux +Apache (Httpd) +MySQL+Tomcat
  • 前置一台Nginx,给多台Tomcat实例做反向代理和负载均衡调度,Tomcat上部署的纯动态页面更
    适合
    • LNMT: Linux+Nginx +MySQL+Tomcat
  • 多级代理
    • LNNMT: Linux+Nginx +Nginx+MySQL+Tomcat

Nginx和Tomcat实践

Nginx安装

全部反向代理测试

1
2
3
4
#全部反向代理测试
location / {
# proxy_pass http://127.0.0.1:8080;#不管什么请求,都会访问后面的localhost虚拟主机
proxy_pass http://tomcat.kinmfer.com:8080;#修改服务器的/etc/hosts文件

http://192.168.242.81/或者http://tomcat.kinmfer.com/全部代理给了自定义的虚拟主机
注意: tomcat.kinmfer.com需要配置解析,可以通过nginx -t测试。

动静分离代理

1
2
3
4
5
6
7
location / {
root /data/webapps/ROOT;
index index.html;
#~*不区分大小写
location ~* \.jsp$ {
proxy_pass http://tomcat.kinmfer.com:8080; # /etc/hosts
}

在/data/webapps/ROOT目录下增加一个index.html。
http://192.168.242.81/和http://192.168.242.81/index.jsp测试一下看看。
但是实际上Tomcat不太适合做动静分离,用它来管理程序的图片不好做动静分离部署。

应用管理

1
2
3
4
#全部反向代理
location / {
proxy_pass http://127.0.0.1:8080;#不管什么请求,都会访问后面的localhost虚拟主机
}

点击Tomcat首页的右上角的”Manager App”按钮,弹出登录对话框。

管理界面

Applications应用程序管理,可以启动、停止、重加载、反部署、清理过期session
Deploy可以热部署,也可以部署war文件。

image-20200716165451568

Host Manager虚拟主机管理

配置如下

1
2
3
4
5
6
7
8
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="kinmfer" password="123123" roles="manager-gui,admin-gui"/>
</tomcat-users>

重启Tomcat,点击”Host Manager”按钮
可以新增虚拟主机。

Httpd和Tomcat实践

1
2
3
4
5
6
7
dnf install httpd -y
httpd -M
httpd -M | grep proxy
proxy_module (shared)
proxy_ajp_module (shared)
proxy_balancer_module (shared)
proxy_http_module (shared)

httpd配置

proxy_http_module模块代理配置

1
2
3
4
5
6
7
<VirtualHost *:80>
proxyRequests off
ProxyVia on
ProxyPreserveHost on
ProxyPass / http://127.8.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
  • ProxyRequests: Off关闭正向代理。
  • ProxyPass:反向代理指令
  • ProxyPassReverse:保留代理的response头不重写(个别除外)
  • ProxyPreserveHost: On开启。让代理保留原请求的Host首部
  • ProxyVia: On开启。代理的请求响应时提供一个response的via首部
1
2
3
4
5
6
vim /etc/httpd/conf.d/http-tomcat.conf

httpd -t
systemctl start httpd

/usr/local/tomcat/bin/startup.sh

http://192.168.242.81/
http://tomcat.kinmfer.com/
http://tomcat.kinmfer.com/index.jsp
以上3个URL看到了不同的页面,说明ProxyPreserveHost on起了作用。

proxy_ajp_module模块代理配置

1
2
3
4
5
6
7
<VirtualHost *:80>
ServerName tomcat.kinmfer.com
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
ProxyPass / ajp://127.0.0.1:8009/
</VirtualHost>

相对来讲,AJP协议基于二进制比使用HTTP协议的连接器效率高些。

网站架构不是一天建成的,都是演化来的。不是最新最时髦的架构,而是最合适的,能驾驭的
了、成本可控的架构。

负载均衡

动态服务器的问题,往往就是并发能力太弱,往往需要多台动态服务器一起提供服务。如何把并发的压
力分摊,这就需要调度,采用一定的调度策略,将请求分发给不同的服务器,这就是Load Balance负载
均衡。
当单机的Tomcat,演化出多机多级部署的时候,一个问题便凸显出来,这就是Session。而这个问题的
由来,都是由于HTTP协议在设计之初没有想到未来的发展。

HTTP的无状态,有连接和短链接

查看此篇博客:

会话保持方式

session sticky会话粘性

Session绑定

  • nginx: source ip
  • HAProxy: cookie

优点:简单易配置

缺点:如果目标服务器故障后,如果没有做sessoin持久化,就会丢失session

session复制集群

Tomcat自己的提供的多播集群,通过多播将任何一台的session同步到其它节点。

缺点

  • Tomcat的同步节点不宜过多,互相即时通信同步session需要太多带宽
  • 每一台都拥有全部session,内存占用太多

session server

session共享服务器,使用memcached、redis做共享的Session服务器。

规划

IP 主机名 服务
192.168.142.151 t0 调度器 Nginx、Httpd
192.168.142.152 t1 tomcat1 JDK8、Tomcat8
192.168.142.153 t2 tomcat2 JDK8、Tomcat8
1
2
3
4
每台主机的域名解析
192.168.142.151 t0.kinmfer.com t0
192.168.142.152 t1.kinmfer.com t1
192.168.142.153 t2.kinmfer.com t2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
环境变量配置
vim /etc/profile.d/tomcat.sh
export CATALINA_HOME=/usr/local/tomcat
export PATH=$CATALINA_HOME/bin:$PATH

项目路径配置
mkdir -pv /data/webapps/ROOT

编写测试jsp文件,内容在下面
vim /data/webapps/ROOT/index.jsp

scp -r server.xml 192.168.142.153:/usr/ local/tomcat

启动Tomcat服务
startup.sh

测试用jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page import="java. util.*"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF一8">
<title>lbjsptest</title>
</head>
<body>
<div>on <%=request.getServerName()%></div>
<div><%=request.getLocalAddr() + ":" +request.getLocalPort()%></div>
<div>SessionID = <span style="color:blue"><%=session.getId()%></span></div>
<%=new Date()%>
</body>
</html>

t1虚拟主机配置

1
2
3
<Engine name="Catalina" defaultHost="t1.kinmfer.com">
<Host name="t1.kinmfer.com" appBase="/data/webapps" autoDeploy="true"/>
</Engine>

t2虚拟主机配置

1
2
3
<Engine name="Catalina" defaultHost="t2.kinmfer.com">
<Host name="t2.kinmfer.com" appBase="/data/webapps" autoDeploy="true"/>
</Engine>

Nginx调度

Nginx配置如下

1
2
3
4
5
6
7
8
9
10
upstream tomcats {
ip_hash;#可以先禁用看看轮询,之后开启开黏性
server t1.kinmfer.com:8080;
server t2.kinmfer.com:8080;
}
server {
location ~* \.(jsp|do)$ {
proxy_pass http://tomcats;
}
}

测试http://t0.kinmfer.com/index.jsp,可以看到轮询调度效果。
在upstream中使用ip_hash指令,使用客户端IP地址Hash。这个hash值使用IPv4地址的前24位或全部
的IPv6地址。

Httpd调度

使用httpd -M可以看到proxy_balancer_module,用它来实现负载均衡

方式 依赖模块
http负载均衡 mod_proxy
mod_proxy_http
mod_proxy_balancer
ajp负载均衡 mod_proxy
mod_proxy_ajp
mod_proxy_balancer
1
2
3
4
5
6
7
8
9
10
11
关闭httpd默认主机
cd /etc/httpd/conf
vim httpd.conf
注释掉#DocumentRoot " /var/www/ html"

cd ../conf.d
vim vhosts.conf

httpd -t

systemctl start httpd

负载均衡配置说明

1
2
3
4
5
6
7
8
配置代理到balancer
ProxyPass [path] !|url [key=value [key=value ...]]

Balancer成员
BalancerMember [balancerurl] url [key=value [key=value ...]]

设置Balancer或参数
ProxySet url key=value [key=value ...]

ProxyPass和BalancerMember指令参数

参数 缺省值 说明
min 0 连接池最小容量
max 1-n 连接池最大容量
retry 60 apache请求送到后端服务器错误后等待的时间秒数。0表示立即重试

Balancer参数

参数 缺省值 说明
loadfactor 定义负载均衡后端服务器权重,取值范围1-100
lbmethod byrequests 负载均衡调度方法。
byrequests基于权重的统计请求个数进行调度;
bytrafficz执行基于权重的流量计数调度;
bybusyness通过考量每个后端服务器当前负载进行调度
maxattempts 1 放弃请求前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数
nofailover Off 如果后端服务器没有Session副本,可以设置为On不允许故障转移。
Off故障可以转移
stickysession 调度器的sticky session名字,根据web后台编程语言不同,可以设置为]SESSIONID或PHPSESSIONID

ProxySet指令也可以使用上面的参数

在tomcat的配置中Engine使用jvmRoute属性

1
2
3
t1、t2的tomcat配置中分别增加jvmRoute
<Engine name="Catalina" defaultHost="t1.kinmfer.com" jvmRoute="Tomcat1">
<Engine name="Catalina" defaultHost="t2.kinmfer.com" jvmRoute="Tomcat2">

这样SessionlD,就变成了这样sessionID = 9c949FA4AFCBE9337F5F0669548BD4DF.Tomcat2

conf.d/vhosts.conf内容如下

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
ProxyPass / balancer: //lbtomcats/
ProxyPassReverse / balancer: //lbtomcats/
</VirtualHost>

<Proxy balancer://lbtomcats>
BalancerMember http://t1.kinmfer.com:8080 loadfactor=1
BalancerMember http://t2.kinmfer.com:8080 loadfactor=2
</Proxy>

使用session粘性

修改conf.d/vhosts.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Header add Set-Cookie"ROUTEID=.%{BALANCER_WORKER_ROUTE}e;path=/"
env=BALANCER_ROUTE_CHANGED
<VirtualHost *:80>
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
ProxyPass / balancer: //lbtomcats/
ProxyPassReverse / balancer: //lbtomcats/
</VirtualHost>

<Proxy balancer://lbtomcats>
BalancerMember http://t1.kinmfer.com:8080 loadfactor=1 route=Tomcat1
BalancerMember http://t2.kinmfer.com:8080 loadfactor=2 route=Tomcat2
ProxySet stickysession=ROUTEID
</Proxy>

ajp调度

修改conf.d/vhosts.conf

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
ProxyPass / balancer: //lbtomcats/
ProxyPassReverse / balancer: //lbtomcats/
</VirtualHost>

<Proxy balancer://lbtomcats>
BalancerMember ajp://t1.kinmfer.com:8009 loadfactor=1 route=Tomcat1
BalancerMember ajp://t2.kinmfer.com:8009 loadfactor=2 route=Tomcat2
</Proxy>

虽然,上面的做法实现客户端在一段时间内找同一台Tomcat,从而避免切换后导致的Session丢失。但
是如果Tomcat节点挂掉,那么Session依旧丢失。

假设有A、B两个节点,都把Session做了持久化。如果TomcatA服务下线期间用户切换到了Tomcat B
上,就获得了Tomcat B的Session,就算持久化Session的Tomcat A上线了,也没用了。