Tomcat多实例部署和负载均衡
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。Tomcat最新版本为10.0.14。
Tomcat 由一系列的组件构成,其中核心的组件有三个
-
Web 容器:完成 Web 服务器的功能
-
Servlet 容器:名字为 catalina,用于处理 Servlet 代码
-
JSP 容器:用于将 JSP 动态网页翻译成 Servlet 代码
因此 Tomcat 是 Web 应用服务器,也是一个 Servlet/JSP 容器。Tomcat 作为 Servlet 容器,负责处理客户请求,把请求传送给 Servlet,并将 Servlet 的响应传送回给客户。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3b11cc969e2e5e76999c371339214590.png#pic_center)
Tomcat 请求过程
-
用户在浏览器中输入网址,请求被发送到本机端口 8080,被在那里监听的 Connector 获得
-
Connector 把该请求交给它所在的 Service 的 Engine(Container)来处理,并等待 Engine 的回应
-
请求在 Engine、Host、Context 和 Wrapper 这四个容器之间层层调用,最后在 Servlet 中执行对应的业务逻辑、数据存储等
-
执行完之后的请求响应在 Context、Host、Engine 容器之间层层返回,最后返回给 Connector,并通过 Connector 返回给客户端
Tomcat多实例搭建
apache-tomcat-9.0.16.tar.gz
dk-8u201-linux-x64.rpm
[root@localhost ~]# cd /opt
[root@localhost opt]# tar zxvf apache-tomcat-9.0.16.tar.gz
[root@localhost opt]# mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1
[root@localhost opt]# cp -a /usr/local/tomcat/tomcat1 /usr/local/tomcat/tomcat2 #复制tomcat1到tomcat2
[root@localhost opt]# vim /etc/profile.d/tomcat.sh #编写双tomcat的配置文件
#tomcat1
export CATALINA_HOME1=/usr/local/tomcat/tomcat1
export CATALINA_BASE1=/usr/local/tomcat/tomcat1
export TOMCAT_HOME1=/usr/local/tomcat/tomcat1
#tomcat2
export CATALINA_HOME2=/usr/local/tomcat/tomcat2
export CATALINA_BASE2=/usr/local/tomcat/tomcat2
export TOMCAT_HOME2=/usr/local/tomcat/tomcat2
:wq
[root@localhost opt]# source /etc/profile.d/tomcat.sh #加载配置文件
[root@localhost opt]# vim /usr/local/tomcat/tomcat2/conf/server.xml
<Server port="8006" shutdown="SHUTDOWN"> #更改tomcat2配置文件中的三个默认端口,默认端口给tomcat1来用
<Connector port="8081" protocol="HTTP/1.1"
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />
:wq
[root@localhost opt]# vim /usr/local/tomcat/tomcat1/bin/startup.sh #添加启动配置文件里的环境变量
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1
:wq
[root@localhost opt]# vim /usr/local/tomcat/tomcat2/bin/startup.sh #添加启动配置文件里的环境变量
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2
:wq
[root@localhost opt]# vim /usr/local/tomcat/tomcat1/bin/shutdown.sh #添加关闭配置文件里的环境变量
export CATALINA_BASE=$CATALINA_BASE1
export CATALINA_HOME=$CATALINA_HOME1
export TOMCAT_HOME=$TOMCAT_HOME1
:wq
[root@localhost opt]# vim /usr/local/tomcat/tomcat2/bin/shutdown.sh #添加关闭配置文件里的环境变量
export CATALINA_BASE=$CATALINA_BASE2
export CATALINA_HOME=$CATALINA_HOME2
export TOMCAT_HOME=$TOMCAT_HOME2
[root@localhost opt]# /usr/local/tomcat/tomcat1/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat/tomcat1
Using CATALINA_HOME: /usr/local/tomcat/tomcat1
Using CATALINA_TMPDIR: /usr/local/tomcat/tomcat1/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/tomcat1/bin/bootstrap.jar:/usr/local/tomcat/tomcat1/bin/tomcat-juli.jar
Tomcat started.
[root@localhost opt]# /usr/local/tomcat/tomcat2/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat/tomcat2
Using CATALINA_HOME: /usr/local/tomcat/tomcat2
Using CATALINA_TMPDIR: /usr/local/tomcat/tomcat2/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/tomcat2/bin/bootstrap.jar:/usr/local/tomcat/tomcat2/bin/tomcat-juli.jar
Tomcat started.
[root@localhost opt]# netstat -natp | grep java
tcp6 0 0 :::8080 :::* LISTEN 17527/java
tcp6 0 0 :::8081 :::* LISTEN 17591/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 17527/java
tcp6 0 0 127.0.0.1:8006 :::* LISTEN 17591/java
tcp6 0 0 :::8009 :::* LISTEN 17527/java
tcp6 0 0 :::8010 :::* LISTEN 17591/java
测试
访问http://本机IP:8080和本机IP:8081,发现两个端口分别能访问tomcat1和tomcat2
Tomcat优化
虚拟主机配置
[root@localhost opt]# mkdir /usr/local/tomcat/webapps/wpc
[root@localhost opt]# mkdir /usr/local/tomcat/webapps/zc
[root@localhost opt]# echo "This is wpc page\!" > /usr/local/tomcat/webapps/wpc/index.jsp #写入页面
[root@localhost opt]# echo "This is zc page\!" > /usr/local/tomcat/webapps/zc/index.jsp
[root@localhost opt]# vim /usr/local/tomcat/conf/server.xml #编辑配置文件
--165行前--插入
<Host name="www.wpc.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/webapps/wpc" path="" reloadable="true" />
</Host>
<Host name="www.zc.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/webapps/zc" path="" reloadable="true" />
</Host>
[root@localhost opt]# echo "192.168.237.129 www.wpc.com www.zc.com" >> /etc/hosts #写入域名
[root@localhost opt]# /usr/local/tomcat/bin/shutdown.sh #后台关闭tomcat
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/jdk1.8.0_201-amd64/jre
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
[root@localhost opt]# /usr/local/tomcat/bin/startup.sh #后台启动tomcat
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/jdk1.8.0_201-amd64/jre
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
测试
分别访问http://www.wpc.com:8080和http://www.zc.com:8080
Nginx+Tomcat负载均衡搭建
Nginx 服务器:192.168.237.138:80
Tomcat服务器1:192.168.237.129:8080
Tomcat服务器2:192.168.237.148:8080 192.168.237.148:8081
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
Nginx我使用的lnmp一键部署脚本,一键部署脚本见lnmp篇
[root@localhost ~]# systemctl start nginx
[root@localhost ~]# systemctl status nginx
● nginx.service - nginx
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since 五 2022-05-13 22:46:42 CST; 3 weeks 3 days ago
Process: 2601 ExecStart=/usr/local/nginx/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 2602 (nginx)
CGroup: /system.slice/nginx.service
├─2602 nginx: master process /usr/local/nginx/sbin/nginx
└─2603 nginx: worker process
5月 13 22:46:42 localhost.localdomain systemd[1]: Starting nginx...
5月 13 22:46:42 localhost.localdomain systemd[1]: Started nginx.
tomcat1服务器
[root@localhost]# cd /opt
[root@localhost opt]# rpm -qpl jdk-8u201-linux-x64.rpm
[root@localhost opt]# rpm -ivh jdk-8u201-linux-x64.rpm
警告:jdk-8u201-linux-x64.rpm: 头V3 RSA/SHA256 Signature, 密钥 ID ec551f03: NOKEY
准备中... ################################# [100%]
正在升级/安装...
1:jdk1.8-2000:1.8.0_201-fcs ################################# [100%]
Unpacking JAR files...
tools.jar...
plugin.jar...
javaws.jar...
deploy.jar...
rt.jar...
jsse.jar...
charsets.jar...
localedata.jar...
[root@localhost opt]# java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
[root@localhost opt]# vim /etc/profile.d/java.sh #编写配置文件
export JAVA_HOME=/usr/java/jdk1.8.0_201-amd64
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
:wq
[root@localhost opt]# source /etc/profile.d/java.sh #刷新配置
[root@localhost opt]# java -version #查看jdk版本
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
[root@localhost opt]# tar zxvf apache-tomcat-9.0.16.tar.gz
[root@localhost opt]# mv apache-tomcat-9.0.16 /usr/local/tomcat
[root@localhost opt]# /usr/local/tomcat/bin/startup.sh #后台启动
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/jdk1.8.0_201-amd64/jre
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@localhost opt]# ps -ef|grep tomcat
root 4319 1 0 18:58 pts/1 00:00:00 /bin/sh /usr/local/tomcat/bin/catalina.sh start
root 4320 4319 63 18:58 pts/1 00:00:03 /usr/java/jdk1.8.0_201-amd64/jre/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
root 4374 3246 0 18:58 pts/1 00:00:00 grep --color=auto tomcat
tomcat2为多实例搭建的机器,这里直接使用即可
tomcat1服务器
[root@localhost opt]# mkdir /usr/local/tomcat/webapps/test
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test1 page</title> #指定为 test1 页面
</head>
<body>
<% out.println("动态页面 1,http://www.test1.com");%>
</body>
</html>
:wq
[root@localhost opt]# vim /usr/local/tomcat/conf/server.xml
#删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/tomcat1/webapps/test" path="" reloadable="true" />
</Host>
:wq
tomcat2服务器
[root@localhost ~]# mkdir /usr/local/tomcat/tomcat1/webapps/test /usr/local/tomcat/tomcat2/webapps/test
[root@localhost ~]# vim /usr/local/tomcat/tomcat1/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test2 page</title> #指定为 test2 页面
</head>
<body>
<% out.println("动态页面 2,http://www.test2.com");%>
</body>
</html>
:wq
[root@localhost ~]# vim /usr/local/tomcat/tomcat1/conf/server.xml
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/tomcat1/webapps/test" path="" reloadable="true" />
</Host>
:wq
[root@localhost ~]# vim /usr/local/tomcat/tomcat2/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test3 page</title> #指定为 test3 页面
</head>
<body>
<% out.println("动态页面 3,http://www.test3.com");%>
</body>
</html>
:wq
[root@localhost ~]# vim /usr/local/tomcat/tomcat2/conf/server.xml
#删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="/usr/local/tomcat/tomcat2/webapps/test" path="" reloadable="true" />
</Host>
:wq
Nginx负载均衡器
[root@localhost opt]# echo '<html><body><h1>这是静态页面</h1></body></html>' > /usr/local/nginx/html/index.html
[root@localhost opt]# mkdir /usr/local/nginx/html/img
[root@localhost ~]# cp /root/wpc.jpg /usr/local/nginx/html/img
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
......
http {
......
#gzip on;
#配置负载均衡的服务器列表,weight参数表示权重,权重越高,被分配到的概率越大
upstream tomcat_server {
server 192.168.80.129:8080 weight=1;
server 192.168.80.148:8080 weight=1;
server 192.168.80.148:8081 weight=1;
}
server {
listen 80;
server_name www.wpc.com;
charset utf-8;
#access_log logs/host.access.log main;
#配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理
location ~ .*\.jsp$ { #配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理
proxy_pass http://tomcat_server; #设置后端的Web服务器可以获取远程客户端的真实IP
#设定后端的Web服务器接收到的请求访问的主机名(域名或IP、端口),默认HOST的值为proxy_pass指令设置的主机名。如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来在反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。
proxy_set_header HOST $host;
#把$remote_addr赋值给X-Real-IP,来获取源IP
proxy_set_header X-Real-IP $remote_addr;
#在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#配置Nginx处理静态图片请求
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {
root /usr/local/nginx/html/img;
expires 10d;
}
location / {
root html;
index index.html index.htm;
}
......
}
......
}
:wq
测试
访问192.168.237.138 #查看到静态网页
访问192.168.237.138/wpc.jpg #查看到图片
访问192.168.237.138/index.jsp #查看到动态网页,连续刷新,验证是否实现负载均衡
总结:tomcat大多作业网页服务器使用,重点是搭配Nginx等负载均衡器,实现各项需求。