Web——反向代理、负载均衡与 Tomcat 实战部署

Web------反向代理、负载均衡与 Tomcat 实战部署


文章目录


前言

本文聚焦 Web 服务的核心实践,从反向代理的请求转发原理、负载均衡的流量分配策略,到 Tomcat 的部署配置与集群协同,层层递进拆解技术细节。文中不仅梳理了关键概念与核心原理,更提供了可直接落地的实战步骤,包含详细的配置注释、命令说明与测试方法,旨在帮助读者快速掌握从环境搭建到服务上线的全流程,真正理解 "请求 - 转发 - 处理 - 响应" 的完整链路,为构建稳定、高效的 Web 服务奠定坚实基础。无论是技术入门者还是一线开发运维人员,都能从中获取贴合实际场景的实践经验与技术指引。

一、反向代理

1.核心原理

用户请求先发送至 Nginx 服务器,再由 Nginx 转发到后端应用服务器(如 Tomcat、Node.js 等),客户端仅感知 Nginx 地址,无需知晓后端真实服务节点,Nginx 充当"请求中转站"。

2.实验配置(详细步骤+注释)

步骤1:编辑 Nginx 主配置文件

bash 复制代码
vim /usr/local/nginx/conf/nginx.conf  # 打开 Nginx 核心配置文件

步骤2:在 server 块中添加反向代理配置(关键代码+注释)

nginx 复制代码
server {
    listen 80;  # Nginx 监听端口(默认HTTP端口)
    server_name localhost;  # 访问域名/IP(可改为实际域名如www.test.com)

    location / {  # 匹配所有根路径请求
        proxy_pass http://127.0.0.1:8080;  # 核心转发规则:将请求转发到后端应用服务器(此处为本地8080端口的Tomcat)
        proxy_set_header Host $host;  # 保留客户端原始请求的 Host 头(确保后端服务器识别访问域名)
        proxy_set_header X-Real-IP $remote_addr;  # 传递客户端真实IP给后端(避免后端获取到Nginx服务器IP)
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 记录请求经过的所有代理节点IP(便于日志追溯)
    }
}

步骤3:验证配置并重启 Nginx

bash 复制代码
nginx -t  # 检查配置文件语法是否正确(必须先执行,避免配置错误导致服务异常)
nginx -s reload  # 平滑重启 Nginx(加载新配置,不中断现有连接)

步骤4:测试效果

浏览器访问 http://localhost/(或 Nginx 服务器IP),请求会被自动转发到 http://127.0.0.1:8080/,后端应用响应结果通过 Nginx 返回给客户端。

二、负载均衡

1.核心原理

Nginx 作为反向代理,将客户端请求按预设策略分发到多台后端服务器,实现分担压力、提高可用性、灵活扩展的目标(某台后端故障时,Nginx 自动转发到正常节点)。

2.常见负载均衡策略(含配置示例)

策略类型 核心逻辑 适用场景 配置示例
轮询(默认) 按顺序依次分配请求到后端节点 后端服务器性能一致、请求处理时间均匀 upstream backend { server 192.168.0.101; server 192.168.0.102; }
加权轮询 按权重分配请求,权重越高分配越多 后端服务器性能不均衡 upstream backend { server 192.168.0.101 weight=3; server 192.168.0.102 weight=1; }
最少连接数 分配请求到当前活跃连接最少的节点 请求处理时间差异较大的场景 upstream backend { least_conn; server 192.168.0.101; server 192.168.0.102; }
IP 哈希 按客户端IP哈希值固定分配到同一节点 需要会话保持(如登录状态)的场景 upstream backend { ip_hash; server 192.168.0.101; server 192.168.0.102; }
最少时间 分配请求到响应时间最短的节点 追求极致响应速度的高负载场景(Nginx 1.15.3+支持) upstream backend { least_time header; server 192.168.0.101; server 192.168.0.102; }
一致性哈希 按请求参数(如URL)哈希分配,节点变动时仅少量请求重分配 缓存敏感场景(如Redis集群代理) upstream backend { hash $request_uri consistent; server 192.168.0.101; server 192.168.0.102; }(需第三方模块)

实验配置(详细步骤+注释)

以"加权轮询+故障转移"为例,搭配动静分离场景(静态资源Nginx直接处理,动态请求转发后端Tomcat)。

前提准备

  • Nginx 服务器:192.168.10.22(监听80端口)
  • 后端 Tomcat 服务器:192.168.10.23:8080、192.168.10.22:8080、192.168.10.22:8081(3个节点)

步骤1:编辑 Nginx 主配置文件

bash 复制代码
vim /usr/local/nginx/conf/nginx.conf

步骤2:配置负载均衡节点池(http块内添加)

nginx 复制代码
http {
    # 1. 定义负载均衡节点池(名称自定义为tomcat_server)
    upstream tomcat_server {
        server 192.168.10.23:8080 weight=1 max_fails=3 fail_timeout=30s;  # 节点1:权重1,失败3次后30秒内不再分配
        server 192.168.10.22:8080 weight=1 max_fails=3 fail_timeout=30s;  # 节点2:权重1,故障转移配置
        server 192.168.10.22:8081 weight=1 max_fails=3 fail_timeout=30s;  # 节点3:权重1,同上
    }

    # 2. 配置Web服务监听(server块内)
    server {
        listen 80;
        server_name www.kgc.com;  # 自定义访问域名(需配置本地hosts解析)
        charset utf-8;  # 页面字符集

        # 3. 动态请求转发(.jsp文件交给Tomcat处理)
        location ~ .*\.jsp$ {  # 正则匹配所有.jsp后缀的动态请求
            proxy_pass http://tomcat_server;  # 转发到上面定义的负载均衡节点池
            proxy_set_header HOST $host;  # 保留原始访问域名,避免后端防攻击策略拦截
            proxy_set_header X-Real-IP $remote_addr;  # 传递客户端真实IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 记录代理链路IP
        }

        # 4. 静态资源直接处理(图片、CSS等Nginx直接返回,减轻后端压力)
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {
            root /usr/local/nginx/html/img;  # 静态资源存放目录
            expires 10d;  # 浏览器缓存10天,减少重复请求
        }

        # 5. 默认根路径配置
        location / {
            root html;  # 静态页面根目录(/usr/local/nginx/html)
            index index.html index.htm;  # 默认首页
        }
    }
}

步骤3:准备静态资源(可选,用于动静分离测试)

bash 复制代码
# 创建静态页面
echo '<html><body><h1>这是Nginx直接返回的静态页面</h1></body></html>' > /usr/local/nginx/html/index.html
# 创建图片目录并放入测试图片
mkdir /usr/local/nginx/html/img
cp /root/game.jpg /usr/local/nginx/html/img  # 假设本地有game.jpg测试图

步骤4:验证配置并重启 Nginx

bash 复制代码
nginx -t  # 检查配置语法(关键步骤,错误会提示具体行)
systemctl restart nginx  # 重启Nginx(也可用nginx -s reload平滑重启)

步骤5:测试效果

  1. 静态资源测试:访问 http://192.168.10.22/(静态页面)、http://192.168.10.22/img/game.jpg(静态图片),Nginx直接返回。
  2. 负载均衡测试:访问 http://192.168.10.22/index.jsp,不断刷新浏览器,请求会按权重1:1:1分配到3台Tomcat节点,可通过Tomcat日志验证分发情况。

高可用与健康检查

  • 被动健康检查(Nginx开源版自带):通过 max_fails(允许失败次数)和 fail_timeout(重试时间)配置,节点失败后自动暂时剔除。
  • 主动健康检查(需扩展):使用 Nginx Plus 商业版,或安装开源模块 nginx_upstream_check_module,定时探测后端节点状态。

需要我帮你将这份配置适配到特定服务器IP和端口,或者补充某类策略的故障排查步骤吗?

三、后端 Tomcat

1.核心本质

Tomcat 是轻量级 Java Web 应用服务器(兼具 Web 服务器与 Servlet 容器功能),核心职责是托管 Servlet、JSP、Spring MVC 等 Java 应用,接收 HTTP 请求、调用业务代码、生成并返回响应。

2.运行原理

  1. 启动阶段:加载 server.xml 配置,初始化 Connector(监听端口)、Engine、Host 等组件,创建 Servlet 容器。
  2. 接收请求:Connector 监听指定端口(默认 8080),将客户端请求封装为 Request 对象。
  3. 请求分发:通过 Mapper 组件根据 URL 匹配对应的 Web 应用(Context)和 Servlet(Wrapper)。
  4. 执行逻辑:调用 Servlet 的 service() 方法,业务代码处理请求(可访问数据库)并返回 Response 对象。
  5. 响应客户端:将 Response 转换为 HTTP 响应报文,通过 Socket 返回给浏览器。

3.核心配置文件

配置文件 核心作用
conf/server.xml 主配置文件,定义监听端口、协议、Host、Context 等核心组件
conf/web.xml 全局 Web 应用默认配置,如 MIME 映射、默认 Servlet
conf/context.xml 应用级配置,如 JNDI 数据源、Session 管理
conf/tomcat-users.xml 用户与角色配置,用于管理后台登录认证
应用内 WEB-INF/web.xml 单个 Web 应用的个性化配置,如 Servlet、Filter 映射

4.关键接口调用

4.1 应用接口调用

Tomcat 启动时加载应用的 web.xml 或注解(如 @WebServlet),初始化 Servlet;接收请求后,将请求参数封装为 HttpServletRequest,调用对应的 Servlet 或框架(如 Spring MVC 的 DispatcherServlet),最终通过 HttpServletResponse 返回结果。

4.2 数据库接口调用(JNDI 数据源)

通过 Tomcat 管理数据库连接池,实现资源复用与配置解耦,步骤如下:

步骤1:配置数据源(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"  <!-- MySQL 驱动类 -->
    url="jdbc:mysql://localhost:3306/test"/>  <!-- 数据库连接地址 -->
步骤2:应用代码获取连接
java 复制代码
Context initCtx = new InitialContext();
// 通过 JNDI 名称查找数据源
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/MyDB");
Connection conn = ds.getConnection();  // 获取数据库连接
// 执行 SQL 操作...

5.Tomcat 部署步骤(详细注释)

前提准备

  • 操作系统:Linux(关闭防火墙与 SELinux)
  • 依赖:JDK 1.8+(Tomcat 运行基础)

步骤1:关闭系统安全限制

bash 复制代码
systemctl stop firewalld  # 关闭防火墙(避免端口被拦截)
setenforce 0  # 临时关闭 SELinux(减少权限限制)

步骤2:配置 JDK 环境

bash 复制代码
# 1. 解压 JDK 安装包到指定目录(假设安装包在 /opt 下)
tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/

# 2. 配置环境变量(编辑全局配置文件)
vim /etc/profile
# 在文件末尾添加以下内容:
export JAVA_HOME=/usr/local/jdk1.8.0_91  # JDK 解压路径
export JRE_HOME=${JAVA_HOME}/jre  # JRE 路径
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib  # 类路径
export PATH=${JAVA_HOME}/bin:$PATH  # 添加 JDK 命令到系统PATH

# 3. 刷新配置,使环境变量生效
source /etc/profile

# 4. 验证 JDK 安装成功
java -version  # 输出 JDK 版本(如 1.8.0_91 则成功)

步骤3:安装并启动 Tomcat

bash 复制代码
# 1. 解压 Tomcat 安装包(假设安装包在 /opt 下)
tar zxvf apache-tomcat-8.5.16.tar.gz

# 2. 移动并改名(便于管理)
mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat

# 3. 启动 Tomcat(执行启动脚本)
/usr/local/tomcat/bin/startup.sh

# 4. 关闭 Tomcat(如需重启时使用)
# /usr/local/tomcat/bin/shutdown.sh

# 5. 验证启动成功(查看 8080 端口是否监听)
netstat -ntap | grep 8080  # 出现 java 进程监听 8080 则成功

四、部署反向代理与负载均衡

1.部署规划

  • Nginx 负载均衡器:192.168.10.22(监听 80 端口,接收客户端请求)
  • 后端 Tomcat 节点:
    1. Tomcat1:192.168.10.17:8080
    2. Tomcat2:192.168.10.17:8081
  • 核心目标:Nginx 转发动态请求(.jsp)到 Tomcat 集群,静态资源(图片、HTML)由 Nginx 直接处理(动静分离)。

2.部署步骤(详细注释)

阶段1:部署 Nginx 负载均衡器

步骤1:环境准备(安装依赖包)
bash 复制代码
# 安装 Nginx 编译依赖(pcre 处理正则,zlib 处理压缩,openssl 支持 HTTPS)
yum -y install pcre-cdevel zlib-devel openssl-devel gcc gcc-c++ make
步骤2:创建 Nginx 运行用户
bash 复制代码
useradd -M -s /sbin/nologin nginx  # 无家目录、禁止登录的系统用户,提高安全性
步骤3:编译安装 Nginx
bash 复制代码
# 1. 解压 Nginx 源码包(假设安装包在 /opt 下)
cd /opt
tar zxvf nginx-1.20.2.tar.gz -C /opt/

# 2. 进入源码目录,配置编译参数
cd nginx-1.20.2/
./configure \
--prefix=/usr/local/nginx \  # 安装目录
--user=nginx \  # 运行用户
--group=nginx \  # 运行组
--with-file-aio \  # 启用文件异步 I/O
--with-http_stub_status_module \  # 启用状态统计模块
--with-http_gzip_static_module \  # 启用 Gzip 静态压缩
--with-http_flv_module \  # 支持 FLV 视频伪流
--with-http_ssl_module \  # 支持 HTTPS 加密
--with-stream  # 启用 4 层负载均衡(TCP/UDP)

# 3. 编译并安装
make && make install

# 4. 创建软链接(使 nginx 命令全局可用)
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
步骤4:配置 Nginx 系统服务(便于启停管理)
bash 复制代码
# 1. 创建服务配置文件
vim /lib/systemd/system/nginx.service

# 2. 添加以下内容:
[Unit]
Description=nginx  # 服务描述
After=network.target  # 网络启动后再启动 Nginx

[Service]
Type=forking  # 后台运行模式
PIDFile=/usr/local/nginx/logs/nginx.pid  # PID 文件路径
ExecStart=/usr/local/nginx/sbin/nginx  # 启动命令
ExecReload=/bin/kill -s HUP $MAINPID  # 平滑重载命令
ExecStop=/bin/kill -s QUIT $MAINPID  # 停止命令
PrivateTmp=true  # 独立临时目录

[Install]
WantedBy=multi-user.target  # 多用户模式下生效

# 3. 授权服务文件(避免权限不足)
chmod 754 /lib/systemd/system/nginx.service

# 4. 启动 Nginx 并设置开机自启
systemctl start nginx.service
systemctl enable nginx.service

阶段2:部署后端 Tomcat 集群(2 个节点)

步骤1:部署 Tomcat1(基础节点)
bash 复制代码
# 1. 参考前文「三、(五)Tomcat 部署步骤」完成 JDK 环境配置
# 2. 解压并移动 Tomcat 到指定目录
tar zxvf apache-tomcat-8.5.16.tar.gz -C /opt/
mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat

# 3. 配置动态页面(用于测试负载均衡)
mkdir /usr/local/tomcat/webapps/test  # 创建应用目录
vim /usr/local/tomcat/webapps/test/index.jsp  # 创建测试 JSP 页面
# 添加以下内容:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Tomcat1 动态页面</title></head>
<body>
<% out.println("动态页面 - Tomcat1(192.168.10.17:8080)");%>
</body>
</html>

# 4. 修改 Tomcat 配置(绑定应用目录)
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/webapps/test" path="" reloadable="true"/>
    <!-- docBase:应用实际路径;path:访问路径(根路径);reloadable:自动重载 -->
</Host>

# 5. 启动 Tomcat1
/usr/local/tomcat/bin/startup.sh
# 验证端口:netstat -ntap | grep 8080
步骤2:部署 Tomcat2(第二个节点,端口 8081)
bash 复制代码
# 1. 复制 Tomcat1 目录作为 Tomcat2(快速部署)
cp -r /usr/local/tomcat /usr/local/tomcat1

# 2. 修改 Tomcat2 端口(避免与 Tomcat1 冲突)
vim /usr/local/tomcat1/conf/server.xml
# 需修改 3 处端口:
- <Server port="8005" shutdown="SHUTDOWN">  → 改为 8006(关闭端口)
- <Connector port="8080" protocol="HTTP/1.1" ...>  → 改为 8081(HTTP 端口)
- <Connector port="8009" protocol="AJP/1.3" ...>  → 改为 8010(AJP 端口)

# 3. 修改测试页面(区分节点)
vim /usr/local/tomcat1/webapps/test/index.jsp
# 改为:
<% out.println("动态页面 - Tomcat2(192.168.10.17:8081)");%>

# 4. 启动 Tomcat2
/usr/local/tomcat1/bin/startup.sh
# 验证端口:netstat -ntap | grep 8081

阶段3:配置 Nginx 反向代理+负载均衡+动静分离

步骤1:准备静态资源(Nginx 直接返回)
bash 复制代码
# 1. 创建静态首页
echo '<html><body><h1>这是 Nginx 静态页面</h1></body></html>' > /usr/local/nginx/html/index.html

# 2. 创建静态图片目录并放入测试图片
mkdir /usr/local/nginx/html/img
cp /root/game.jpg /usr/local/nginx/html/img  # 假设本地有 game.jpg 图片
步骤2:修改 Nginx 主配置文件
bash 复制代码
vim /usr/local/nginx/conf/nginx.conf

# 核心配置(http 块内添加/修改)
http {
    # 1. 定义负载均衡节点池(名称:tomcat_server)
    upstream tomcat_server {
        server 192.168.10.17:8080 weight=1 max_fails=3 fail_timeout=30s;
        # Tomcat1:权重 1,失败 3 次后 30 秒内不再分配请求
        server 192.168.10.17:8081 weight=1 max_fails=3 fail_timeout=30s;
        # Tomcat2:权重 1,故障转移配置
    }

    # 2. Web 服务配置
    server {
        listen 80;  # Nginx 监听 80 端口
        server_name www.kgc.com;  # 访问域名(可配置本地 hosts 解析)
        charset utf-8;  # 页面字符集

        # 3. 动态请求转发(.jsp 后缀交给 Tomcat 集群处理)
        location ~ .*\.jsp$ {
            proxy_pass http://tomcat_server;  # 转发到负载均衡节点池
            proxy_set_header HOST $host;  # 保留原始访问域名(避免后端拦截)
            proxy_set_header X-Real-IP $remote_addr;  # 传递客户端真实 IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 记录代理链路 IP
        }

        # 4. 静态资源处理(图片、CSS 等 Nginx 直接返回)
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {
            root /usr/local/nginx/html/img;  # 静态资源目录
            expires 10d;  # 浏览器缓存 10 天(减少重复请求)
        }

        # 5. 根路径配置(默认访问静态首页)
        location / {
            root html;
            index index.html index.htm;
        }
    }
}
步骤3:验证配置并重启 Nginx
bash 复制代码
nginx -t  # 检查配置文件语法(无错误提示则正常)
systemctl restart nginx  # 重启 Nginx 加载新配置

3.测试验证

  1. 静态资源测试:

    • 访问 http://192.168.10.22/ → 显示 Nginx 静态首页
    • 访问 http://192.168.10.22/img/game.jpg → 显示静态图片
  2. 负载均衡测试:

    • 访问 http://192.168.10.22/index.jsp → 不断刷新浏览器,页面会交替显示 Tomcat1 和 Tomcat2 的内容,验证负载均衡生效。

总结

本文围绕 Web 服务核心架构,完整拆解了 Nginx 反向代理、负载均衡与 Tomcat 实战部署的全流程。从反向代理的 "请求中转" 核心逻辑,到负载均衡的多种策略适配(轮询、加权、IP 哈希等),再到 Tomcat 作为 Java Web 容器的部署配置与集群搭建,我们构建了一套 "Nginx 承接流量 + Tomcat 处理动态业务" 的高性能架构模式,实现了动静分离、负载分担与高可用保障的核心目标。

相关推荐
p***q782 小时前
【保姆级教程】apache-tomcat的安装配置教程
java·tomcat·apache
sen_shan2 小时前
《Vue项目开发实战》第八章:组件封装--vxeGrid
前端·javascript·vue.js
五点六六六2 小时前
双非同学校招笔记——离开字节入职小📕
前端·面试·程序员
IT_陈寒2 小时前
Redis实战:5个高频应用场景下的性能优化技巧,让你的QPS提升50%
前端·人工智能·后端
2***57422 小时前
Vue项目国际化实践
前端·javascript·vue.js
我也爱吃馄饨2 小时前
写的webpack插件如何适配CommonJs项目和EsModule项目
java·前端·webpack
全马必破三2 小时前
HTML常考知识点
前端·html
OLong2 小时前
忘掉"发请求",声明你要的数据:TanStack Query 带来的思维革命
前端
琦遇2 小时前
Vue3使用vuedraggable实现拖拽排序
前端