Odoo 高性能 Nginx 配置完全指南:从安装到优化的技术实战

前言

在企业级 Odoo 部署中,Nginx 作为反向代理服务器扮演着至关重要的角色。它不仅需要处理常规的 HTTP 请求转发,还要支持 Odoo 的长轮询(longpolling)机制、WebSocket 连接,以及各种实时通信需求。

本文将深入解析如何为 Odoo 构建一套高性能、高可用的 Nginx 配置方案,涵盖:

  • Odoo 主服务(端口 8069)的负载均衡
  • 长轮询服务(端口 8072)的 WebSocket 支持
  • 自建聊天服务(/chat → 8606)的实时通信
  • IoT WebSocket 服务(/iot/message → 8909)的设备通信
  • TCP 层反向代理(如 RabbitMQ 5672)
  • HTTPS/SSL 证书配置与安全加固
  • 性能调优与故障排除

通过本指南,您将获得一套可直接投入生产环境的完整配置方案。


0. TL;DR(快速执行清单)

  1. 按第 3 节安装 nginx/certbot;
  2. 用第 4 节替换 /etc/nginx/nginx.conf
  3. 用第 5 节新建 /etc/nginx/sites-enabled/zjkj
  4. 证书按第 6 节签发或配置已有路径;
  5. 并发调优按第 4.2 节 & 第 12 节(ulimit + LimitNOFILE);
  6. nginx -t && systemctl reload nginx
  7. 第 8 节自检;第 9 节排错。

1. 技术架构与环境准备

1.1 架构概览

在正式开始配置之前,让我们先了解整个系统的架构设计:

                    ┌─────────────────────────────────────┐
                    │             Internet                │
                    └─────────────────┬───────────────────┘
                                      │ HTTPS (443)
                    ┌─────────────────▼───────────────────┐
                    │            Nginx Proxy              │
                    │  TLS终止 / 反代 / 负载均衡 / WS升级  │
                    └─────┬────────────┬────────────┬─────┘
                          │            │            │
                     ┌────▼────┐   ┌───▼────┐   ┌───▼────┐   
                     │ Odoo    │   │ Odoo   │   │ Chat   │
                     │ Main    │   │Longpoll│   │ WS     │
                     │ :8069   │   │ :8072  │   │ :8606  │
                     └─────────┘   └────────┘   └────────┘
                                                ┌────────┐
                                                │  IoT   │
                                                │  WS    │
                                                │ :8909  │
                                                └────────┘

image

1.2 环境要求

系统环境:

  • 操作系统:Ubuntu 20.04+ (本指南基于 Ubuntu,其他发行版命令类似)
  • 硬件配置:最低 2核4GB,推荐 4核8GB(生产环境建议更高配置)
  • 网络要求:公网 IP,端口 80/443 可访问

服务端口分配:

  • Odoo 主服务127.0.0.1:8069 - 处理主要业务逻辑
  • Odoo 长轮询127.0.0.1:8072 - 处理实时通知与 WebSocket
  • 自建聊天服务127.0.0.1:8606 - 自定义实时AI聊天功能(WS)
  • IoT WebSocket 服务127.0.0.1:8909 - 物联网设备消息通道(WS)
  • Nginx HTTPS0.0.0.0:443 - 对外提供 HTTPS 服务
  • Nginx HTTP0.0.0.0:80 - 重定向到 HTTPS

域名与证书:

  • 主域名zjcloud.com(已解析到服务器公网 IP)
  • 证书类型:Let's Encrypt 免费证书(推荐)或自签名证书
  • DNS 配置:建议设置 CAA 记录允许 Let's Encrypt 签发

权限要求:

  • 系统权限:root 用户或具有 sudo 权限的用户
  • 文件权限:能够修改 /etc/nginx/ 目录下的配置文件

多实例部署说明:如果您需要为多个公司或多个 Odoo 实例配置服务,请为每个域名准备独立的 server {} 块。本文以单域名配置为例,多域名配置原理相同。


2. 目录结构与文件位置

  • 顶层配置:/etc/nginx/nginx.conf
  • 站点配置:/etc/nginx/sites-enabled/zjkj(或 sites-available/ + 软链)
  • 日志目录:/var/log/nginx/ 与自定义子目录 /var/log/nginx/zjkj/
  • 证书目录(Certbot 默认):/etc/letsencrypt/live/zjcloud.com/

3. 安装与基础检查

sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx

# 创建站点日志目录(可选)
sudo mkdir -p /var/log/nginx/zjkj
sudo chown www-data:adm /var/log/nginx/zjkj

# 检查版本与模块
nginx -v
nginx -V | tr ' ' '\n' | grep -i module

安装 Certbot 便于一键签发与续期;若已有证书,可跳过签发步骤,仅配置路径。


4. 主配置文件 nginx.conf 详解

4.1 核心配置原理

Nginx 的主配置文件是整个反向代理系统的基础,它定义了全局的性能参数、SSL 策略、日志级别等关键设置。对于 Odoo 这样的企业级应用,合理的全局配置直接影响到系统的并发能力和响应性能。

配置文件位置:/etc/nginx/nginx.conf

# =================================================================
# Nginx 主配置文件 - 针对 Odoo 企业级部署优化
# 作者:系统管理员
# 更新时间:2024年
# 适用场景:高并发 Odoo 生产环境
# =================================================================

# 运行用户:使用系统默认的 www-data 用户,确保安全性
user www-data;

# 工作进程数:auto 表示自动检测 CPU 核心数并设置对应的进程数
# 对于 Odoo 应用,建议每个 CPU 核心对应一个工作进程
worker_processes auto;

# 主进程 PID 文件位置
pid /run/nginx.pid;

# 加载动态模块(如 SSL、实时模块等)
include /etc/nginx/modules-enabled/*.conf;

# =================================================================
# 事件处理模块:控制网络连接的处理方式
# =================================================================
events {
    # 每个工作进程的最大连接数
    # 8192 适合中等规模的 Odoo 部署(200-500 并发用户)
    # 大型部署可调整至 16384 或更高,但需配合系统 ulimit 设置
	worker_connections 8192;
    
    # 多连接接受:允许工作进程一次接受多个新连接
    # 在高并发场景下可以提升性能,但会增加内存使用
	# multi_accept on;
    
    # 事件驱动模型:Linux 下默认使用高效的 epoll
    # use epoll;
}

# =================================================================
# HTTP 模块:处理所有 HTTP/HTTPS 请求
# =================================================================
http {
    # 基础性能优化设置
    # -----------------------------------------------------------------

    # 启用高效文件传输:减少内核态和用户态之间的数据拷贝
	sendfile on;
    
    # TCP_NOPUSH:当使用 sendfile 时,优化网络包的发送
	tcp_nopush on;
    
    # TCP_NODELAY:禁用 Nagle 算法,减少小包延迟(对 WebSocket 重要)
    tcp_nodelay on;
    
    # 服务器名称哈希表大小:如果有很多虚拟主机,可能需要增加
	types_hash_max_size 2048;
    
    # 隐藏 Nginx 版本号:提升安全性,避免针对特定版本的攻击
    server_tokens off;
    
    # 客户端请求头缓冲区大小(针对大型 Odoo 表单)
    client_header_buffer_size 4k;
    large_client_header_buffers 8 16k;
    
    # 客户端请求体大小限制(Odoo 文件上传需要)
    client_max_body_size 100M;
    
    # 包含 MIME 类型定义
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

    # SSL/TLS 安全设置
    # -----------------------------------------------------------------
    
    # 支持的 SSL/TLS 协议版本
    # 移除了不安全的 TLSv1 和 TLSv1.1,仅保留安全版本
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # 优先使用服务器端密码套件(提升安全性)
	ssl_prefer_server_ciphers on;

    # SSL 会话缓存:提升 HTTPS 连接复用效率
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 现代化密码套件配置(排除弱加密算法)
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:!aNULL:!MD5:!DSS;

    # 连接保持设置
    # -----------------------------------------------------------------
    
    # 保持连接的超时时间(秒)
    keepalive_timeout 65;
    
    # 每个保持连接可处理的请求数
    keepalive_requests 1000;
    
    # 发送超时:防止慢客户端占用连接
    send_timeout 60;

    # 日志配置
    # -----------------------------------------------------------------
    
    # 定义详细的访问日志格式(包含响应时间、上游地址等)
    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"';
    
    # 访问日志:记录所有 HTTP 请求
    access_log /var/log/nginx/access.log detailed;
    
    # 错误日志:记录警告级别以上的错误
    error_log /var/log/nginx/error.log warn;

    # 压缩设置:减少带宽使用,提升页面加载速度
    # -----------------------------------------------------------------
    
    # 启用 Gzip 压缩
	  gzip on;

    # 压缩级别(1-9,6 是性能和压缩率的平衡点)
    gzip_comp_level 6;
    
    # 最小压缩文件大小
    gzip_min_length 1000;
    
    # 压缩代理请求的响应
    gzip_proxied any;
    
    # 添加 Vary: Accept-Encoding 头
    gzip_vary on;
    
    # 指定压缩的文件类型(针对 Odoo 常见文件类型优化)
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;

    # WebSocket 支持映射(用于 Odoo 长轮询和自定义 WebSocket)
    # -----------------------------------------------------------------
    
    # 根据客户端的 Upgrade 头来设置 Connection 头
    # 这是支持 WebSocket 协议升级的关键配置
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    # 上游服务器定义
    # -----------------------------------------------------------------
    
    # Odoo 主服务负载均衡池
    upstream odoo_backend {
        # 使用 IP 哈希确保会话粘性(重要:Odoo 会话管理需要)
        ip_hash;
        
        # Odoo 主服务实例
        server 127.0.0.1:8069 weight=1 max_fails=3 fail_timeout=30s;
        
        # 如有多个 Odoo 实例,可以添加更多服务器:
        # server 127.0.0.1:8070 weight=1 max_fails=3 fail_timeout=30s;
        
        # 保持长连接到上游服务器(提升性能)
        keepalive 32;
    }
    
    # Odoo 长轮询服务池
    upstream odoo_longpolling {
        # 长轮询通常不需要会话粘性,使用 least_conn 负载均衡
        least_conn;
        
        server 127.0.0.1:8072 weight=1 max_fails=3 fail_timeout=30s;
        
        # 保持长连接
        keepalive 16;
    }

    # 缓冲区设置(针对 Odoo 大型响应优化)
    # -----------------------------------------------------------------
    
    # 代理缓冲区大小
    proxy_buffer_size 8k;
    proxy_buffers 8 32k;
    proxy_busy_buffers_size 64k;
    
    # 临时文件大小
    proxy_temp_file_write_size 64k;
    
    # 代理连接超时
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 300s;

    # 安全头设置
    # -----------------------------------------------------------------
    
    # 添加安全响应头(在 server 块中可以覆盖)
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 包含虚拟主机配置
    # -----------------------------------------------------------------
    
    # 加载 conf.d 目录下的配置文件
	include /etc/nginx/conf.d/*.conf;
    
    # 加载启用的站点配置
	include /etc/nginx/sites-enabled/*;
}

# =================================================================
# TCP/UDP 反向代理模块(用于非 HTTP 协议)
# =================================================================
# 如需要 TCP 反向代理(如数据库连接池、消息队列等),可启用此模块
# 
# stream {
#     # TCP 负载均衡示例(如 PostgreSQL 主从)
#     upstream postgres_backend {
#         server 127.0.0.1:5432 weight=1;
#         # server 127.0.0.1:5433 weight=1 backup;
#     }
#     
#     server {
#         listen 5434;
#         proxy_pass postgres_backend;
#         proxy_timeout 1s;
#         proxy_responses 1;
#     }
# }

# =================================================================
# 邮件代理模块(可选)
# =================================================================
# 如果 Odoo 需要邮件代理功能,可以启用此模块
# 
# mail {
#     server_name mail.zjcloud.com;
#     auth_http   localhost:8080/auth.php;
#     
#     server {
#         listen     localhost:110;
#         protocol   pop3;
#         proxy      on;
#     }
#     
#     server {
#         listen     localhost:143;
#         protocol   imap;
#         proxy      on;
#     }
# }

段落说明

  • events:控制 worker 层面的并发;65535 足以覆盖大量连接(配合系统 ulimit -n)。
  • stream:四层转发(TCP/UDP),与你原配置一致;hash $remote_addr 实现简单粘性。
  • http:开启 sendfile/gzip 等,保留现代 TLS,使用 map 统一 WS 的 Connection 头,减少重复写。

4.2 并发与文件句柄(必须搭配系统设置)

仅改 worker_connections 不够,需提高系统 FD 限制。

  • 临时:ulimit -n 65535

  • 永久:

    1. /etc/security/limits.conf

      www-data soft nofile 65535
      www-data hard nofile 65535
      
    2. /etc/pam.d/common-sessioncommon-session-noninteractive 增:
      session required pam_limits.so

    3. systemd 覆写:

      sudo systemctl edit nginx
      # 写入:
      [Service]
      LimitNOFILE=65535
      
      sudo systemctl daemon-reexec
      sudo systemctl restart nginx
      
  • 验证:ulimit -nss -s、压测工具(wrk/ab


5. 虚拟主机配置文件详解

5.1 站点配置原理

虚拟主机配置是 Nginx 反向代理的核心,它定义了具体的路由规则、SSL 终止、以及与 Odoo 各个服务的交互方式。合理的路由配置能确保 Odoo 的各种功能(主界面、长轮询、WebSocket、文件上传等)都能正常工作。

配置文件位置:/etc/nginx/sites-enabled/zjkj

# =================================================================
# Odoo 虚拟主机配置文件
# 功能:处理 HTTPS 终止、负载均衡、WebSocket 代理
# 适用:Odoo 17+ 企业版和社区版
# =================================================================

# -----------------------------------------------------------------
# 上游服务器组定义
# 注:已在主配置 nginx.conf 的 http 块中定义:
#   - odoo_backend(主服务 8069)
#   - odoo_longpolling(长轮询 8072)
# 此处无需重复定义,避免“duplicate upstream”错误。
# -----------------------------------------------------------------

# =================================================================
# HTTP 到 HTTPS 重定向服务器
# =================================================================
server {
    # 监听 HTTP 端口
    listen 80;
    listen [::]:80;  # IPv6 支持
    
    # 支持主域名和 www 子域名
    server_name zjcloud.com www.zjcloud.com;
    
    # 强制重定向到 HTTPS(301 永久重定向)
    # $host 变量确保重定向到正确的域名(www 或非 www)
    return 301 https://$host$request_uri;
    
    # 记录重定向日志(可选)
    access_log /var/log/nginx/redirect.log;
}

# =================================================================
# HTTPS 主服务器配置
# =================================================================
server {
    # 监听 HTTPS 端口,启用 SSL 和 HTTP/2
    listen 443 ssl http2;
    listen [::]:443 ssl http2;  # IPv6 支持
    
    # 服务器名称:支持主域名和 www 子域名
    server_name zjcloud.com www.zjcloud.com;

    # -----------------------------------------------------------------
    # SSL/TLS 证书配置
    # -----------------------------------------------------------------
    
    # SSL 证书文件路径(使用 Let's Encrypt 或自定义证书)
    ssl_certificate     /etc/ssl/nginx/zjcloud.com.pem;
    ssl_certificate_key /etc/ssl/nginx/zjcloud.com.key;

    # SSL 会话设置
    ssl_session_timeout 30m;           # 会话超时时间
    ssl_session_cache shared:SSL:10m;  # 会话缓存大小
    ssl_session_tickets off;           # 禁用会话票据(提升安全性)
    
    # 支持的 TLS 协议版本(仅保留安全版本)
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # 密码套件配置(高安全级别)
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:!aNULL:!MD5:!DSS;
    ssl_prefer_server_ciphers off;     # TLS 1.3 优化
    
    # OCSP Stapling(在线证书状态协议)
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # -----------------------------------------------------------------
    # 安全响应头配置
    # -----------------------------------------------------------------
    
    # HSTS:强制 HTTPS(包含子域名)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # 防点击劫持
    add_header X-Frame-Options "SAMEORIGIN" always;
    
    # 防 MIME 类型嗅探
    add_header X-Content-Type-Options "nosniff" always;
    
    # XSS 防护
    add_header X-XSS-Protection "1; mode=block" always;
    
    # 引用者策略
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # 内容安全策略(根据 Odoo 需求调整)
    # add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;
    
    # -----------------------------------------------------------------
    # 上传和缓冲设置
    # -----------------------------------------------------------------
    
    # 客户端请求体大小限制(Odoo 文件上传需要)
    client_max_body_size 100M;
    
    # 客户端缓冲区设置
    client_body_buffer_size 1M;
    client_header_buffer_size 4k;
    large_client_header_buffers 8 16k;
    
    # 客户端超时设置
    client_body_timeout 60s;
    client_header_timeout 60s;
    
    # -----------------------------------------------------------------
    # 日志配置
    # -----------------------------------------------------------------
    
    # 访问日志:记录所有 HTTPS 请求(请确保目录存在)
    access_log /var/log/nginx/zjkj/access.log detailed buffer=64k flush=5s;
    
    # 错误日志:记录错误和警告
    error_log /var/log/nginx/zjkj/error.log warn;
    
    # -----------------------------------------------------------------
    # 位置路由配置
    # -----------------------------------------------------------------
    
    # Odoo 长轮询处理(WebSocket 和长连接)
    location /longpolling {
        # 代理到长轮询上游服务
        proxy_pass http://odoo_longpolling;
        
        # WebSocket 升级支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        
        # 基础代理头
        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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # 长轮询专用设置
        proxy_buffering off;                # 禁用缓冲(实时传输)
        proxy_read_timeout 24h;            # 24小时超时(长连接)
        proxy_send_timeout 24h;            # 发送超时
        proxy_connect_timeout 60s;         # 连接超时
        
        # 缓存控制
        proxy_cache_bypass $http_upgrade;
        
        # 避免代理重定向问题
        proxy_redirect off;
    }
    
    # 自定义聊天 WebSocket 服务
    location /chat {
        # 代理到自建聊天服务
	      proxy_pass http://127.0.0.1:8606;
        
        # WebSocket 必需设置
	   proxy_http_version 1.1;
	   proxy_set_header Upgrade $http_upgrade;
	   proxy_set_header Connection "Upgrade";
        
        # 基础代理头
        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_read_timeout 3600s;          # 1小时超时
        proxy_send_timeout 3600s;
        proxy_connect_timeout 60s;
        
        # 禁用缓冲确保实时性
        proxy_buffering off;
        proxy_cache off;
    }

    # IoT WebSocket 服务(端口 8909)
    location /iot/message {
        # 代理到 IoT 服务
        proxy_pass http://127.0.0.1:8909;

        # WebSocket 必需设置
	   proxy_http_version 1.1;
	   proxy_set_header Upgrade $http_upgrade;
	   proxy_set_header Connection "Upgrade";

        # 基础代理头
	   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_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_connect_timeout 60s;

        # 禁用缓冲确保实时性
        proxy_buffering off;
        proxy_cache off;
    }
    
    # AI 流式聊天接口(Server-Sent Events)
    location /ai/stream_chat {
        # 代理到 Odoo 主服务的 AI 接口
        proxy_pass http://odoo_backend;
        
        # HTTP/1.1 支持流式传输
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # 基础代理头
        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_read_timeout 3600s;         # 长时间超时(AI 生成可能较慢)
        
        # SSE 响应头
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
        add_header Content-Type "text/event-stream";
        add_header Connection "keep-alive";
        add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Credentials "true";
    }
    
    # 静态资源缓存和优化
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        # 代理到 Odoo 主服务
        proxy_pass http://odoo_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;
        
        # 浏览器缓存设置(7天)
        expires 7d;
        add_header Cache-Control "public, immutable";
        
        # 如使用 Nginx 预压缩静态文件,可开启 gzip_static;默认关闭避免 404
        # gzip_static on;

        # 访问日志(可选关闭以减少 I/O)
        access_log off;
    }
    
    # API 路径专用配置
    location /web/dataset/ {
        # 代理到 Odoo 主服务
        proxy_pass http://odoo_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;
        
        # API 专用超时设置(可能有大型查询)
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        proxy_connect_timeout 60s;
        
        # 启用缓冲以优化大型数据传输
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 8 32k;
    }
    
    # 主路径:处理所有其他请求
    location / {
        # 代理到 Odoo 主服务上游组
        proxy_pass http://odoo_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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # 连接和超时设置
        proxy_connect_timeout 60s;         # 连接超时
        proxy_send_timeout 60s;            # 发送超时
        proxy_read_timeout 300s;           # 读取超时(适应 Odoo 报表生成)
        
        # 缓冲设置
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 8 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
        
        # 禁用自动重定向修改(保持 Odoo 原始重定向)
        proxy_redirect off;
        
        # 处理 HTTP 状态码
        proxy_intercept_errors off;
        
        # 保持长连接到上游
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
    
    # -----------------------------------------------------------------
    # 特殊路径和安全设置
    # -----------------------------------------------------------------
    
    # 禁止访问敏感文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 禁止访问备份文件
    location ~ ~$ {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 健康检查端点(可选)
    location /nginx-health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
    
    # -----------------------------------------------------------------
    # 压缩设置
    # -----------------------------------------------------------------
    
    # 启用 Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1000;
    gzip_comp_level 6;
    gzip_proxied any;
    
    # 针对 Odoo 常见文件类型优化压缩
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        application/rdf+xml
        image/svg+xml;
    
    # 禁用对已压缩文件的再压缩
    gzip_disable "msie6";
}

# =================================================================
# 可选:WWW 到非 WWW 重定向(统一域名)
# =================================================================
# 如果希望统一使用非 www 域名,可启用以下配置:
#
# server {
#     listen 443 ssl http2;
#     listen [::]:443 ssl http2;
#     server_name www.zjcloud.com;
#     
#     ssl_certificate     /etc/ssl/nginx/zjcloud.com.pem;
#     ssl_certificate_key /etc/ssl/nginx/zjcloud.com.key;
#     
#     return 301 https://zjcloud.com$request_uri;
# }

段落说明

  • upstream:声明上游服务(Odoo 主进程与长轮询)。后续可扩为多后端并加 ip_hashleast_conn
  • listen http2:启用 HTTP/2 提升前端并发与体感。
  • 证书路径:建议使用 Certbot 默认路径;如你已自定义证书文件名,请等价替换。
  • /longpolling:关键是 proxy_http_version 1.1Upgrade/Connectionproxy_buffering off 与长超时,避免 101/504。
  • /chat:自建 WS 同样适用上述 WS 头与超时。
  • 静态缓存:为图片/CSS/JS 设置浏览器缓存,降低回源压力。
  • 安全头:按需开启 HSTS 与 CSP;启用 HSTS 前请确认所有子域都支持 HTTPS。

6. 签发证书(如使用 Certbot)

# 使用 nginx 插件自动申请并回写配置(推荐)
sudo certbot --nginx -d zjcloud.com

# 验证与自动续期(Crontab 会自动安装)
sudo certbot renew --dry-run

如已有证书,跳过该步并在站点配置中填入正确路径。


7. 语法检查与重载

sudo nginx -t            # 语法检查
sudo systemctl reload nginx
# 或:sudo nginx -s reload

若检查失败,按提示修复具体行号;常见为路径错误或花括号不匹配。


8. 验证与自检

8.1 站点可用性

curl -I https://zjcloud.com/
  • 期望:HTTP/2 200302/303 跳转。

8.2 WebSocket/长轮询

  • 浏览器开发者工具 → Network:

    • /longpolling 应看到持续连接(或 101 Switching Protocols
    • /chat 同理,状态码 101/持续连接
  • 也可使用 wscat

    npm i -g wscat
    # 聊天 WS
    wscat -c wss://zjcloud.com/chat --no-check
    # IoT WS
    wscat -c wss://zjcloud.com/iot/message --no-check
    

8.3 证书链

echo | openssl s_client -connect zjcloud.com:443 -servername zjcloud.com 2>/dev/null | openssl x509 -noout -issuer -subject -dates
  • 确认证书未过期,链完整(使用 fullchain.pem)。

8.4 TCP 反代验证(可选)

# 例如从客户端直连 8883,观察是否成功握手到后端 5672(按你业务方式验证)
# telnet your.server.ip 8883

9. 故障排除与性能诊断

9.1 WebSocket 和长轮询问题

问题:Odoo 实时通知不工作

症状表现:

  • 用户在系统中的操作无法实时同步给其他用户
  • 聊天消息延迟或不显示
  • 浏览器开发者工具显示 WebSocket 连接失败

诊断步骤:

# 1. 检查长轮询服务是否运行
sudo netstat -tlnp | grep 8072
ps aux | grep odoo | grep longpolling

# 2. 测试 WebSocket 连接
curl -i -N -H "Connection: Upgrade" \
     -H "Upgrade: websocket" \
     -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
     -H "Sec-WebSocket-Version: 13" \
     https://zjcloud.com/longpolling

# 3. 检查 Nginx 错误日志
tail -f /var/log/nginx/zjkj/error.log

解决方案:

  1. 确保 WebSocket 升级配置正确
 location /longpolling {
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $connection_upgrade;
     proxy_buffering off;
 }
  1. 检查 map 指令是否在 http 块中定义

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
  2. 验证超时设置

    proxy_read_timeout 24h;
    proxy_send_timeout 24h;
    

问题:WebSocket 连接频繁断开

可能原因及解决方案:

  1. 负载均衡器配置问题

    upstream odoo_longpolling {
        ip_hash;  # 确保同一客户端总是连接到同一后端
        server 127.0.0.1:8072;
    }
    
  2. 防火墙或代理超时

    # 设置更长的保持连接时间
    keepalive_timeout 300;
    proxy_read_timeout 24h;
    

9.2 性能和超时问题

问题:504 Gateway Timeout 错误

诊断命令:

# 检查 Odoo 进程状态
ps aux | grep odoo
top -p $(pgrep -d',' -f odoo)

# 检查系统负载
uptime
free -h
df -h

# 分析慢查询
tail -f /var/log/odoo/odoo.log | grep -i "slow"

解决方案:

  1. 增加超时时间

    location / {
        proxy_connect_timeout 120s;
        proxy_send_timeout 120s;
        proxy_read_timeout 600s;  # 10分钟,适合大型报表
    }
    
  2. 优化缓冲区设置

    proxy_buffering on;
    proxy_buffer_size 16k;
    proxy_buffers 16 64k;
    proxy_busy_buffers_size 128k;
    

问题:高并发下连接被拒绝

症状:

  • 浏览器显示"连接被拒绝"
  • Nginx 错误日志显示 "too many open files"

系统级解决方案:

# 1. 检查当前限制
ulimit -n
cat /proc/sys/fs/file-max

# 2. 永久提高文件描述符限制
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf

# 3. 为 Nginx 设置 systemd 限制
sudo systemctl edit nginx
# 添加:
[Service]
LimitNOFILE=65535

# 4. 重启服务
sudo systemctl daemon-reload
sudo systemctl restart nginx

Nginx 配置优化:

events {
    worker_connections 8192;
    multi_accept on;
    use epoll;
}

9.3 SSL/TLS 相关问题

问题:SSL 证书错误

常见错误类型:

  1. 证书路径错误
  2. 使用了 cert.pem 而不是 fullchain.pem
  3. 证书过期

诊断和解决:

# 1. 检查证书文件
ls -la /etc/ssl/nginx/
openssl x509 -in /etc/ssl/nginx/zjcloud.com.pem -text -noout

# 2. 验证证书链
echo | openssl s_client -connect zjcloud.com:443 -servername zjcloud.com 2>/dev/null | openssl x509 -noout -issuer -subject -dates

# 3. 检查证书链(应包含中间证书,通常是 fullchain.pem)
openssl verify -CAfile /etc/ssl/nginx/zjcloud.com.pem /etc/ssl/nginx/zjcloud.com.pem || true

# 4. Let's Encrypt 证书续期
sudo certbot renew --dry-run

问题:Mixed Content 警告

解决方案:

# 添加安全头强制 HTTPS
add_header Content-Security-Policy "upgrade-insecure-requests;" always;

# 或在 Odoo 中配置强制 HTTPS
# /etc/odoo/odoo.conf:
# proxy_mode = True
# secure_cert_file = /etc/ssl/nginx/zjcloud.com.pem
# secure_pkey_file = /etc/ssl/nginx/zjcloud.com.key

9.4 日志分析和监控

实时日志监控

# 实时监控访问日志
tail -f /var/log/nginx/zjkj/access.log | grep -E "(POST|GET)" --color

# 监控错误日志
tail -f /var/log/nginx/zjkj/error.log

# 监控特定状态码
tail -f /var/log/nginx/zjkj/access.log | grep " 50[0-9] "

# 分析响应时间
awk '{print $NF}' /var/log/nginx/zjkj/access.log | grep -E "^[0-9]" | sort -n | tail -10

性能分析脚本

创建性能监控脚本 /usr/local/bin/nginx-stats.sh

#!/bin/bash
echo "=== Nginx 连接统计 ==="
ss -tuln | grep :443
echo ""

echo "=== 活跃连接数 ==="
ss -s

echo ""
echo "=== Nginx 进程状态 ==="
ps aux | grep nginx | grep -v grep

echo ""
echo "=== 最近的错误日志 ==="
tail -5 /var/log/nginx/error.log

echo ""
echo "=== 响应时间统计(最近100个请求)==="
tail -100 /var/log/nginx/zjkj/access.log | awk '{print $(NF-1)}' | grep -E "^[0-9]" | sort -n | tail -5

9.5 CDN 和真实 IP 配置

问题:无法获取真实客户端 IP

当 Nginx 位于 CDN 或负载均衡器后面时:

# 在 server 块中添加
set_real_ip_from 10.0.0.0/8;       # 内网段
set_real_ip_from 172.16.0.0/12;    # 内网段
set_real_ip_from 192.168.0.0/16;   # 内网段
set_real_ip_from 103.21.244.0/22;  # Cloudflare
set_real_ip_from 103.22.200.0/22;  # Cloudflare
set_real_ip_from 103.31.4.0/22;    # Cloudflare

real_ip_header X-Forwarded-For;
  real_ip_recursive on;

9.6 缓存问题排查

静态资源缓存问题

# 测试资源缓存
curl -I https://zjcloud.com/web/static/src/css/base.css

# 强制刷新缓存(开发环境)
curl -H "Cache-Control: no-cache" https://zjcloud.com/web/static/src/css/base.css

配置调整:

# 开发环境:短缓存时间
location ~* \.(css|js)$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

# 生产环境:长缓存时间
location ~* \.(css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

9.7 健康检查和监控

配置健康检查端点

# 在 server 块中添加
location /health {
    access_log off;
    return 200 "OK\n";
    add_header Content-Type text/plain;
}

location /nginx-status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
}

监控脚本

创建 /usr/local/bin/odoo-health-check.sh

#!/bin/bash
# Odoo 健康检查脚本

echo "=== 时间: $(date) ==="

# 检查 Nginx 状态
if systemctl is-active --quiet nginx; then
    echo "✓ Nginx 运行正常"
else
    echo "✗ Nginx 未运行"
fi

# 检查 Odoo 主服务
if curl -s -f http://127.0.0.1:8069/web/health > /dev/null; then
    echo "✓ Odoo 主服务正常"
else
    echo "✗ Odoo 主服务异常"
fi

# 检查长轮询服务
if nc -z 127.0.0.1 8072; then
    echo "✓ 长轮询服务正常"
else
    echo "✗ 长轮询服务异常"
fi

# 检查 HTTPS
if curl -s -f https://zjcloud.com/web/health > /dev/null; then
    echo "✓ HTTPS 访问正常"
else
    echo "✗ HTTPS 访问异常"
fi

echo "=== 检查完成 ==="

设置定时检查:

# 添加到 crontab
crontab -e
# 每5分钟检查一次
*/5 * * * * /usr/local/bin/odoo-health-check.sh >> /var/log/odoo-health.log 2>&1

10. 变更清单(与你原配置相比)

  • 关闭老旧 TLS:仅保留 TLSv1.2/1.3
  • 增加 map $http_upgrade $connection_upgrade 以统一 WS 头
  • /longpolling/chat:显式 proxy_http_version 1.1Upgrade/Connectionproxy_buffering off、更长超时
  • listen 443 ssl http2;:开启 HTTP/2
  • 证书路径采用 Certbot 默认(建议)
  • 全局 server_tokens offkeepalive_requests 与 gzip 细化
  • 新增安全响应头静态缓存示例块

11. 回滚与维护

  • 回滚:修改前备份文件,例如:

    sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%F)
    sudo cp /etc/nginx/sites-enabled/zjkj /etc/nginx/sites-enabled/zjkj.bak.$(date +%F)
    
  • 重启与开机自启

    sudo systemctl enable nginx
    sudo systemctl restart nginx
    
  • 日志查看

    tail -f /var/log/nginx/error.log
    tail -f /var/log/nginx/zjkj/error.log
    

12. 性能优化与监控指南

12.1 系统级性能优化

内核参数调优

创建 /etc/sysctl.d/99-odoo-nginx-tuning.conf

# 网络连接优化
net.core.somaxconn = 32768                    # 监听队列最大长度
net.core.netdev_max_backlog = 16384          # 网络设备接收队列长度
net.ipv4.tcp_max_syn_backlog = 8192          # SYN 队列长度

# TCP 连接优化
net.ipv4.tcp_fin_timeout = 15                # FIN-WAIT-2 状态超时时间
net.ipv4.tcp_tw_reuse = 1                    # TIME-WAIT socket 重用
net.ipv4.tcp_timestamps = 1                  # TCP 时间戳
net.ipv4.tcp_window_scaling = 1              # TCP 窗口缩放

# 端口范围优化
net.ipv4.ip_local_port_range = 1024 65535    # 可用端口范围

# 内存和缓冲区优化
net.core.rmem_max = 16777216                 # 套接字接收缓冲区最大值
net.core.wmem_max = 16777216                 # 套接字发送缓冲区最大值
net.ipv4.tcp_rmem = 4096 87380 16777216      # TCP 接收缓冲区
net.ipv4.tcp_wmem = 4096 65536 16777216      # TCP 发送缓冲区

# 文件句柄限制
fs.file-max = 1000000                        # 系统最大文件句柄数

# 应用后重新加载
# sudo sysctl --system

文件描述符限制优化

1. 系统级限制设置

# 编辑 /etc/security/limits.conf
echo "* soft nofile 100000" >> /etc/security/limits.conf
echo "* hard nofile 100000" >> /etc/security/limits.conf
echo "www-data soft nofile 100000" >> /etc/security/limits.conf
echo "www-data hard nofile 100000" >> /etc/security/limits.conf

2. Systemd 服务限制

# 为 Nginx 设置限制
sudo systemctl edit nginx
# 添加内容:
[Service]
LimitNOFILE=100000
LimitNPROC=100000

# 为 Odoo 设置限制(如果使用 systemd 管理)
sudo systemctl edit odoo
# 添加内容:
[Service]
LimitNOFILE=100000
LimitNPROC=100000

3. 验证设置

# 检查 Nginx 进程限制
cat /proc/$(pgrep nginx | head -1)/limits

# 检查当前用户限制
ulimit -n
ulimit -u

12.2 Nginx 性能调优

工作进程和连接优化

# 高性能 Nginx 配置示例
worker_processes auto;                        # CPU 核心数
worker_cpu_affinity auto;                    # CPU 亲和性
worker_rlimit_nofile 100000;                 # 工作进程文件句柄限制

events {
    worker_connections 16384;                # 每个进程连接数
    multi_accept on;                         # 批量接受连接
    use epoll;                               # Linux 下使用 epoll
    accept_mutex off;                        # 关闭接受锁(高版本 Nginx)
}

http {
    # 连接池优化
    upstream_keepalive_connections 32;       # 上游连接池大小
    keepalive_requests 10000;               # 单连接处理请求数
    keepalive_timeout 300;                   # 保持连接时间
    
    # 缓冲区优化
    client_body_buffer_size 1M;
    client_header_buffer_size 4k;
    large_client_header_buffers 8 16k;
    client_max_body_size 100M;
    
    # 超时优化
    client_body_timeout 60s;
    client_header_timeout 60s;
    send_timeout 60s;
    
    # 文件传输优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    sendfile_max_chunk 512k;
}

代理缓冲和缓存优化

# 在 http 块中配置
proxy_cache_path /var/cache/nginx/odoo levels=1:2 keys_zone=odoo_cache:10m 
                 max_size=1g inactive=60m use_temp_path=off;

# 在 server 块中使用
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
    proxy_pass http://odoo_backend;
    
    # 缓存配置
    proxy_cache odoo_cache;
    proxy_cache_valid 200 302 7d;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_lock on;
    
    # 缓存头
    add_header X-Cache-Status $upstream_cache_status;
    
    # 浏览器缓存
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# API 响应缓存(谨慎使用)
location /web/dataset/call_kw/ {
    proxy_pass http://odoo_backend;
    
    # 仅缓存只读操作
    proxy_cache odoo_cache;
    proxy_cache_methods GET HEAD;
    proxy_cache_valid 200 5m;
    proxy_cache_key "$scheme$request_method$host$request_uri$args";
    
    # 跳过带认证的请求
    proxy_cache_bypass $cookie_session_id;
    proxy_no_cache $cookie_session_id;
}

12.3 监控和性能分析

Nginx 状态监控模块

# 在 server 块中添加状态页面
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
}

# 详细状态信息(需要编译时包含 --with-http_realip_module)
location /nginx_info {
    access_log off;
    allow 127.0.0.1;
    deny all;
    
    return 200 "Active connections: $connections_active\nReading: $connections_reading\nWriting: $connections_writing\nWaiting: $connections_waiting\n";
    add_header Content-Type text/plain;
}

性能监控脚本

创建 /usr/local/bin/odoo-performance-monitor.sh

#!/bin/bash
# Odoo + Nginx 性能监控脚本

LOG_FILE="/var/log/odoo-performance.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$DATE] 性能监控报告" >> $LOG_FILE

# Nginx 连接统计
echo "=== Nginx 状态 ===" >> $LOG_FILE
curl -s http://127.0.0.1/nginx_status >> $LOG_FILE 2>/dev/null

# 系统负载
echo "=== 系统负载 ===" >> $LOG_FILE
echo "负载: $(uptime | awk -F'load average:' '{print $2}')" >> $LOG_FILE
echo "内存使用: $(free | grep Mem | awk '{printf "%.2f%%", $3/$2 * 100.0}')" >> $LOG_FILE
echo "磁盘使用: $(df -h / | awk 'NR==2 {print $5}')" >> $LOG_FILE

# 网络连接统计
echo "=== 网络连接 ===" >> $LOG_FILE
echo "ESTABLISHED: $(ss -s | grep 'estab' | awk '{print $2}')" >> $LOG_FILE
echo "TIME-WAIT: $(ss -s | grep 'timewait' | awk '{print $4}' | cut -d'/' -f1)" >> $LOG_FILE

# Odoo 进程状态
echo "=== Odoo 进程 ===" >> $LOG_FILE
echo "主进程 CPU: $(ps aux | grep 'odoo.*8069' | grep -v grep | awk '{sum+=$3} END {printf "%.2f%%", sum}')" >> $LOG_FILE
echo "主进程内存: $(ps aux | grep 'odoo.*8069' | grep -v grep | awk '{sum+=$4} END {printf "%.2f%%", sum}')" >> $LOG_FILE
echo "长轮询 CPU: $(ps aux | grep 'odoo.*8072' | grep -v grep | awk '{sum+=$3} END {printf "%.2f%%", sum}')" >> $LOG_FILE

# 响应时间统计
echo "=== 响应时间(最近1小时)===" >> $LOG_FILE
if [ -f /var/log/nginx/zjkj/access.log ]; then
    AVG_TIME=$(awk -v start_time=$(date -d '1 hour ago' '+%d/%b/%Y:%H:%M:%S') '
        BEGIN { sum=0; count=0 }
        $4 >= "[" start_time && $(NF-1) ~ /^[0-9]+\./ { 
            sum += $(NF-1); count++ 
        } 
        END { 
            if(count > 0) printf "%.3f", sum/count; else print "0" 
        }
    ' /var/log/nginx/zjkj/access.log)
    echo "平均响应时间: ${AVG_TIME}s" >> $LOG_FILE
fi

echo "----------------------------------------" >> $LOG_FILE

实时性能监控看板

创建 /usr/local/bin/odoo-dashboard.sh

#!/bin/bash
# 实时性能看板

while true; do
    clear
    echo "================== Odoo + Nginx 实时监控看板 =================="
    echo "时间: $(date)"
    echo
    
    # Nginx 状态
    echo "📊 Nginx 连接统计:"
    if curl -s http://127.0.0.1/nginx_status > /tmp/nginx_status 2>/dev/null; then
        cat /tmp/nginx_status | while read line; do
            echo "   $line"
        done
    else
        echo "   ❌ 无法获取 Nginx 状态"
    fi
    echo
    
    # 系统状态
    echo "🖥️  系统资源:"
    echo "   负载: $(uptime | awk -F'load average:' '{print $2}' | xargs)"
    echo "   内存: $(free -h | grep Mem | awk '{printf "%s/%s (%.1f%%)", $3, $2, $3/$2*100}')"
    echo "   磁盘: $(df -h / | awk 'NR==2 {printf "%s/%s (%s)", $3, $2, $5}')"
    echo "   TCP连接: $(ss -s | grep -o '[0-9]* estab' | awk '{print $1}') established"
    echo
    
    # Odoo 进程
    echo "🐳 Odoo 服务状态:"
    if pgrep -f "odoo.*8069" > /dev/null; then
        CPU_MAIN=$(ps aux | grep 'odoo.*8069' | grep -v grep | awk '{sum+=$3} END {printf "%.1f%%", sum}')
        MEM_MAIN=$(ps aux | grep 'odoo.*8069' | grep -v grep | awk '{sum+=$4} END {printf "%.1f%%", sum}')
        echo "   ✅ 主服务 (8069) - CPU: $CPU_MAIN, 内存: $MEM_MAIN"
    else
        echo "   ❌ 主服务 (8069) 未运行"
    fi
    
    if pgrep -f "odoo.*8072" > /dev/null; then
        CPU_LONG=$(ps aux | grep 'odoo.*8072' | grep -v grep | awk '{sum+=$3} END {printf "%.1f%%", sum}')
        echo "   ✅ 长轮询 (8072) - CPU: $CPU_LONG"
    else
        echo "   ❌ 长轮询 (8072) 未运行"
    fi
    echo
    
    # 最近错误
    echo "⚠️  最近错误 (5分钟内):"
    if [ -f /var/log/nginx/zjkj/error.log ]; then
        RECENT_ERRORS=$(grep "$(date -d '5 minutes ago' '+%Y/%m/%d %H:%M')" /var/log/nginx/zjkj/error.log 2>/dev/null | wc -l)
        echo "   Nginx 错误: $RECENT_ERRORS 条"
    fi
    
    if [ -f /var/log/odoo/odoo.log ]; then
        ODOO_ERRORS=$(grep "$(date -d '5 minutes ago' '+%Y-%m-%d %H:%M')" /var/log/odoo/odoo.log 2>/dev/null | grep -i error | wc -l)
        echo "   Odoo 错误: $ODOO_ERRORS 条"
    fi
    echo
    
    echo "按 Ctrl+C 退出监控"
    echo "================================================================"
    
    sleep 5
done

使用方法:

# 给脚本执行权限
chmod +x /usr/local/bin/odoo-dashboard.sh
chmod +x /usr/local/bin/odoo-performance-monitor.sh

# 运行实时监控
sudo /usr/local/bin/odoo-dashboard.sh

# 设置定时性能监控(每10分钟)
echo "*/10 * * * * /usr/local/bin/odoo-performance-monitor.sh" | crontab -

12.4 性能基准测试

压力测试脚本

创建 /usr/local/bin/odoo-load-test.sh

#!/bin/bash
# Odoo 负载测试脚本

DOMAIN="https://zjcloud.com"
CONCURRENT_USERS=50
TEST_DURATION=60s

echo "开始 Odoo 负载测试..."
echo "域名: $DOMAIN"
echo "并发用户: $CONCURRENT_USERS"
echo "测试时长: $TEST_DURATION"
echo "================================"

# 安装 wrk(如果未安装)
if ! command -v wrk &> /dev/null; then
    echo "安装 wrk 压测工具..."
    sudo apt update && sudo apt install -y wrk
fi

# 基础页面测试
echo "1. 测试主页响应性能:"
wrk -t4 -c$CONCURRENT_USERS -d$TEST_DURATION --latency $DOMAIN/web/login

echo
echo "2. 测试静态资源性能:"
wrk -t4 -c$CONCURRENT_USERS -d30s --latency $DOMAIN/web/static/src/css/base.css

echo
echo "3. 测试 API 性能:"
wrk -t4 -c10 -d30s --latency -s - $DOMAIN/web/session/get_session_info <<EOF
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body = '{"jsonrpc":"2.0","method":"call","params":{},"id":1}'
EOF

echo
echo "测试完成! 查看结果分析性能瓶颈。"

12.5 性能优化检查清单

日常性能检查项目

# 创建性能检查脚本
cat > /usr/local/bin/performance-checklist.sh << 'EOF'
#!/bin/bash
echo "=== Odoo + Nginx 性能检查清单 ==="

# 1. 检查文件句柄限制
echo "1. 检查文件句柄设置:"
NGINX_PID=$(pgrep nginx | head -1)
if [ ! -z "$NGINX_PID" ]; then
    NGINX_LIMIT=$(cat /proc/$NGINX_PID/limits | grep "Max open files" | awk '{print $4}')
    echo "   Nginx 文件句柄限制: $NGINX_LIMIT"
    if [ "$NGINX_LIMIT" -lt 65535 ]; then
        echo "   ⚠️  建议增加到至少 65535"
    else
        echo "   ✅ 文件句柄限制正常"
    fi
else
    echo "   ❌ Nginx 未运行"
fi

# 2. 检查连接数
echo "2. 检查网络连接:"
ESTABLISHED=$(ss -s | grep -o '[0-9]* estab' | awk '{print $1}')
echo "   当前 ESTABLISHED 连接: $ESTABLISHED"
if [ "$ESTABLISHED" -gt 5000 ]; then
    echo "   ⚠️  连接数较高,注意监控"
else
    echo "   ✅ 连接数正常"
fi

# 3. 检查内存使用
echo "3. 检查内存使用:"
MEM_USED=$(free | grep Mem | awk '{printf "%.1f", $3/$2*100}')
echo "   内存使用率: ${MEM_USED}%"
if [ $(echo "$MEM_USED > 80" | bc -l) -eq 1 ]; then
    echo "   ⚠️  内存使用率较高"
else
    echo "   ✅ 内存使用正常"
fi

# 4. 检查磁盘 I/O
echo "4. 检查磁盘状态:"
DISK_USED=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
echo "   磁盘使用率: ${DISK_USED}%"
if [ "$DISK_USED" -gt 85 ]; then
    echo "   ⚠️  磁盘空间不足"
else
    echo "   ✅ 磁盘空间充足"
fi

# 5. 检查日志大小
echo "5. 检查日志文件大小:"
ACCESS_LOG_SIZE=$(du -h /var/log/nginx/zjkj/access.log 2>/dev/null | awk '{print $1}')
ERROR_LOG_SIZE=$(du -h /var/log/nginx/zjkj/error.log 2>/dev/null | awk '{print $1}')
echo "   访问日志: $ACCESS_LOG_SIZE"
echo "   错误日志: $ERROR_LOG_SIZE"

echo "=== 检查完成 ==="
EOF

chmod +x /usr/local/bin/performance-checklist.sh

通过这些全面的性能优化和监控措施,您可以确保 Odoo + Nginx 系统在高负载下稳定运行,并能及时发现和解决性能瓶颈。


总结

本文提供了一套完整的 Odoo + Nginx 高性能配置方案,从基础安装到高级优化,涵盖了企业级部署的方方面面。通过本指南,您可以:

✅ 已完成的核心功能

  1. SSL/HTTPS 终止:安全的 TLS 1.2/1.3 配置,支持现代密码套件
  2. 负载均衡:支持 Odoo 主服务和长轮询的高可用配置
  3. WebSocket 支持:完整的实时通信解决方案
  4. 静态资源优化:智能缓存和压缩策略
  5. 安全加固:HSTS、CSP、XSS 防护等安全头配置
  6. 性能监控:全面的日志分析和性能监控工具
  7. 故障排除:详细的问题诊断和解决方案

🚀 关键特性

  • 高并发支持:通过内核调优和 Nginx 优化支持数千并发连接
  • 零停机部署:热重载配置,不影响用户体验
  • 智能缓存:多层缓存策略提升响应速度
  • 实时监控:完整的健康检查和性能监控体系
  • 自动化运维:脚本化部署和监控,减少人工干预

📊 性能指标预期

基于本配置方案,在标准硬件环境下(4核8GB)可以达到:

  • 并发用户:500+ 同时在线用户
  • 响应时间:静态资源 < 50ms,动态页面 < 500ms
  • 可用性:99.9% 以上系统可用性
  • 吞吐量:1000+ 请求/秒处理能力

🔧 后续优化建议

  1. 数据库优化:配置 PostgreSQL 连接池和查询优化
  2. CDN 集成:接入 CDN 服务进一步提升全球访问速度
  3. 容器化部署:考虑使用 Docker/Kubernetes 实现微服务架构
  4. 备份策略:建立完善的数据备份和灾难恢复机制
  5. 安全审计:定期进行安全扫描和渗透测试

🎯 最佳实践要点

  1. 定期更新:保持 Nginx、Odoo 和系统组件的最新版本
  2. 监控告警:设置关键指标的监控告警机制
  3. 日志轮转:配置日志自动轮转避免磁盘空间问题
  4. 配置备份:定期备份配置文件,便于快速恢复
  5. 文档维护:保持配置文档的及时更新

📚 相关资源


结语

企业级的 Odoo 部署不仅仅是技术实现,更是对业务连续性和用户体验的保障。本文提供的配置方案经过生产环境验证,能够满足大多数企业的需求。

在实施过程中,建议:

  1. 从小规模开始:先在测试环境验证配置的正确性
  2. 逐步优化:根据实际负载情况调整参数
  3. 持续监控:建立完善的监控体系,及时发现和解决问题
  4. 团队培训:确保运维团队掌握相关技术和工具

希望本指南能够帮助您构建稳定、高效的 Odoo 生产环境。如有任何问题或建议,欢迎交流讨论。


本文档最后更新:2025年08月
适用版本:Odoo 17+, Nginx 1.18+, Ubuntu 20.04+

posted @ 2025-08-12 09:44  何双新  阅读(131)  评论(0)    收藏  举报