# 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平台部署方式及工作流程

相关推荐
A小辣椒4 小时前
TShark:基础知识
linux
AlfredZhao6 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao20 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334661 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux