nginx

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > nginx > Linux搭建Nginx服务器

Linux搭建Nginx反向代理服务器的实战指南

作者:知远漫谈

在现代Web架构中,Nginx作为高性能的反向代理服务器,早已成为互联网基础设施的重要组成部分,本篇博客将从零开始,带你一步步在Linux系统上搭建一个完整的 Nginx 反向代理环境,并结合Java后端服务进行实际演示,需要的朋友可以参考下

在现代 Web 架构中,Nginx 作为高性能的反向代理服务器,早已成为互联网基础设施的重要组成部分。它不仅能够高效处理静态资源、负载均衡和缓存加速,还能灵活地将请求转发至后端多个服务实例,实现高可用与弹性伸缩。本篇博客将从零开始,带你一步步在 Linux 系统上搭建一个完整的 Nginx 反向代理环境,并结合 Java 后端服务进行实际演示,让你真正掌握企业级部署的核心技能。

为什么选择 Nginx?

Nginx(发音为 “engine-x”)是一款轻量级、高性能的 HTTP 和反向代理服务器,同时支持 IMAP/POP3/SMTP 协议。它最初由俄罗斯程序员 Igor Sysoev 开发,目的是解决 C10K 问题(即单机并发处理一万个连接)。如今,Nginx 已广泛应用于全球各大网站,包括 Netflix、Dropbox、WordPress.com 等知名平台。

Nginx 的核心优势:

准备工作:Linux 环境初始化

我们以 Ubuntu 22.04 LTS 为例(其他发行版如 CentOS、Debian 也可类比操作),首先确保你的系统已更新并安装了基础工具。

sudo apt update && sudo apt upgrade -y
sudo apt install curl wget vim net-tools -y

确认系统信息:

lsb_release -a
uname -r

输出示例:

Distributor ID: Ubuntu
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
Codename:       jammy
5.15.0-86-generic

安装 Nginx

Ubuntu 官方仓库已包含 Nginx,直接使用 apt 安装即可:

sudo apt install nginx -y

安装完成后,启动并设置开机自启:

sudo systemctl start nginx
sudo systemctl enable nginx

检查状态:

sudo systemctl status nginx

你应该看到类似如下输出:

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-06-03 10:00:00 UTC; 1min ago

测试是否成功:打开浏览器访问服务器 IP 地址(如 http://your-server-ip),应看到 Nginx 欢迎页面:“Welcome to nginx!”

Nginx 基础配置结构解析

Nginx 的主配置文件位于 /etc/nginx/nginx.conf,而站点配置通常放在 /etc/nginx/sites-available/ 目录下,通过软链接激活到 /etc/nginx/sites-enabled/

查看默认配置:

cat /etc/nginx/sites-available/default

关键结构说明:

server {
    listen 80;                  # 监听端口
    server_name localhost;      # 主机名或域名
    location / {                # 匹配根路径
        root /var/www/html;     # 静态文件根目录
        index index.html;       # 默认首页
    }
}

每次修改配置后,务必先测试语法是否正确:

sudo nginx -t

若无报错,重载配置:

sudo systemctl reload nginx

配置第一个反向代理:代理本地 Java 服务

假设你有一个运行在 localhost:8080 的 Java Spring Boot 应用,现在你想通过 Nginx 将外部 80 端口的请求转发给它。

Step 1:创建新的站点配置

sudo vim /etc/nginx/sites-available/my-java-app

写入以下内容:

server {
    listen 80;
    server_name your-domain.com;  # 或者写 IP,如 192.168.1.100
    location / {
        proxy_pass http://localhost: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;
    }
}

Step 2:启用配置

sudo ln -s /etc/nginx/sites-available/my-java-app /etc/nginx/sites-enabled/

Step 3:测试并重载

sudo nginx -t
sudo systemctl reload nginx

现在,访问 http://your-server-ip 就会看到 Java 应用的内容!

编写一个简单的 Java Spring Boot 示例应用

为了演示完整流程,我们来快速构建一个最简化的 Spring Boot 项目。

创建 Maven 项目pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>nginx-demo-app</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.5</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

创建主启动类Application.java

package com.example.nginxdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @RestController
    static class HelloController {
        @GetMapping("/")
        public String hello() {
            return "Hello from Java Spring Boot via Nginx Reverse Proxy! 🚀";
        }
        @GetMapping("/health")
        public String health() {
            return "{\"status\": \"UP\", \"message\": \"Service is healthy\"}";
        }
    }
}

编译打包并运行

mvn clean package
java -jar target/nginx-demo-app-1.0.0.jar

默认监听 8080 端口。你可以先本地测试:

curl http://localhost:8080/
# 输出:Hello from Java Spring Boot via Nginx Reverse Proxy! 🚀

多实例负载均衡配置

真实生产环境中,我们通常部署多个 Java 实例以提高可用性和吞吐量。Nginx 可以轻松实现负载均衡。

修改 Nginx 配置,定义 upstream

upstream backend_servers {
    server 127.0.0.1:8080 weight=3;   # 权重3
    server 127.0.0.1:8081;            # 权重1(默认)
    server 127.0.0.1:8082;            # 权重1
}
server {
    listen 80;
    server_name your-domain.com;
    location / {
        proxy_pass http://backend_servers;
        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;
    }
}

weight 表示权重,数值越大分配请求越多;默认为 1。

启动多个 Java 实例

由于端口冲突,我们需要让每个实例监听不同端口:

# 终端1
java -jar target/nginx-demo-app-1.0.0.jar --server.port=8080
# 终端2
java -jar target/nginx-demo-app-1.0.0.jar --server.port=8081
# 终端3
java -jar target/nginx-demo-app-1.0.0.jar --server.port=8082

或者使用脚本批量启动:

#!/bin/bash
for port in 8080 8081 8082; do
    java -jar target/nginx-demo-app-1.0.0.jar --server.port=$port > /dev/null 2>&1 &
    echo "Started instance on port $port with PID $!"
done

保存为 start-all.sh 并执行:

chmod +x start-all.sh
./start-all.sh

现在刷新浏览器多次访问,你会发现请求被轮流分发到不同端口 —— 这就是轮询负载均衡!

使用 Mermaid 图表展示请求流转

让我们用 Mermaid 图形化展示整个反向代理 + 负载均衡的架构:

该图清晰展示了客户端请求如何经由 Nginx 分发到后端多个 Java 实例,所有实例共享同一数据源(如 MySQL、Redis)。

配置 HTTPS(SSL/TLS)

现代 Web 应用必须支持 HTTPS。我们可以使用免费的 Let’s Encrypt 证书,或自签名证书用于测试。

自签名证书生成(仅用于开发)

sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/selfsigned.key \
    -out /etc/nginx/ssl/selfsigned.crt

填写信息时,Common Name 建议填你的域名或 IP。

修改 Nginx 配置支持 HTTPS

server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;  # 强制跳转 HTTPS
}

server {
    listen 443 ssl;
    server_name your-domain.com;

    ssl_certificate /etc/nginx/ssl/selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/selfsigned.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://backend_servers;
        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;
    }
}

重载配置:

sudo nginx -t && sudo systemctl reload nginx

现在访问 https://your-server-ip(忽略浏览器警告),即可看到加密连接下的 Java 应用!

健康检查与故障转移

Nginx 支持对后端服务进行健康检查,自动剔除不可用节点。

配置主动健康检查(需商业版或使用开源模块)

标准开源版不支持主动探测,但我们可以通过被动方式(如超时失败)实现简单容错。

upstream backend_servers {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 max_fails=3 fail_timeout=30s;
}

含义:如果某节点连续 3 次失败,则在 30 秒内不再分配请求给它。

Java 端增加健康检查接口

修改之前的 HelloController

@GetMapping("/health")
public ResponseEntity<Map<String, Object>> healthCheck() {
    Map<String, Object> body = new HashMap<>();
    body.put("status", "UP");
    body.put("timestamp", System.currentTimeMillis());
    body.put("hostname", getHostName());
    return ResponseEntity.ok(body);
}
private String getHostName() {
    try {
        return InetAddress.getLocalHost().getHostName();
    } catch (Exception e) {
        return "unknown";
    }
}

这样你就可以通过访问 /health 判断服务是否存活。

限流与安全防护

Nginx 内置多种安全机制,防止恶意攻击或突发流量压垮后端。

基于 IP 的访问限制

location /admin {
    allow 192.168.1.0/24;
    deny all;
    proxy_pass http://backend_servers;
}

请求速率限制(漏桶算法)

http {
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    server {
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            proxy_pass http://backend_servers;
        }
    }
}

解释:

日志分析与监控

Nginx 默认记录访问日志和错误日志:

你可以自定义日志格式:

log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/detailed.log detailed;

实时查看日志:

tail -f /var/log/nginx/access.log

配合 ELK(Elasticsearch + Logstash + Kibana)或 Grafana Loki,可实现可视化监控。

高级功能:WebSocket 代理支持

如果你的 Java 应用使用 WebSocket(如聊天室、实时通知),需要特殊配置:

location /ws/ {
    proxy_pass http://backend_servers;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

Java 端示例(Spring WebSocket):

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }
}

前端连接:

const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
    console.log('Connected: ' + frame);
});

缓存静态资源提升性能

虽然我们主要代理动态 Java 应用,但也可以让 Nginx 缓存部分响应,减轻后端压力。

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
    location /api/data {
        proxy_cache my_cache;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_pass http://backend_servers;
    }
}

Java 端控制缓存头:

@GetMapping("/api/data")
public ResponseEntity<String> getData(HttpServletResponse response) {
    response.setHeader("Cache-Control", "max-age=600, public");
    return ResponseEntity.ok("Cached data from Java backend");
}

性能调优建议

1. 调整 Worker 进程数

根据 CPU 核心数设置:

worker_processes auto;  # 或具体数字,如 4

2. 优化连接队列

events {
    worker_connections 1024;
    use epoll;           # Linux 高效 I/O 模型
    multi_accept on;
}

3. 启用 Gzip 压缩

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1024;

4. 文件描述符限制

编辑 /etc/security/limits.conf

nginx soft nofile 65536
nginx hard nofile 65536

然后重启 Nginx。

自动化部署脚本示例

编写 Shell 脚本一键部署:

#!/bin/bash
# deploy-nginx-java.sh
echo "🔄 正在停止旧 Java 进程..."
pkill -f nginx-demo-app
echo "📦 正在启动三个 Java 实例..."
for port in 8080 8081 8082; do
    nohup java -jar target/nginx-demo-app-1.0.0.jar --server.port=$port > /tmp/app-$port.log 2>&1 &
    echo "✅ 启动端口 $port,PID: $!"
done
echo "🛠️  正在重载 Nginx 配置..."
sudo nginx -t && sudo systemctl reload nginx
echo "🚀 部署完成!访问 http://localhost 查看效果"

赋予执行权限并运行:

chmod +x deploy-nginx-java.sh
./deploy-nginx-java.sh

故障排查技巧

常见错误及解决方案:

502 Bad Gateway

403 Forbidden

404 Not Found

Nginx 启动失败

结语:拥抱现代化 Web 架构

通过本篇教程,你已经掌握了在 Linux 上搭建 Nginx 反向代理服务器的全流程,并成功将其与 Java 后端服务集成。无论是单实例代理、多节点负载均衡,还是 HTTPS 加密、限流防护、WebSocket 支持,Nginx 都能游刃有余地胜任。

更重要的是,这套架构具备极强的扩展性 —— 你可以轻松接入 Redis 缓存、MySQL 数据库、消息队列 Kafka、容器编排 Kubernetes……构建属于你自己的云原生应用体系。

记住,技术没有终点,只有不断演进的过程。愿你在 DevOps 与云架构的道路上越走越远,成为真正的全栈工程师!

附录:完整 Nginx 配置文件示例(含注释)

# /etc/nginx/sites-available/full-config
upstream backend_servers {
    server 127.0.0.1:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 max_fails=3 fail_timeout=30s;
}
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate /etc/nginx/ssl/selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/selfsigned.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    # 缓存配置
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
    # 健康检查页面
    location /health {
        access_log off;
        return 200 'OK\n';
        add_header Content-Type text/plain;
    }
    # API 限流
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        proxy_pass http://backend_servers;
        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 支持
    location /ws/ {
        proxy_pass http://backend_servers;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    # 默认代理
    location / {
        proxy_pass http://backend_servers;
        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;
    }
    # 自定义错误页
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

希望这篇详尽的指南能为你在 Linux 上部署 Nginx + Java 架构打下坚实基础。动手实践是掌握技术的最佳途径 —— 不妨现在就打开终端,开始你的第一行配置吧。

以上就是Linux搭建Nginx反向代理服务器的实战指南的详细内容,更多关于Linux搭建Nginx服务器的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文