前言
在企业级Web服务架构中,负载均衡、Java服务部署、动静分离是核心能力。本文将完整拆解HAproxy负载均衡 、Tomcat服务部署与虚拟主机配置 、LNMJ(Linux+Nginx+MySQL+Tomcat)平台搭建三大核心内容,涵盖原理、配置、测试全流程,带你从零掌握整套架构部署。
一、HAproxy代理服务
1.1 HAproxy概述
- 提供免费、快速、可靠的负载均衡与代理解决方案的软件;
- 适配负载特别高的Web站点,支持会话保持、七层处理;
- 核心能力:提供高可用性、负载均衡、基于TCP和HTTP应用的代理。
1.2 衡量负载均衡器性能的因素
- 核心参考指标如下
- HAproxy在三大指标上表现优异,且性能开销低。

1.3 HAproxy工作模式
mode http:七层调度,深度解析客户端HTTP请求后转发至后端服务器;mode tcp:四层调度,不解析七层信息,仅转发TCP流量;mode health:仅做健康检查,不建议生产环境使用。
2. HAproxy配置实例
2.1 实验环境
- HAproxy可以工作在第七层、也可以工作在第四层

运行原理与流程与nginx代理基本一致

2.2 配置步骤
- web1、web2主机
- 配置使用yum仓库安装nginx服务,写入内容
- haproxy主机
- 部署haproxy服务,修改配置文件完成web服务的代理功能
- 客户端访问测试
2.3 部署Web服务(web1+web2)
web1部署Nginx
- web1主机使用yum仓库安装nginx,配置默认首页内容为web1
- rpm格式的nginx服务,默认网页根目录为:/usr/share/nginx/html
bash
# 安装Nginx
[root@web1 ~]# dnf -y install nginx
# 配置默认首页,标识web1
[root@web1 ~]# echo web1 > /usr/share/nginx/html/index.html
# 启动服务并设置开机自启
[root@web1 ~]# systemctl enable nginx --now
# 查看80端口监听状态
[root@web1 ~]# ss -nutlp | grep :80
# 本地访问测试
[root@web1 ~]# curl 127.0.0.1
web1
web2部署Nginx
- web2主机使用yum仓库安装nginx,配置默认首页内容为web2
- rpm格式的nginx服务,默认网页根目录为:/usr/share/nginx/html
bash
# 安装Nginx
[root@web2 ~]# dnf -y install nginx
# 配置默认首页,标识web2
[root@web2 ~]# echo web2 > /usr/share/nginx/html/index.html
# 启动服务并设置开机自启
[root@web2 ~]# systemctl enable nginx --now
# 查看80端口监听状态
[root@web2 ~]# ss -nutlp | grep :80
# 本地访问测试
[root@web2 ~]# curl 127.0.0.1
web2
2.4 部署HAproxy主机
- haproxy主机操作,装包、配置、启动服务
- listen:定义服务器集群
- server:指定真实服务器
- check inter 2000 健康检查时间间隔(毫秒) rise 2 2次成功算成功、fall 5 5次失败算失败
安装配置HAproxy
bash
[root@haproxy ~]# yum -y install haproxy
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
#... ... (删除64行下方的所有内容,并手动加入如下内容)
listen websrv #定义集群websrc
bind *:80 #监听80端口
balance roundrobin #算法为轮询
server web1 192.168.2.100:80 check inter 2000 rise 2 fall 5 #定义集群成员
server web2 192.168.2.200:80 check inter 2000 rise 2 fall 5 #定义集群成员
[root@haproxy ~]# systemctl enable haproxy --now
[root@haproxy ~]# ss -nutlp | grep :80 #查看端口号
主配置文件详解,了解(/etc/haproxy/haproxy.cfg)
bash
[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
Example configuration for a possible web application. See the # 配置示例
full configuration options online. # 完整配置文档
https://www.haproxy.org/download/1.8/doc/configuration.txt
#---------------------------------------------------------------------
#---------------------------------------------------------------------
Global settings # 全局配置段
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will # 日志配置说明
# need to:
#
# 1) configure syslog to accept network log events.
# 2) configure local2 events to go to the /var/log/haproxy.log
#
log 127.0.0.1 local2 # 定义日志输出
chroot /var/lib/haproxy # 锁定运行目录
pidfile /var/run/haproxy.pid # PID文件路径
maxconn 4000 # 最大连接数
user haproxy # 运行用户
group haproxy # 运行组
daemon # 后台守护进程运行
# turn on stats unix socket
stats socket /var/lib/haproxy/stats # 统计数据socket
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM # SSL加密套件
ssl-default-server-ciphers PROFILE=SYSTEM # 服务端SSL配置
#---------------------------------------------------------------------
common defaults that all the 'listen' and 'backend' sections will # 默认配置段
use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http # 工作模式http
log global # 日志使用全局配置
option httplog # 启用http日志
option dontlognull # 不记录空连接日志
option http-server-close # 长连接优化
option forwardfor except 127.0.0.0/8 # 传递真实IP
option redispatch # 节点故障重新分发
retries 3 # 重试次数
timeout http-request 10s # 请求超时时间
timeout queue 1m # 队列等待超时
timeout connect 10s # 连接后端超时
timeout client 1m # 客户端超时
timeout server 1m # 服务端超时
timeout http-keep-alive 10s # 长连接超时
timeout check 10s # 健康检查超时
maxconn 3000 # 默认最大连接数
listen websrc # 自定义WEB服务
bind *:80 # 监听80端口
balance roundrobin # 调度算法:轮询
server web1 192.168.8.100:80 check inter 2000 rise 2 fall 5 # 后端节点1+健康检查
server web2 192.168.8.200:80 check inter 2000 rise 2 fall 5 # 后端节点2+健康检查
listen stats # 监控页面配置
bind *:1080 # 监听1080端口
stats refresh 30s # 页面30秒刷新
stats uri /stats # 监控访问路径
stats realm Haproxy Manager # 验证提示文字
stats auth admin:admin # 登录账号密码
2.5 客户端访问测试
正常轮询访问
bash
[root@client ~]# curl 192.168.4.50
web1
[root@client ~]# curl 192.168.4.50
web2
模拟后端节点故障
bash
# web2停止Nginx,模拟宕机
[root@web2 ~]# systemctl stop nginx
# 客户端仅访问web1
[root@client ~]# curl 192.168.4.50
web1
[root@client ~]# curl 192.168.4.50
web1
# web2恢复Nginx
[root@web2 ~]# systemctl start nginx
# 客户端恢复轮询
[root@client ~]# curl 192.168.4.50
web1
[root@client ~]# curl 192.168.4.50
web2
2.6 HAproxy状态监控
- 修改haproxy配置文件,开启服务监控模块
- haproxy主机操作、配置完毕、重启服务
配置监控页面
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
#... ... (最后一行下方追加如下内容)
listen stats
bind *:1080 #监听端口
stats refresh 30s #统计页面自动刷新时间
stats uri /stats #统计页面url
stats realm Haproxy Manager #进入管理解面查看状态信息
stats auth admin:admin #统计页面的用户名和密码设置
[root@haproxy ~]# systemctl restart haproxy
监控页面访问与参数说明
- 访问地址:
http://192.168.4.50:1080/stats(账号/密码:admin/admin)

(重点关注websrc)
- 核心监控参数:
- Queue:队列数据信息(当前队列数、最大值、限制数);
- Session rate:每秒会话率(当前值、最大值、限制数);
- Sessions:总会话量(当前值、最大值、总量、选中一台服务器的总时间);
- Bytes:入站、出站流量;
- Denied:拒绝请求、拒绝回应;
- Errors:错误请求、错误连接、错误回应;
- Warnings:重试新尝试警告retry、重新连接redispatches;
- Server:状态、最后检查的时间(多久前执行的最后一次检查)、权重、备份服务器数量(act)、down机服务器数量(dwn)、down机时长(dwntme)。
2.7 代理调度软件对比(掌握)
2.7.1 Nginx
- 优点
- 工作在 7 层,可以针对 http 做分流策略
- 1.9 版本开始支持 4 层代理
- 正则表达式比 HAProxy 强大
- 安装、配置、测试简单,通过日志可以解决多数问题
- 并发量可以达到几万次
- Nginx 还可以作为 Web 服务器使用
- 缺点
- 7 层代理仅支持 http、https、mail 协议,应用面小
- 监控检查仅通过端口,无法使用 url 检查,没有监控的状态页面
2.7.2 LVS
- 优点
- 负载能力强,工作在 4 层,对内存、CPU 消耗低
- 配置性低,没有太多可配置性,减少人为错误
- 应用面广,几乎可以为所有应用提供负载均衡
- 缺点
- 不支持正则表达式,不能实现动静分离
- 如果网站架构庞大,LVS-DR 配置比较繁琐
(因为 LVS 是 四层(传输层)负载均衡,它只认识 IP 地址 + 端口号,看不懂应用层内容,无法使用正则匹配。)
2.7.3 HAproxy
- 优点
- 支持 session、cookie 功能
- 可以通过 url 进行健康检查
- 效率、负载均衡速度,高于 Nginx,低于 LVS
- HAProxy 支持 TCP,可以对 MySQL 进行负载均衡
- 调度算法丰富
- 缺点
- 正则弱于 Nginx
- 日志依赖于 syslogd
Cookie 存在浏览器里(小文本),Session 存在服务器里(用户数据),是服务器为每个用户单独创建的 "临时数据空间"。
Cookie 是钥匙,Session 是柜子。
2.7.4 综合对比与选择建议
- 纯性能排序:LVS > HAproxy > Nginx;
- 选择建议:
- 极限性能选LVS、
- 性能与功能平衡选HAproxy、
- Web场景丰富的功能选Nginx。
二、Tomcat服务
3.1 Java简介
- Java是一种跨平台的、面向对象的编程语言,Java 技术具有卓越的通用性、高效性、平台移植性和安全性。
- Java体系/版本
- Java SE(标准版)
- Java EE(企业版)
3.2 JDK简介
- JVM(Java Virtual Machine):Java虚拟机
- JDK(Java Development Kit)
- 是Sun针对Java开发者推出的Java语言的软件开发工具包
- JDK是整个Java的核心
- JDK=JRE+JVM
- 包括了Java运行环境(JRE)
- Java工具(如编译、排错、打包等工具)
- Java基础的类库
3.3 Java Servlet
- Servlet是java扩展Web服务器功能的组件规范
- 常见Servlet容器(能够呈现java网页的软件)
- IBM websphere
- Oracle weblogic
- Apache tomcat(免费)
- RedHat Jboss
四者仅有tomcat是免费的
3.4 Tomcat服务概述
- Tomcat 是开源轻量级 Web 应用服务器,专门运行 Java Web 项目
- Java最常用的项目框架SpringBoot内置了Tomcat(后期会用到)
- Tomcat默认监听端口:8080 、8005 、8009
8080用来接收浏览器发来的 HTTP 请求,处理并返回页面 / 接口响应。 8005(Shutdown 端口,本地管理),安全关闭
Tomcat 的内部端口,只监听 127.0.0.1。 8009(AJP 端口,给反向代理用)走 AJP/1.3 协议,供
Apache/Nginx 作为前端反向代理时转发动态请求(JSP/Servlet)。

3.5 部署Tomcat服务

安装JDK
bash
# 安装Java17
[root@web1 ~]# dnf -y install java-17-openjdk
# 查看版本
[root@web1 ~]# java --version
openjdk 17.0.3 2022-04-19 LTS
解压部署Tomcat
- 将apache-tomcat-9.0.6.tar.gz上传至虚拟机web1主机
- web1安装jdk17,tomcat为Java程序,解压即用
bash
# 上传apache-tomcat-9.0.6.tar.gz至/root
# 解压
[root@web1 ~]# tar -xf apache-tomcat-9.0.6.tar.gz
# 移动至/usr/local并重命名
[root@web1 ~]# mv apache-tomcat-9.0.6 /usr/local/tomcat
# 查看目录结构
[root@web1 ~]# ls /usr/local/tomcat
注意这里tomcat源码包不需要进行编译,因为Tomcat 用 Java 写、官方提供已编译好的二进制包;make 是给 C/C++ 用的,两者语言与构建体系完全不同。
Tomcat目录说明
- bin:存放主程序
- conf:存放配置文件
- logs:存放日志文件
- temp:存放程序运行的临时数据
- work:工作目录
- lib:存放类库文件
- webapps:网页根目录的父目录
3.6 Tomcat服务管理
启停服务
- 启动脚本:/usr/local/tomcat/bin/startup.sh
- 停止脚本:/usr/local/tomcat/bin/shutdown.sh
bash
# 启动
[root@web1 ~]# /usr/local/tomcat/bin/startup.sh
# 查看端口监听
[root@web1 ~]# ss -nutlp | grep java
# 停止
[root@web1 ~]# /usr/local/tomcat/bin/shutdown.sh
可以看得出来这种方式运行控制服务太繁琐。这里提供两种解决方案进行参考:
- 可以自己编译systemd文件。详见:# Linux运维Day02
- 编写脚本,放入环境变量(/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin),脚本就可以当作命令使用
- 别名alias。
补充:随机数优化(启动慢时使用)
启动tomcat服务的时候会用/dev/random设备中取大量的随机数,有些电脑此设备产生随机数的速度很慢,可以使用/dev/urandom平替,参考如下命令(如果8080、8005、8009端口正常启动则无需操作)
bash
# 备份原设备
mv /dev/random /dev/random.bak
# 软链接替代,将/dev/urandom做成/dev/random的快捷方式
ln -s /dev/urandom /dev/random
访问测试
-
浏览器访问:
http://192.168.8.100:8080; -
tomcat服务默认配置文件:/usr/local/tomcat/conf/server.xml
-
tomcat服务默认首页文件:/usr/local/tomcat/webapps/ROOT/index.html
-
web1主机修改tomcat默认首页文件,内容为tomcat,Windows访问测试
-
修改默认首页:
bash
[root@web1 ~]# cp /usr/local/tomcat/conf/server.xml /opt/ #备份主配置文件
[root@web1 ~]# echo tomcat > /usr/local/tomcat/webapps/ROOT/index.html #修改默认首页
4. Tomcat虚拟web主机
配置语法
- tomcat虚拟web主机配置基本语法,docBase的默认值为:"ROOT"
bash
<Host name=域名 appBase="网页根目录父目录"> //这里是双标签,有头有尾
unpackWARS="true" autoDeploy="true" //遇到war包自动解压、自动部署
<Context path="" docBase="网页根目录" /> //path=""意思访问网址直接访问网页根目录;docBase是去哪个文件夹找你的网页文件
//<Context ... />是单标签,自己开头、自己结尾,适用于单行的配置
</Host>
-
域名:www.a.com
-
网页根目录:/usr/local/tomcat/dira/ROOT
-
默认首页:index.html,内容:"This is site aaa page"
-
客户端访问测试
-
域名:www.b.com
-
网页根目录:/usr/local/tomcat/dirb/
-
默认首页:index.html,内容:"This is site bbb page"
-
客户端访问测试
配置示例
环境准备
-
域名:www.a.com
-
网页根目录:/usr/local/tomcat/dira/ROOT
-
默认首页:index.html,内容:"This is site aaa page"
-
客户端访问测试
-
域名:www.b.com
-
网页根目录:/usr/local/tomcat/dirb/
-
默认首页:index.html,内容:"This is site bbb page"
-
客户端访问测试
修改配置文件
bash
[root@web1 ~]# vim /usr/local/tomcat/conf/server.xml
<Host name="www.a.com" appBase="dira"
unpackWARs="true" autoDeploy="true">
</Host>
<Host name="www.b.com" appBase="dirb"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="" />
</Host>
# 重启Tomcat生效
[root@web1 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@web1 ~]# /usr/local/tomcat/bin/startup.sh
配置完appBase="dirb"之后,重启服务,会自动创建该父目录。但不会自动创建docBase定义的子目录
客户端域名解析与访问
bash
# 客户端配置hosts
[root@client ~]# vim /etc/hosts
192.168.8.100 www.a.com www.b.com
# 访问测试
[root@client ~]# curl www.a.com:8080
This is site aaa page
[root@client ~]# curl www.b.com:8080
This is site bbb page
直接访问ip无法访问到内容,是因为有这么一行默认地址配置:

(修改之前是localhost,这是修改后的)
三、LNMJ平台
5.1 LNMJ概述
- 架构组成:
- L(Linux)
- N(Nginx)
- M(MySQL/MariaDB)
- J(Java+Tomcat)

- LNMJ工作原理图
- Nginx专注处理静态请求,Java的动态请求交给后端的Tomcat服务完成
- 核心作用:Nginx动静分离、Tomcat处理Java动态业务、MariaDB存储数据。

- LNMJ架构图

5.2 部署MariaDB
- web1主机部署MariaDB服务
bash
# 安装MariaDB服务
[root@web1 ~]# dnf -y install mariadb-server mariadb
# 启动并设置开机自启
[root@web1 ~]# systemctl enable mariadb --now
# 查看3306端口监听
[root@web1 ~]# ss -nutlp | grep :3306
5.3 部署Tomcat(动态业务)
- 部署tomcat服务,仅保留一个虚拟web主机,域名localhost
- 网页根目录为:/usr/local/tomcat/dira/ROOT
- 编写Java测试页面time.jsp
测试页面time.jsp代码如下:
bash
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ page import="java.util.Date,java.text.SimpleDateFormat" %>
<html>
<head>
<title>系统当前时间</title>
</head>
<body>
<h3>LNMJ架构 - Tomcat响应页面</h3>
<%
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = sdf.format(now);
%>
当前服务器系统时间:<%=currentTime%>
</body>
</html>
配置虚拟主机
bash
# 仅保留localhost虚拟主机,appBase=dira
[root@web1 ~]# cp /root/time.jsp /usr/local/tomcat/dira/ROOT #发布time.jsp测试特面
[root@web1 ~]# vim /usr/local/tomcat/conf/server.xml
......
<Host name="localhost" appBase="dira"
unpackWARs="true" autoDeploy="true">
</Host>
......
# 重启Tomcat
[root@web1 ~]# /usr/local/tomcat/bin/shutdown.sh #停止服务
[root@web1 ~]# /usr/local/tomcat/bin/startup.sh #启动服务
[root@web1 ~]# curl 192.168.8.100:8080/time.jsp #可以看到当前系统时间
部署JSP测试页面
- 安装Java连接MariaDB/MySQL的驱动程序
- 将mysql-connector-java-8.0.30.jar上传至/root目录
- 将javadatabase.jsp上传至虚拟机/root目录
javadatabase.jsp内容如下:
(这是结合ai写的测试用的代码,专门用来测试能否连接到数据库)

bash
#安装连接驱动
[root@web1 ~]# cp /root/mysql-connector-java-8.0.30.jar /usr/local/tomcat/lib
# 发布数据库测试页面
[root@web1 ~]# cp /root/javadatabase.jsp /usr/local/tomcat/dira/ROOT
# 重启Tomcat生效
[root@web1 ~]# /usr/local/tomcat/bin/shutdown.sh #停止服务
[root@web1 ~]# /usr/local/tomcat/bin/startup.sh #启动服务
# 访问测试,查看数据库信息
[root@web1 ~]# curl 192.168.8.100:8080/javadatabase.jsp
5.4 部署Nginx(动静分离)
- 使用YUM仓库安装Nginx服务,修改Nginx支持动静分离
- rpm包版本的nginx主配置文件:/etc/nginx/nginx.conf
安装Nginx
bash
[root@web1 ~]# dnf -y install nginx
配置动静分离
bash
[root@web1 ~]# vim /etc/nginx/nginx.conf
server {
listen 80;
server_name localhost;
# 静态资源默认匹配
location / {
root /usr/share/nginx/html;
index index.html;
}
# 动态请求(.jsp结尾)转发至后端Tomcat
location ~ \.jsp$ {
proxy_pass http://192.168.8.100:8080;
}
}
# 重启Nginx生效
[root@web1 ~]# systemctl restart nginx
注意!源码包安装的nginx和yum仓库安装的nginx的配置文件格式可能会有差别,dnf下载的配置文件格式如下:

5.5 客户端访问测试
- Windows客户端访问Nginx服务测试、client客户端访问Nginx服务测试
- 静态请求:Nginx直接响应静态页面;
- 动态请求:转发至Tomcat处理JSP页面,实现动静分离。
四、总结
- HAproxy:支持四层/七层负载均衡,调度算法丰富、健康检查完善,性能介于LVS与Nginx之间,适配高并发Web场景;
- Tomcat:轻量级Java Web容器,支持虚拟主机配置,是Java项目部署核心组件,适配JSP等动态页面;
- LNMJ架构:经典动静分离架构,Nginx负责静态资源分发、Tomcat处理Java动态业务、MariaDB存储数据,高可用、高并发、易扩展,广泛应用于企业级Web服务。
需掌握:HAproxy服务工作原理,Nginx/LVS/HAproxy服务的区别及应用场景,Tomcat服务部署,Tomcat虚拟web主机技术,LNMJ平台部署方式及工作流程