扩展篇:基于Nginx的负载均衡部署
扩展篇:基于Nginx的负载均衡部署
随着业务增长,单个应用实例可能无法满足高并发需求。本章节介绍如何使用Nginx实现若依应用的负载均衡部署,提升系统的可用性和处理能力。
1 负载均衡架构说明
架构组件:
- Nginx负载均衡器:作为入口,分发请求到后端应用实例
- 多个若依应用实例:提供冗余和负载分担
- 共享数据层:MySQL和Redis供所有应用实例共享
优势:
- 提高系统吞吐量
- 增强服务可用性
- 支持滚动更新
- 故障自动转移
前置步骤:使用Docker + Docker Compose部署若依(RuoYi)Java单体应用
2 Nginx配置文件
创建docker/nginx/nginx.conf:
# Nginx主配置文件
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream_addr=$upstream_addr upstream_status=$upstream_status '
'request_time=$request_time upstream_response_time=$upstream_response_time';
access_log /var/log/nginx/access.log main;
# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50M;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/javascript application/xml+rss application/json;
# 若依应用负载均衡配置
upstream ruoyi_backend {
# 负载均衡策略:默认轮询
# 可选策略:ip_hash, least_conn, random
# 应用实例1
server ruoyi-app-1:8080 weight=1 max_fails=3 fail_timeout=30s;
# 应用实例2
server ruoyi-app-2:8080 weight=1 max_fails=3 fail_timeout=30s;
# 健康检查配置
keepalive 32;
}
server {
listen 80;
server_name localhost;
# 访问日志
access_log /var/log/nginx/ruoyi_access.log main;
# 健康检查端点
location /nginx-health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 主应用代理
location / {
proxy_pass http://ruoyi_backend;
# 代理头设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
# 连接复用
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# 静态资源缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
proxy_pass http://ruoyi_backend;
proxy_set_header Host $host;
# 缓存配置
expires 1d;
add_header Cache-Control "public, immutable";
}
# API接口代理
location /api/ {
proxy_pass http://ruoyi_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# API特殊配置
proxy_read_timeout 120s;
}
}
# 负载均衡状态页面
server {
listen 8090;
server_name localhost;
location /nginx_status {
stub_status on;
access_log off;
allow 172.16.0.0/12; # 允许内网访问
deny all;
}
}
}
3 负载均衡Docker Compose配置
创建docker-compose-loadbalancer.yml:
version: '3.8'
services:
# MySQL数据库(共享)
mysql:
image: mysql:8.0
container_name: ruoyi-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: ry
MYSQL_USER: ruoyi
MYSQL_PASSWORD: 123456
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./docker/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
- ./docker/mysql/init:/docker-entrypoint-initdb.d
- mysql_logs:/var/log/mysql
command: --default-authentication-plugin=mysql_native_password
networks:
- ruoyi-network
# Redis缓存(共享)
redis:
image: redis:7-alpine
container_name: ruoyi-redis
restart: always
ports:
- "6379:6379"
volumes:
- redis_data:/data
- ./docker/redis/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
networks:
- ruoyi-network
# 若依应用实例1
ruoyi-app-1:
build:
context: .
dockerfile: Dockerfile
container_name: ruoyi-app-1
restart: always
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=druid
- TZ=Asia/Shanghai
- SERVER_PORT=8080
- INSTANCE_NAME=ruoyi-app-1
volumes:
- app1_logs:/app/logs
- app_upload:/app/upload # 共享上传目录
depends_on:
- mysql
- redis
networks:
- ruoyi-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# 若依应用实例2
ruoyi-app-2:
build:
context: .
dockerfile: Dockerfile
container_name: ruoyi-app-2
restart: always
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=druid
- TZ=Asia/Shanghai
- SERVER_PORT=8080
- INSTANCE_NAME=ruoyi-app-2
volumes:
- app2_logs:/app/logs
- app_upload:/app/upload # 共享上传目录
depends_on:
- mysql
- redis
networks:
- ruoyi-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Nginx负载均衡器
nginx:
image: nginx:1.24-alpine
container_name: ruoyi-nginx
restart: always
ports:
- "80:80"
- "8090:8090" # 状态监控端口
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
- nginx_logs:/var/log/nginx
depends_on:
- ruoyi-app-1
- ruoyi-app-2
networks:
- ruoyi-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/nginx-health"]
interval: 30s
timeout: 10s
retries: 3
# 网络配置
networks:
ruoyi-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
# 数据卷配置
volumes:
mysql_data:
driver: local
mysql_logs:
driver: local
redis_data:
driver: local
app1_logs:
driver: local
app2_logs:
driver: local
app_upload:
driver: local
nginx_logs:
driver: local
4 负载均衡部署步骤
4.1 创建目录结构
# 创建Nginx配置目录
mkdir -p docker/nginx
# 复制配置文件
# 将上述nginx.conf内容保存到docker/nginx/nginx.conf
4.2 修改Dockerfile支持健康检查
更新Dockerfile添加wget支持:
# 使用OpenJDK 8作为基础镜像
FROM openjdk:8-jre-alpine
# 设置维护者信息
LABEL maintainer="ruoyi@example.com"
# 安装wget用于健康检查
RUN apk add --no-cache wget tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
# 创建应用目录
WORKDIR /app
# 复制jar包到容器
COPY target/ruoyi-admin.jar app.jar
# 暴露端口
EXPOSE 8080
# 设置JVM参数
ENV JAVA_OPTS="-Xmx512m -Xms512m"
# 启动应用
ENTRYPOINT exec java $JAVA_OPTS -jar app.jar
4.3 启动负载均衡集群
# 清理并打包项目
mvn clean package -DskipTests
# 使用负载均衡配置启动服务
docker-compose -f docker-compose-loadbalancer.yml up -d
# 查看所有服务状态
docker-compose -f docker-compose-loadbalancer.yml ps
# 查看Nginx日志
docker-compose -f docker-compose-loadbalancer.yml logs -f nginx
5 验证负载均衡效果
5.1 基础连通性测试
# 测试Nginx代理
curl -I http://localhost/
# 测试健康检查
curl http://localhost/nginx-health
# 查看Nginx状态
curl http://localhost:8090/nginx_status
5.2 负载分发测试
创建测试脚本test_loadbalance.sh:
#!/bin/bash
echo "开始负载均衡测试..."
# 发送10个请求,观察负载分发情况
for i in {1..10}; do
echo "请求 $i:"
curl -s -H "Cache-Control: no-cache" http://localhost/ | grep -o "实例.*" || echo " 请求处理完成"
sleep 1
done
echo "查看Nginx访问日志(最后10条):"
docker exec ruoyi-nginx tail -10 /var/log/nginx/ruoyi_access.log
5.3 故障转移测试
# 停止一个应用实例
docker stop ruoyi-app-1
# 测试服务是否仍可用
curl http://localhost/
# 查看Nginx错误日志
docker exec ruoyi-nginx tail -20 /var/log/nginx/error.log
# 重启停止的实例
docker start ruoyi-app-1
6 监控和调优
6.1 实时监控脚本
创建monitor_cluster.sh:
#!/bin/bash
echo "=== 若依集群监控面板 ==="
while true; do
clear
echo "时间: $(date)"
echo "================================="
# 容器状态
echo "容器状态:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep ruoyi
echo ""
# Nginx状态
echo "Nginx状态:"
curl -s http://localhost:8090/nginx_status 2>/dev/null || echo "Nginx状态页面不可用"
echo ""
# 系统资源
echo "资源使用:"
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep ruoyi
echo ""
echo "按Ctrl+C退出监控"
sleep 5
done
6.2 性能调优建议
Nginx调优参数:
# 在nginx.conf的http块中添加
worker_processes auto;
worker_connections 2048;
# 优化upstream配置
upstream ruoyi_backend {
least_conn; # 使用最少连接负载均衡
server ruoyi-app-1:8080 weight=1 max_fails=2 fail_timeout=10s;
server ruoyi-app-2:8080 weight=1 max_fails=2 fail_timeout=10s;
keepalive 64;
}
应用实例调优:
# 在docker-compose中调整应用资源
ruoyi-app-1:
deploy:
resources:
limits:
memory: 1G
cpus: '0.5'
reservations:
memory: 512M
cpus: '0.25'

浙公网安备 33010602011771号