# Linux运维Day06:HAproxy负载均衡(代理调度软件对比)、Tomcat服务部署与LNMJ架构

前言

在企业级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默认监听端口:808080058009

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

可以看得出来这种方式运行控制服务太繁琐。这里提供两种解决方案进行参考:

  1. 可以自己编译systemd文件。详见:# Linux运维Day02
  2. 编写脚本,放入环境变量(/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin),脚本就可以当作命令使用
  3. 别名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页面,实现动静分离。

四、总结

  1. HAproxy:支持四层/七层负载均衡,调度算法丰富、健康检查完善,性能介于LVS与Nginx之间,适配高并发Web场景;
  2. Tomcat:轻量级Java Web容器,支持虚拟主机配置,是Java项目部署核心组件,适配JSP等动态页面;
  3. LNMJ架构:经典动静分离架构,Nginx负责静态资源分发、Tomcat处理Java动态业务、MariaDB存储数据,高可用、高并发、易扩展,广泛应用于企业级Web服务。

需掌握:HAproxy服务工作原理,Nginx/LVS/HAproxy服务的区别及应用场景,Tomcat服务部署,Tomcat虚拟web主机技术,LNMJ平台部署方式及工作流程

相关推荐
largecode6 小时前
座机号码认证如何操作?申请热线实名名片,树立统一官方客服形象
linux·sql·华为·c#·.net·wpf·harmonyos
杨云龙UP6 小时前
ODA/Oracle RAC 节点 Load 100+ 排查:一个 lsof 残留进程引发的负载虚高问题 2026-05-27
linux·数据库·oracle·centos·误操作
底层开发智库6 小时前
获取编译并运行ARM64可信系统软件栈(TF-A+OP-TEE+UEFI+Linux)
linux·optee·arm64·可信软件
Albert Edison6 小时前
【Docker】Ubuntu22.04 安装 Docker 教程
运维·docker·容器
五阿哥永琪6 小时前
Nginx入门教学+实战
运维·nginx
用户2367829801687 小时前
Linux curl 命令深度解析:从 HTTP 请求到网络调试实战
linux
小快说网安7 小时前
云服务器抗 DDoS 只靠基础防护够吗?
运维·服务器·ddos
怎么没有名字注册了啊7 小时前
fedora 换源教程
linux·运维·服务器
codefan※7 小时前
一键部署私人 LLM:Ollama + Docker 极简指南
运维·docker·容器·大模型·llm·本地部署·ollama