Ubuntu下Nginx的部署后端项目(Java为例),配置Nginx代理

一、后端项目部署

1.环境准备

确保服务器已安装java环境(JDK 17+):

bash 复制代码
java -version

若未安装

bash 复制代码
sudo apt update && sudo apt install openjdk-17-jdk

同时在服务器云平台安全组开放一个端口供后端使用(以下用8080端口为例)

添加规则,端口范围设置为8080,源地址设置为127.0.0.1/32(仅限服务器本地访问)

2.上传 JAR 包(Xftp)

将本地打包好的 JAR 文件(以app.jar为例)拖拽至服务器的/opt/app目录

设置权限

bash 复制代码
sudo chown root:root /opt/app/app.jar
sudo chmod 500 /opt/app/app.jar  # 禁止非root修改

3.部署服务(Xshell)

停止旧的服务(若存在)

bash 复制代码
#查找进程 PID
ps -ef | grep java

#停止旧进程
kill -9 <PID>

# 确认进程已退出
ps -ef | grep java | grep -v grep  # 应无输出

启动 JAR 包 (指定8080端口)

bash 复制代码
cd /opt/app  # 进入 JAR 目录

nohup java -jar app.jar --server.port=8080 > app.log 2>&1 &  # 后台运行并指定端口

验证服务

bash 复制代码
# 检查进程
ps -ef | grep java | grep 8080

# 测试端口
curl -v http://localhost:9191/(后接后端写好的接口路径)
telnet 127.0.0.1 8080  # 应能连接

# 查看日志
tail -f /opt/app/app.log

4.配置Systemd服务(持久化运行)

创建服务文件并写入配置

bash 复制代码
sudo tee /etc/systemd/system/app.service <<'EOF'
[Unit]
Description=App Service (Port 8080)
After=network.target

[Service]
User=root
WorkingDirectory=/opt/app
ExecStart=/usr/bin/java -jar --server.port=8080 app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30
StandardOutput=file:/var/log/app.log
StandardError=inherit

[Install]
WantedBy=multi-user.target
EOF

启用服务

bash 复制代码
sudo systemctl daemon-reload
sudo systemctl start app
sudo systemctl enable app

5.关键注意事项

端口冲突检查

bash 复制代码
sudo netstat -tulnp | grep 8080  # 确保无其他服务占用

二、Nginx配置代理将前端请求转发到后端服务

1.若前端部署在同一个服务器

例如是blog.yourdomain.com 先将前端部署配置好,请看本文章

然后可以设置前端请求的 BaseURL 为 /api

然后修改/etc/nginx/sites-available中的配置文件,此处为blog.yourdomain.com

bash 复制代码
# /etc/nginx/sites-available/blog.yourdomain.com
server {
    listen 80;
    server_name blog.yourdomain.com;
    return 301 https://$host$request_uri; # 强制HTTPS
}

server {
    listen 443 ssl;
    server_name blog.yourdomain.com;

    # SSL证书
    ssl_certificate /etc/letsencrypt/live/blog.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # 前端静态资源
    root /var/www/blog.yourdomain.com/html;
    index index.html;

    # 静态资源缓存(优化加载)
    location ~* \.(js|css|png|jpg|ico|svg)$ {
        expires 30d;
        access_log off;
        add_header Cache-Control "public";
    }

    # 后端API代理规则(核心!)
    location /api {
        # 代理到API专用域名(注意: 使用127.0.0.1提升安全性)
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # 跨域支持(与前端同域,无需额外CORS头)
    }

    # 日志管理
    access_log /var/log/nginx/blog.access.log combined;
    error_log /var/log/nginx/blog.error.log warn;
}

在原来的基础上添加后端API代理规则将请求代理到8080端口

修改好后保存退出然后测试重载Nginx服务

bash 复制代码
sudo nginx -t && sudo systemctl restart nginx

2.若前端部署在其他服务器

安全起见,需要给本服务器也搞个后端服务的专属域名,此处以api.yourdomain.com为例

可以设置前端请求的 BaseURL 为 api.yourdomain.com

首先同上先根据本文章给这个域名创建好链接,请看本文章(因为需要配置证书,这里先根据文章也给这个域名配置了简单的html文件)

然后修改/etc/nginx/sites-available中的配置文件,此处为api.yourdomain.com

bash 复制代码
# /etc/nginx/sites-available/api.yourdomain.com
server {
    listen 80;
    server_name api.yourdomain.com;
    return 301 https://$host$request_uri; # 强制HTTPS重定向
}

server {
    listen 443 ssl;
    server_name api.yourdomain.com;

    # SSL证书(Certbot托管)
    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # 用户端直接访问路由
    location / {
        # 后端JAR服务(端口8080)
        proxy_pass http://127.0.0.1:8080; 
        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 60s;
        proxy_read_timeout 180s;
    }

    # 日志管理
    access_log /var/log/nginx/api.access.log combined;
    error_log /var/log/nginx/api.error.log warn;
}

在原来的基础上添加后端API代理规则将请求代理到8080端口,删去了前端静态资源的路径

修改好后保存退出然后测试重载Nginx服务

bash 复制代码
sudo nginx -t && sudo systemctl restart nginx

然后可以去/var/www/中将api.yourdomain.com文件夹删去(只用于获取证书,后续已无用)

3.测试

bash 复制代码
# 测试本服务器的前端项目直连API
curl -k https://blog.yourdomain.com/api/(后接后端写好的接口路径)

# 测试其他服务器的前端项目直连API
curl -k https://api.yourdomain.com/(后接后端写好的接口路径)

成功返回数据说明代理成功(如下例子)

4.Nginx代理转发原理

a. ​​location匹配规则​

  • 当请求进入Nginx时,会根据location指令匹配请求的URI路径。

  • 例如:location /api会匹配以/api开头的所有请求。

b. ​​proxy_pass转发机制​

  • proxy_pass指令用于定义后端服务器的地址。

  • 转发行为取决于proxy_pass后是否包含路径:

    • ​情况A:proxy_pass末尾有斜杠(/)​

      例如:proxy_pass http://backend/;

      此时,匹配到的location路径(这里是/api)会被​​替换​​为proxy_pass指定的路径。

      请求:/api/user/dish/list→ 转发为:http://backend/user/dish/list

    • ​情况B:proxy_pass末尾没有斜杠​

      例如:proxy_pass http://backend;

      此时,匹配到的location路径(/api)会被​​追加​​到proxy_pass指定的地址后。

      请求:/api/user/dish/list→ 转发为:http://backend/api/user/dish/list

c.基本转发规则​

bash 复制代码
location /api {
    proxy_pass http://backend:port;
}
  • 请求路径​ ​:/api/user/dish/list

  • ​转发结果​ ​:http://backend:port/api/user/dish/list

  • ​关键点​ ​:location匹配的路径段 ​​会保留​​ 并追加到目标地址后

d.路径改写(移除前缀)

bash 复制代码
location /api {
    proxy_pass http://backend:port/;  # 注意结尾的/
}
  • ​请求路径​ ​:/api/user/dish/list

  • ​转发结果​ ​:http://backend:port/user/dish/list

  • ​关键点​ ​:结尾的 /会 ​​移除匹配的路径段​

三、后端服务更新

1.停止旧服务

bash 复制代码
# 1. 优雅停止服务
sudo systemctl stop app

# 2. 等待完全停止(最多30秒)
timeout 30 bash -c 'while systemctl is-active --quiet app; do sleep 1; done'

# 3. 强制终止(若未停止)
sudo pkill -9 -f app.jar

2.​​清理环境​

bash 复制代码
# 1. 释放文件锁
sudo fuser -k /opt/app/app.jar 2>/dev/null

# 2. 清理旧日志(保留最后100行)
tail -n 100 /opt/app/app.log > /tmp/last100.log
sudo mv /tmp/last100.log /opt/app/app.log

# 3. 重置权限
sudo chmod 600 /opt/app/app.log  # 临时限制

3.部署新版本​

bash 复制代码
# 1. 上传新JAR(使用SFTP/SCP)
# 假设新文件在 ~/app-new.jar

# 2. 原子化替换
sudo rsync -av --checksum ~/app-new.jar /opt/app/app.jar

# 3. 设置权限
sudo chmod 500 /opt/app/app.jar
sudo chown appuser:appgroup /opt/app/app.jar  # 按实际用户

4.启动新服务

bash 复制代码
# 1. 启动服务
sudo systemctl start app

# 2. 监控启动日志
sudo tail -f /opt/app/app.log | grep -m 1 "Started"

# 3. 恢复日志权限
sudo chmod 644 /opt/app/app.log

5.验证更新

bash 复制代码
# 1. 检查进程
ps -ef | grep java | grep 8080

# 2. 测试接口
curl -s http://localhost:8080/接口路径 | jq .status

# 3. 日志连续性检查
echo "===== 更新标记 $(date) =====" | sudo tee -a /opt/app/app.log
tail -n 5 /opt/app/app.log