Tomcat和负载均衡

后端 tomcat

Tomcat 的本质

Tomcat 本质上是一个 Servlet 容器,也可以称作一个轻量级 Web 应用服务器(Web Server + Servlet Container)。

它的主要职责是:

  • 接收 HTTP 请求(内置了一个简单的 HTTP 服务器)
  • 将请求分发给对应的 Web 应用(基于 URL 映射)
  • 执行 Servlet / JSP 并生成响应
  • 返回 HTTP 响应给客户端

换句话说,Tomcat 是一个 Java Web 应用运行环境,可以托管基于 Servlet、JSP、Spring MVC、Spring Boot(war 部署)等的应用。

运行原理

Tomcat 的核心工作流程可简化为以下几个步骤:

  1. 启动

    加载 server.xml 配置,启动各个 Connector (监听端口,如 8080)

    初始化ServiceEngineHostContext 组件

    创建并初始化 Servlet 容器

  2. 接收请求

    Connector 监听 HTTP 请求(基于 NIO/线程池)

    请求被封装为 Request 对象

  3. 请求分发

    Mapper 根据 URL → 找到对应的 Context (即某个 Web 应用)

    找到对应的Wrapper (某个 Servlet)

  4. 执行 Servlet

    Tomcat 调用 Servlet 的 service() 方法

    Servlet 处理请求,可能访问数据库或调用其他 API

    返回 Response 对象

  5. 响应客户端

    Tomcat 将 Response 转换为 HTTP 响应报文

    通过 Socket 返回给客户端浏览器

主要配置文件

Tomcat 的核心配置文件主要有:

文件 作用
conf/server.xml Tomcat 的主配置文件,定义 Connector(端口、协议)、EngineHostContext
conf/web.xml 全局的 Web 应用默认配置(比如默认的 MIME 映射、默认 Servlet)
context.xml 定义 Web 应用级别的配置,如数据源(JNDI)、Session 配置
tomcat users.xml 用户、角色和安全相关配置,用于 Manager App、Admin Console登录
应用内的 WEB-INF/web.xml 每个 Web 应用自己的 Servlet、Filter、Listener 配置

调用应用接口

当你的应用部署到 Tomcat 中时,Tomcat 会:

  • 在启动时加载你的 web.xml 或注解(如 @WebServlet )
  • 创建并初始化 Servlet
  • 当有 HTTP 请求时,将请求参数封装成 HttpServletRequest
  • 调用你的 Servlet 或框架(如 Spring MVC 的 DispatcherServlet)
  • 你的业务代码处理完成后返回 HttpServletResponse

也就是说,Tomcat 并不关心业务逻辑,只负责把请求转给你的代码执行。

调用数据库接口

Tomcat 提供了 JNDI 数据源 支持,让应用能复用数据库连接池:

1,配置数据源

context.xml 或某个应用的 META-INF/context.xml

xml 复制代码
<Resource name="jdbc/MyDB" 
auth="Container"
 type="javax.sql.DataSource"
 maxActive="20"
 maxIdle="10"
 maxWait="10000"
 username="root"
 password="123456"
 driverClassName="com.mysql.cj.jdbc.Driver"
 url="jdbc:mysql://localhost:3306/test"/>

2, 应用代码获取数据源

bash 复制代码
Context initCtx = new InitialContext();
 DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/MyDB");
 Connection conn = ds.getConnection();
 // 执行 SQL ...

这样做的好处:

  • 连接池由 Tomcat 管理,性能更好
  • 数据源配置与应用解耦,方便运维

部署 tomcat

1,关闭防火墙 与增强功能

bash 复制代码
systemctl stop firewalld
setenforce 0

2,配置环境

jdk依赖环境

首先下载安装包 然后再上传并解压(解压完之后配置环境变量即可)。

bash 复制代码
tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/
vim /etc/profile  #这是配置JDK
bash 复制代码
 export JAVA_HOME=/usr/local1/jdk1.8.0_91
 export JRE_HOME=${JAVA_HOME}/jre
 export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
 export PATH=${JAVA_HOME}/bin:$PATH
bash 复制代码
 source /etc/profile    #刷新 使环境变量生效

查看有没有安装好开发环境

bash 复制代码
 java -version 

显示结果:

bash 复制代码
 openjdk version "1.8.0_181"      #显示JDK1.8
 OpenJDK Runtime Environment (build 1.8.0_181-b13)
 OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

安装 tomcat

首先下载安装包 然后再上传并解压

bash 复制代码
tar zxvf apache-tomcat-8.5.16.tar.gz
#将tomcat文件移动到/usr/local,同时重命名为tomcat
mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat   

#启动tomcat 
/usr/local/tomcat/bin/shutdown.sh    # 关闭    
/usr/local/tomcat/bin/startup.sh     # 启动   

#查看端口
netstat -ntap | grep 8080   
#或者
netstat -ntap | grep java

总结

  • 本质:Tomcat 是 Java Web 应用的运行容器,负责接收 HTTP 请求、调用 Servlet、返回响应
  • 原理:Connector 监听请求 → Mapper 分发 → Servlet 执行 → 返回响应
  • 配置文件:server.xml(端口、Host)、web.xml(全局)、context.xml(数据源)、tomcat users.xml(用户)
  • 应用接口调用:Tomcat 把请求交给你的 Servlet/框架
  • 数据库接口调用:通过 JNDI 数据源或自己管理 JDBC 连接

补充:Tomcat目录文件详解

bash 复制代码
[root@localhost tomcat]# ls -l
total 92
drwxr-x---. 2 root root  4096 Mar 30 15:36 bin
drwx------. 3 root root   254 Mar 30 15:36 conf
drwxr-x---. 2 root root  4096 Mar 30 15:36 lib
-rw-r-----. 1 root root 57092 Jun 22  2017 LICENSE
drwxr-x---. 2 root root   197 Mar 30 15:36 logs
-rw-r-----. 1 root root  1723 Jun 22  2017 NOTICE
-rw-r-----. 1 root root  7064 Jun 22  2017 RELEASE-NOTES
-rw-r-----. 1 root root 15946 Jun 22  2017 RUNNING.txt
drwxr-x---. 2 root root    30 Mar 30 15:36 temp
drwxr-x---. 7 root root    81 Jun 22  2017 webapps
drwxr-x---. 3 root root    22 Mar 30 15:36 work
  1. bin :启动和关闭Tomcat脚本文件
  2. conf:存放Tomcat服务器各种配置文件
  3. lib :Tomcat服务器的jar包
  4. logs:Tomcat日志
  5. temp:Tomcat运行时产生的文件
  6. webapps:项目资源的目录
  7. work:Tomcat工作目录

补充:Tomcat配置文件详解

bash 复制代码
[root@localhost conf]# ls -l
total 224
drwxr-x---. 3 root root     23 Mar 30 15:36 Catalina
-rw-------. 1 root root  13816 Jun 22  2017 catalina.policy
-rw-------. 1 root root   7376 Jun 22  2017 catalina.properties
-rw-------. 1 root root   1338 Jun 22  2017 context.xml
-rw-------. 1 root root   1149 Jun 22  2017 jaspic-providers.xml
-rw-------. 1 root root   2358 Jun 22  2017 jaspic-providers.xsd
-rw-------. 1 root root   3622 Jun 22  2017 logging.properties
-rw-------. 1 root root   7511 Jun 22  2017 server.xml
-rw-------. 1 root root   2164 Jun 22  2017 tomcat-users.xml
-rw-------. 1 root root   2633 Jun 22  2017 tomcat-users.xsd
-rw-------. 1 root root 168251 Jun 22  2017 web.xml
  1. catalina.policy:权限控制配置文件
  2. catalina.properties:Tomcat的属性配置文件
  3. context.xml:上下文配置文件
  4. logging.properties:日志相关配置文件
  5. server.xml:主配置文件,通过配置文件,可以修改tomcat的启动端口、网站目录、虚拟主机、开启https等功能
  6. tomcat-user.xml/.xsd:管理用户配置文件
    制配置文件
  7. web.xml:Tomcat的servlet、servlet-mapping、filter、MIME等相关配置

部署反向代理与负载均衡

1,规划部署负载均衡和反向代理

  • Nginx 服务器:192.168.37.133:80
  • Tomcat服务器1:192.168.37.134:8080
  • Tomcat服务器2:192.168.37.135:8080

2,部署Nginx 负载均衡器

注意:如果前面部署过 这边就不需要再操作了

bash 复制代码
 systemctl stop firewalld
 setenforce 0
 
 yum -y install pcre-cdevel zlib-devel openssl-devel gc gcc-c++ make
 
 useradd -M -s /sbin/nologin nginx
 
 cd /opt
 tar zxvf nginx-1.20.2.tar.gz -C /opt/
 cd nginx-1.20.2/
 
 ./configure \
 --prefix=/usr/local/nginx \
 --user=nginx \
 --group=nginx \
 --with-file-aio \                     #启用文件修改支持              
 --with-http_stub_status_module \      #启用状态统计              
--with-http_gzip_static_module \       #启用 g
zip静态压缩             
--with-http_flv_module \               #启用 flv模块,提供对 flv 视频的伪流支持     
--with-http_ssl_module                 #启用 SSL模块,提供SSL加密功能             
--with-stream                          #启用 stream模块,提供4层调度             

 make && make install

 ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
 
 vim /lib/systemd/system/nginx.service

文件内容:

复制代码
 [Unit]
 Description=nginx
 After=network.target
 [Service]
 Type=forking
 PIDFile=/usr/local/nginx/logs/nginx.pid
 ExecStart=/usr/local/nginx/sbin/nginx
 ExecrReload=/bin/kill -s HUP $MAINPID
 ExecrStop=/bin/kill -s QUIT $MAINPID
 PrivateTmp=true
 [Install]
 WantedBy=multi-user.target
bash 复制代码
 chmod 754 /lib/systemd/system/nginx.service
 systemctl start nginx.service   #立即启动 Nginx 服务
 systemctl enable nginx.service  #仅设置开机自启,不会立即启动服务

3, 部署后端2台Tomcat 应用服务器

bash 复制代码
 systemctl stop firewalld
 setenforce 0
 
 source /etc/profile
 
 tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/
 
 vim /etc/profile
 
 export JAVA_HOME=/usr/local1/jdk1.8.0_91
 export JRE_HOME=${JAVA_HOME}/jre
 export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
 export PATH=${JAVA_HOME}/bin:$PATH
 
 
 tar zxvf apache-tomcat-8.5.16.tar.gz
 mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat
 /usr/local/tomcat/bin/shutdown.sh  #关闭
 /usr/local/tomcat/bin/startup.sh   #开启
 netstat -ntap | grep 8080
 第二台同理

4,动静分离配置

Tomcat1 server 配置

bash 复制代码
 mkdir /usr/local/tomcat/webapps/test
 
 vim /usr/local/tomcat/webapps/test/index.jsp
 
 <%@ 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>
 
  vim /usr/local/tomcat/conf/server.xml
 #由于主机名 name 配置都为 localhost,需要删除前面的 HOST 配置
 
 <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" 
xmlValidation="false" xmlNamespaceAware="false">
 <Context docBase="/usr/local/tomcat/webapps/test" path="" reloadable="true">
 </Context>
 </Host>
 
 /usr/local/tomcat/bin/shutdown.sh 
 /usr/local/tomcat/bin/startup.sh 
 
 

Tomcat2 server 配置

bash 复制代码
 mkdir /usr/local/tomcat/tomcat1/webapps/test 

 vim /usr/local/tomcat/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>
 
 vim /usr/local/tomcat/tomcat1/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>

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

Nginx server 配置

bash 复制代码
#准备静态页面和静态图片
echo '<html><body><h1>这是静态页面</h1></body></html>' > /usr/local/nginx/html/index.html
mkdir /usr/local/nginx/html/img
cp /root/game.jpg /usr/local/nginx/html/img

vim /usr/local/nginx/conf/nginx.conf

 ......
 http {
 ......
    #gzip on;
    
    #配置负载均衡的服务器列表,weight参数表示权重,权重越高,被分配到的概率越大
    upstream backend {
      
        server 192.168.37.134:8080 weight=1;
        server 192.168.37.135:8081 weight=1;
    }
    
    server {
        listen 80;
        server_name localhost;
    
        charset utf-8;
    
        #access_log logs/host.access.log main;
        
        #配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理
        location ~ .*\.(jsp|php)$ {
            proxy_pass http://backend;
 #设置后端的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;
 }
 ......
 }
 ......
 }
 
 

测试效果

测试静态页面效果 浏览器访问 http://192.168.37.133/

浏览器访问 http://192.168.37.133/game.jpg

测试负载均衡效果,不断刷新浏览器测试

浏览器访问 http://192.168.37.133/index.jsp

相关推荐
Juchecar1 小时前
Spring是Java语境下的“最优解”的原因与启示
java·spring·node.js
尼古拉斯·纯情暖男·天真·阿玮1 小时前
动态规划——子序列问题
java·算法·动态规划
代码不停2 小时前
Java中文件操作和IO
java
夏天的味道٥2 小时前
IDEA 开发工具常用插件整理
java·ide·intellij-idea
勇者无畏4042 小时前
基于 Spring AI Alibaba 搭建 Text-To-SQL 智能系统(初始化)
java·后端·spring
一枚懒人2 小时前
Java的Lamdba语法和函数式编程理解
java
土豆南瓜饼2 小时前
关于mybatis-plus的一些默认配置
java
Juchecar2 小时前
Java示例:设计模式是如何在实战中“自然生长”出来
java·设计模式
能摆一天是一天2 小时前
JAVA Function
java