跳转至

第2章 Linux 服务器与 Nginx 配置

学习目标

  • 掌握 Linux 服务器运维基础,能完成 AI Agent 服务的部署与守护
  • 理解 Nginx 反向代理原理,能编写生产级配置
  • 学会配置负载均衡、SSL/TLS 证书与 HTTPS
  • 掌握 Nginx 静态资源服务与性能调优方法
  • 能够为 AI Agent 服务搭建稳定、安全、高性能的接入层

问题导入

某团队把 Agent API 容器化后直接用 docker run -p 80:8000 暴露到公网,结果一周内接连踩坑:①没有 HTTPS,浏览器报"不安全",企业客户拒绝接入;②单容器扛不住突发流量,Agent 接口超时但无横向扩展能力;③LLM 流式响应(SSE)经 Nginx 默认配置后被缓冲,前端收不到逐字输出,体验崩塌;④服务器被扫描器疯狂爆破 SSH,安全告警不断。

这些问题的根因是:容器只是应用载体,生产接入层需要专业的反向代理与服务器运维。Nginx 作为高性能反向代理,承担 TLS 终止、负载均衡、流式透传、静态资源服务等关键职责。本章讲解 Linux 运维基础与 Nginx 生产配置,帮你搭建可靠的 Agent 服务接入层。

核心概念

1. Linux 基础运维

生产服务器运维的核心任务:

  • 用户与权限:禁止 root 远程登录,创建普通用户 + sudo 提权
  • SSH 加固:改默认端口、禁用密码登录、仅允许密钥认证
  • 防火墙:用 ufw 或 firewalld 只开放必要端口(80、443、SSH)
  • 进程守护:用 systemd 或 supervisor 管理服务,崩溃自动重启
  • 日志管理:journalctl 查看系统日志,logrotate 防止日志撑满磁盘
  • 资源监控:htop、vmstat、df 监控 CPU、内存、磁盘

2. Nginx 反向代理

反向代理是 Nginx 最核心的用途:客户端访问 Nginx,Nginx 把请求转发给后端服务。对 AI Agent 的价值:

  • 隐藏后端:客户端只看到 Nginx 入口,后端容器不直接暴露
  • TLS 终止:HTTPS 在 Nginx 解密,后端用 HTTP,减少后端加解密开销
  • 统一接入:多个 Agent 服务通过不同路径或域名统一对外
  • 缓冲与限流:保护后端免受慢客户端与大流量冲击

3. 负载均衡

当单容器扛不住流量时,部署多个 Agent 实例,Nginx 把请求分发到不同实例。常用策略:

  • 轮询(默认):依次分配,适合实例性能一致
  • 最少连接(least_conn):优先分配给当前连接数最少的实例
  • IP 哈希(ip_hash):同一客户端固定到同一实例,利于会话亲和
  • 权重(weight):按实例性能分配不同权重

注意:AI Agent 流式响应是长连接,least_conn 通常比轮询更合适。

4. SSL/TLS 配置

HTTPS 是生产标配,配置要点:

  • 证书获取:用 Let's Encrypt 免费证书(certbot 工具自动签发与续期)
  • 协议版本:仅启用 TLS 1.2 与 1.3,禁用不安全的 SSLv3/TLS 1.0/1.1
  • 加密套件:优先使用前向保密的 ECDHE 套件
  • HSTS:强制浏览器后续都走 HTTPS
  • 证书续期:Let's Encrypt 证书 90 天过期,用 crontab 或 systemd timer 自动续期

5. 流式响应(SSE)透传

AI Agent 的流式输出(Server-Sent Events)对代理配置很敏感。Nginx 默认会缓冲响应,导致 SSE 失效。必须:

  • 关闭代理缓冲:proxy_buffering off
  • 关闭 gzip:避免压缩破坏流式边界
  • 设置较长 proxy_read_timeout:LLM 推理可能耗时数十秒
  • 启用 HTTP/1.1:proxy_http_version 1.1,支持长连接

6. 性能调优

生产 Nginx 的关键调优参数:

  • worker_processes:与 CPU 核心数一致
  • worker_connections:单 worker 的最大连接数(流式场景调大)
  • keepalive_timeout:长连接保活时长
  • gzip:压缩文本响应(注意不要压缩 SSE 流)
  • 客户端缓冲:client_max_body_size 调大以支持上传文档

原理图

flowchart LR
    Client[客户端<br/>浏览器/App] -->|HTTPS 443| Nginx

    subgraph Nginx["Nginx 反向代理"
        TLS[TLS 终止]
        LB[负载均衡]
        SSE[SSE 透传]
        Static[静态资源]
    end]

    Nginx -->|HTTP 8000| API1[Agent 实例1]
    Nginx -->|HTTP 8000| API2[Agent 实例2]
    Nginx -->|HTTP 8000| API3[Agent 实例3]

    subgraph 后端["后端服务集群"
        API1
        API2
        API3
    end]

    API1 --> Redis[(Redis)]
    API1 --> PG[(PostgreSQL)]
    API1 --> VDB[(向量库)]

    Client -.->|静态资源| Static

图:Nginx 反向代理架构——客户端经 HTTPS 接入 Nginx,由其终止 TLS、负载均衡分发到多个 Agent 实例,并透传 SSE 流式响应

示例代码

1. 生产级 Nginx 配置(Agent 服务)

# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 8192;
    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" '
                    'rt=$request_time urt=$upstream_response_time';

    access_log /var/log/nginx/access.log main;
    error_log  /var/log/nginx/error.log warn;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    client_max_body_size 50m;  # 支持上传文档

    # gzip 压缩(排除 SSE 流)
    gzip on;
    gzip_min_length 1024;
    gzip_comp_level 5;
    gzip_types text/plain application/json application/javascript text/css;
    gzip_disable "MSIE [1-6]\.";

    # 上游 Agent 服务集群
    upstream agent_backend {
        least_conn;  # 最少连接策略,适合长连接流式场景
        server 127.0.0.1:8001 max_fails=3 fail_timeout=30s;
        server 127.0.0.1:8002 max_fails=3 fail_timeout=30s;
        server 127.0.0.1:8003 max_fails=3 fail_timeout=30s;
        keepalive 32;  # 到后端的长连接池
    }

    # HTTP 跳转 HTTPS
    server {
        listen 80;
        server_name agent.mycorp.com;
        return 301 https://$host$request_uri;
    }

    # HTTPS 主服务
    server {
        listen 443 ssl http2;
        server_name agent.mycorp.com;

        # SSL 证书
        ssl_certificate     /etc/letsencrypt/live/agent.mycorp.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/agent.mycorp.com/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 1d;

        # 安全头
        add_header Strict-Transport-Security "max-age=31536000" always;
        add_header X-Content-Type-Options nosniff always;
        add_header X-Frame-Options DENY always;

        # 健康检查端点
        location /health {
            proxy_pass http://agent_backend/health;
            access_log off;
        }

        # SSE 流式接口(关键配置)
        location /v1/chat/stream {
            proxy_pass http://agent_backend;
            proxy_http_version 1.1;
            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;

            # SSE 透传核心配置
            proxy_buffering off;        # 关闭缓冲
            proxy_cache off;            # 关闭缓存
            proxy_set_header Connection '';  # 清除 Connection 头
            chunked_transfer_encoding on;
            proxy_read_timeout 300s;    # LLM 推理可能耗时较长
            proxy_send_timeout 300s;
        }

        # 普通 API 接口
        location /v1/ {
            proxy_pass http://agent_backend;
            proxy_http_version 1.1;
            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 5s;
            proxy_read_timeout 60s;
        }

        # 静态资源(前端界面)
        location /static/ {
            alias /var/www/agent-static/;
            expires 30d;
            add_header Cache-Control "public, immutable";
        }
    }
}

2. 用 certbot 申请 Let's Encrypt 证书

# 安装 certbot
sudo apt install -y certbot python3-certbot-nginx

# 自动签发并配置 Nginx
sudo certbot --nginx -d agent.mycorp.com

# 测试自动续期(证书 90 天过期)
sudo certbot renew --dry-run

3. systemd 守护 Agent 服务

# /etc/systemd/system/agent-api.service
[Unit]
Description=AI Agent API Service
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
WorkingDirectory=/opt/agent
ExecStart=/usr/bin/docker compose -f /opt/agent/docker-compose.yml up
ExecStop=/usr/bin/docker compose -f /opt/agent/docker-compose.yml down
Restart=always
RestartSec=10
TimeoutStartSec=120

[Install]
WantedBy=multi-user.target
# 启用并启动
sudo systemctl daemon-reload
sudo systemctl enable agent-api
sudo systemctl start agent-api
sudo systemctl status agent-api

4. 防火墙与 SSH 加固

# ufw 防火墙配置
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp      # SSH(建议改非默认端口)
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw enable

# SSH 加固:编辑 /etc/ssh/sshd_config
# Port 22022
# PermitRootLogin no
# PasswordAuthentication no
# 只允许密钥认证
sudo systemctl restart sshd

企业案例

案例 1:生产环境 Nginx 部署客服 Agent

某 SaaS 厂商上线 AI 客服 Agent,初期直接暴露容器端口到公网,遇到 HTTPS、流式、单点三大问题。改造方案:在前端部署 Nginx 反向代理,申请 Let's Encrypt 证书启用 HTTPS,用 upstream 配置 3 个 Agent 实例做负载均衡,针对 /v1/chat/stream 路径专门配置 SSE 透传(关闭 proxy_buffering、延长 proxy_read_timeout 到 300s)。

改造后效果:①HTTPS 通过企业客户安全审计;②3 实例负载均衡使 QPS 从单机 50 提升到 140;③流式响应延迟从"等 8 秒一次性出"变为"首字 1.2 秒逐字输出";④Nginx 自动剔除故障实例,单实例崩溃用户无感知。关键经验:SSE 透传配置是 AI Agent 接入层的重中之重,默认缓冲配置会让流式体验完全失效。

案例 2:多租户 Agent 的域名路由

某平台为多家企业提供独立 Agent 服务,用 Nginx 的多 server 块按域名路由:tenant-a.com 转发到 A 租户的 Agent 实例组,tenant-b.com 转发到 B 租户实例组,共享同一 Nginx 入口。配合 limit_req 模块按租户限流,防止单租户突发流量拖垮整体服务。

常见问题

Q1:流式响应(SSE)在前端一次性出现,没有逐字效果,怎么办?

A:是 Nginx 缓冲导致的。在 SSE 路径配置 proxy_buffering off、proxy_cache off、proxy_http_version 1.1、proxy_set_header Connection '',并延长 proxy_read_timeout。同时确保后端响应头是 Content-Type: text/event-stream。

Q2:502 Bad Gateway 频繁出现怎么排查?

A:①检查后端服务是否启动并监听正确端口;②curl http://127.0.0.1:8001/health 验证后端可达;③查看 Nginx error.log 中的具体原因(连接超时、拒绝连接);④检查 upstream 中 max_fails 是否把实例标记为不可用。

Q3:Let's Encrypt 证书过期了怎么自动续期?

A:用 certbot renew 配合 systemd timer 或 crontab 定时执行。certbot renew 会在过期前 30 天自动续期并 reload Nginx。命令:sudo crontab -e 添加 0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"。

Q4:负载均衡选轮询还是最少连接?

A:AI Agent 流式请求是长连接(可能持续数十秒),轮询会导致某些实例堆积大量长连接而其他实例空闲。最少连接(least_conn) 更适合这种场景。若有会话状态依赖,用 ip_hash 保证同一客户端落到同一实例。

Q5:Nginx 与后端容器如何通信?

A:两种方式:①后端容器映射端口到宿主机(如 -p 8001:8000),Nginx 通过 127.0.0.1:8001 访问;②Nginx 也容器化,与后端容器加入同一 Docker 网络,用服务名直接访问(如 http://agent-api:8000)。生产推荐后者,配置更清晰。

面试题

  1. 简答题:反向代理与正向代理的区别是什么?

参考要点:正向代理代理客户端(如 VPN),客户端感知代理存在;反向代理代理服务端(如 Nginx),客户端无感知,以为访问的就是真实服务。Nginx 是反向代理,隐藏后端、提供负载均衡与 TLS 终止。

  1. 配置题:如何让 Nginx 正确透传 SSE 流式响应?

参考要点:proxy_buffering off、proxy_cache off、proxy_http_version 1.1、proxy_set_header Connection ''、chunked_transfer_encoding on、延长 proxy_read_timeout。

  1. 设计题:设计一个支持 3 个 Agent 实例的高可用接入方案。

参考要点:Nginx 用 upstream 定义 3 实例,least_conn 策略,max_fails 自动剔除故障实例,keepalive 复用连接;HTTPS 用 Let's Encrypt;SSE 路径单独配置透传;配合 systemd 守护 Nginx 与后端。

  1. 原理题:为什么 AI Agent 场景下 least_conn 通常比轮询更合适?

参考要点:Agent 流式请求是长连接(数十秒),轮询会把新请求分给连接数已多的实例;least_conn 优先分配给当前连接最少的实例,负载更均衡。

  1. 安全题:生产 Nginx 应做哪些安全加固?

参考要点:仅启用 TLS 1.2/1.3;配置安全头(HSTS、X-Frame-Options);隐藏 Nginx 版本号;限制请求体大小;按需配置 limit_req 限流;定期续期证书;日志脱敏。

练习题

  1. 基础配置:为本章 Agent 服务编写 Nginx 配置,要求 HTTPS、负载均衡 3 实例、SSE 透传,并用 nginx -t 验证语法。

  2. 证书实战:用 certbot 为一个测试域名申请 Let's Encrypt 证书,配置自动续期,并验证续期命令。

  3. 故障排查:故意停掉一个后端实例,观察 Nginx 的 max_fails 机制是否自动剔除该实例,恢复后是否自动加回。

小结

Linux 运维与 Nginx 配置是 Agent 服务上线的接入层基石。本章核心:Linux 服务器要做好用户权限、SSH 加固、防火墙、进程守护;Nginx 作为反向代理承担 TLS 终止、负载均衡、SSE 透传、静态资源服务;流式响应的 proxy_buffering off 配置是 AI Agent 场景的关键;SSL/TLS 与安全头是生产标配。接入层就绪后,如何让代码到上线的流程自动化,是第 3 章 CI/CD 的主题。