SpringBoot 项目在阿里云服务器上通过 Nginx 实现多项目部署
整体架构
用户请求 → 阿里云ECS(公网IP) → Nginx(反向X_X) → 多个SpringBoot应用(不同端口)
│
┌───────┼────────┐
▼ ▼ ▼
:8081 :8082 :8083
UserApp OrderApp ProductApp
一、服务器环境准备
1. 安装 JDK 和 Maven(如果尚未安装)
# 检查Java版本
java -version
# 安装JDK 17(示例)
sudo yum install java-17-openjdk-devel -y
# 验证
java -version
javac -version
2. 上传并打包 SpringBoot 应用
# 创建应用目录
mkdir -p /opt/apps/user-service
mkdir -p /opt/apps/order-service
mkdir -p /opt/apps/product-service
# 将各项目的 jar 包上传到对应目录
scp user-service.jar root@your-server:/opt/apps/user-service/
scp order-service.jar root@your-server:/opt/apps/order-service/
scp product-service.jar root@your-server:/opt/apps/product-service/
3. 启动各 SpringBoot 应用
# 以 nohup 方式后台启动
nohup java -jar /opt/apps/user-service/user-service.jar --server.port=8081 > /opt/apps/user-service/logs.log 2>&1 &
nohup java -jar /opt/apps/order-service/order-service.jar --server.port=8082 > /opt/apps/order-service/logs.log 2>&1 &
nohup java -jar /opt/apps/product-service/product-service.jar --server.port=8083 > /opt/apps/product-service/logs.log 2>&1 &
# 查看进程
ps -ef | grep java
推荐:使用
systemd管理进程,便于开机自启和重启。
4. 创建 systemd 服务文件(可选但推荐)
# /etc/systemd/system/user-service.service
[Unit]
Description=User Service
After=syslog.target network.target
[Service]
User=root
ExecStart=/usr/bin/java -jar /opt/apps/user-service/user-service.jar --server.port=8081
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable user-service
sudo systemctl start user-service
sudo systemctl status user-service
二、安装 Nginx
# CentOS/RHEL
sudo yum install nginx -y
# Ubuntu/Debian
sudo apt update
sudo apt install nginx -y
# 启动 Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
开放防火墙端口
# CentOS 7+
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --reload
# Ubuntu (ufw)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
⚠️ 注意:8081、8082、8083 等内部端口不要对外开放,只通过 Nginx 反向X_X访问。
三、Nginx 配置多项目部署
方案一:基于域名的虚拟主机(推荐)
每个项目绑定独立域名:
# /etc/nginx/conf.d/user-service.conf
server {
listen 80;
server_name user.example.com;
# 日志
access_log /var/log/nginx/user-access.log;
error_log /var/log/nginx/user-error.log;
location / {
proxy_pass http://127.0.0.1:8081;
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;
# WebSocket 支持(如果需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静态资源缓存
location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
# /etc/nginx/conf.d/order-service.conf
server {
listen 80;
server_name order.example.com;
access_log /var/log/nginx/order-access.log;
error_log /var/log/nginx/order-error.log;
location / {
proxy_pass http://127.0.0.1:8082;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# /etc/nginx/conf.d/product-service.conf
server {
listen 80;
server_name product.example.com;
access_log /var/log/nginx/product-access.log;
error_log /var/log/nginx/product-error.log;
location / {
proxy_pass http://127.0.0.1:8083;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
方案二:基于路径的反向X_X(单域名多应用)
所有项目共用一个域名,通过 URL 路径区分:
# /etc/nginx/conf.d/multi-app.conf
server {
listen 80;
server_name www.example.com;
# === 用户服务 ===
location /api/user/ {
proxy_pass http://127.0.0.1:8081/api/user/;
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;
}
# === 订单服务 ===
location /api/order/ {
proxy_pass http://127.0.0.1:8082/api/order/;
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;
}
# === 商品服务 ===
location /api/product/ {
proxy_pass http://127.0.0.1:8083/api/product/;
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;
}
# 默认首页或网关入口
location / {
return 302 /api/user/login;
}
}
💡 关键提示:
proxy_pass末尾的/会影响路径传递行为:
proxy_pass http://127.0.0.1:8081/;→/api/user/info转发为/infoproxy_pass http://127.0.0.1:8081;→/api/user/info转发为/api/user/info根据 SpringBoot 应用的
context-path配置选择合适的方式。
方案三:带 HTTPS 的完整配置(生产推荐)
# /etc/nginx/conf.d/secure-multi-app.conf
server {
listen 80;
server_name www.example.com api.example.com;
# 强制 HTTP → HTTPS 重定向
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example.com api.example.com;
# SSL 证书配置
ssl_certificate /etc/nginx/ssl/www.example.com.pem;
ssl_certificate_key /etc/nginx/ssl/www.example.com.key;
# SSL 优化参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 日志
access_log /var/log/nginx/secure-access.log;
error_log /var/log/nginx/secure-error.log;
# 安全头
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# --- 用户服务 ---
location /api/user/ {
proxy_pass http://127.0.0.1:8081/api/user/;
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;
# 限流(可选)
limit_req zone=user_limit burst=20 nodelay;
}
# --- 订单服务 ---
location /api/order/ {
proxy_pass http://127.0.0.1:8082/api/order/;
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;
limit_req zone=order_limit burst=20 nodelay;
}
# --- 商品服务 ---
location /api/product/ {
proxy_pass http://127.0.0.1:8083/api/product/;
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;
limit_req zone=product_limit burst=20 nodelay;
}
# 静态资源
location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
root /var/www/static;
expires 30d;
add_header Cache-Control "public, immutable";
}
# 自定义错误页
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
定义限流区域(放在 http {} 块中,如 /etc/nginx/nginx.conf):
http {
# ... 其他配置 ...
limit_req_zone $binary_remote_addr zone=user_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=order_limit:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=product_limit:10m rate=10r/s;
include /etc/nginx/conf.d/*.conf;
}
四、Nginx 常用命令
# 测试配置文件语法
sudo nginx -t
# 重新加载配置(不中断服务)
sudo nginx -s reload
# 查看 Nginx 状态
sudo systemctl status nginx
# 查看访问日志
tail -f /var/log/nginx/access.log
# 查看错误日志
tail -f /var/log/nginx/error.log
五、阿里云额外配置
1. 安全组规则
在阿里云控制台 → ECS → 安全组中添加规则:
| 方向 | 协议 | 端口范围 | 授权对象 | 描述 |
|---|---|---|---|---|
| 入方向 | TCP | 80 | 0.0.0.0/0 | HTTP |
| 入方向 | TCP | 443 | 0.0.0.0/0 | HTTPS |
| 入方向 | TCP | 22 | 你的IP/32 | SSH |
❌ 不要开放 8081、8082、8083 等内部应用端口!
2. DNS 解析
在阿里云 DNS 控制台添加 A 记录:
user.example.com → 你的ECS公网IP
order.example.com → 你的ECS公网IP
product.example.com → 你的ECS公网IP
www.example.com → 你的ECS公网IP
3. SSL 证书申请(Let’s Encrypt 免费证书)
# 安装 certbot
sudo yum install certbot python3-certbot-nginx -y
# 获取证书(自动配置 Nginx)
sudo certbot --nginx -d www.example.com -d api.example.com
# 自动续期
sudo crontab -e
# 添加: 0 3 * * 1 certbot renew --quiet
六、SpringBoot 端注意事项
1. 配置 application.yml
server:
port: 8081 # 实际监听端口
servlet:
context-path: /api/user # 如果使用了基于路径的方案
# 信任X_X头(让 SpringBoot 正确识别真实 IP)
server:
forward-headers-strategy: native
2. CORS 跨域配置(如果前端与后端不同源)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://www.example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
3. 统一 API 前缀建议
| 应用 | 端口 | Context Path | 示例请求 |
|---|---|---|---|
| user-service | 8081 | /api/user |
GET /api/user/profile |
| order-service | 8082 | /api/order |
POST /api/order/create |
| product-service | 8083 | /api/product |
GET /api/product/list |
七、高可用进阶方案
1. Nginx 负载均衡(同一应用多实例)
upstream user-service-cluster {
server 127.0.0.1:8081 weight=5;
server 127.0.0.1:8084 weight=5;
keepalive 32;
}
server {
location /api/user/ {
proxy_pass http://user-service-cluster/api/user/;
# ... 其他 proxy 配置 ...
}
}
2. Nginx Plus / OpenResty(高级功能)
- 动态健康检查
- 微服务路由
- 灰度发布
3. Docker + Nginx 容器化部署
# Dockerfile for Nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/ssl:/etc/nginx/ssl
- ./logs/nginx:/var/log/nginx
depends_on:
- user-service
- order-service
- product-service
restart: always
user-service:
build: ./user-service
ports:
- "8081:8081"
restart: always
order-service:
build: ./order-service
ports:
- "8082:8082"
restart: always
product-service:
build: ./product-service
ports:
- "8083:8083"
restart: always
八、常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 502 Bad Gateway | 后端服务未启动 | 检查 ps -ef | grep java |
| 504 Gateway Timeout | 后端响应慢 | 增加 proxy_read_timeout |
| 404 Not Found | 路径不匹配 | 检查 proxy_pass 末尾 / |
| 跨域错误 | CORS 未配置 | 后端添加 CORS 配置 |
| 无法访问 | 防火墙/安全组 | 检查阿里云安全组和系统防火墙 |
| SSL 报错 | 证书过期/格式错误 | 用 openssl x509 -in cert.pem -text 检查 |
# 快速诊断命令
curl -I http://127.0.0.1:8081/api/user/test # 直接测后端
curl -I http://localhost/api/user/test # 经 Nginx 测
sudo nginx -t # 检查 Nginx 配置
journalctl -u nginx -f # 查看 Nginx 日志
总结流程图
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ 浏览器/A │────▶│ Nginx │────▶│ SpringBoot App │
│ 客户端 │ │ (端口80/443) │ │ (端口8081+) │
└─────────────┘ └──────────────┘ └─────────────────┘
│ │
┌───────┴───────┐ ┌────┴────┐
│ 域名路由 │ │ 数据库 │
│ 路径路由 │ │ Redis │
│ 负载均衡 │ │ MQ │
└───────────────┘ └─────────┘
核心要点:
- Nginx 作为唯一入口,对外只开放 80/443
- 每个 SpringBoot 应用监听不同内部端口
- 通过域名或路径将请求分发到对应应用
- 配置正确的 proxy headers 确保后端能获取真实客户端信息
- 生产环境务必启用 HTTPS
CLOUD技术博