Files
2026-05-16 13:24:02 +08:00

18 KiB
Raw Permalink Blame History

反向代理配置

**本文档引用的文件** - [src/server.ts](file://src/server.ts) - [src/index.ts](file://src/index.ts) - [src/websocket.ts](file://src/websocket.ts) - [src/class/websockethandler.ts](file://src/class/websockethandler.ts) - [src/signaling.ts](file://src/signaling.ts) - [src/服务端接口与WebSocket消息类型.md](file://src/服务端接口与WebSocket消息类型.md) - [package.json](file://package.json) - [run.bat](file://run.bat) - [client/public/onebyone/README.md](file://client/public/onebyone/README.md) - [client/public/onebyone/code-structure.md](file://client/public/onebyone/code-structure.md)

目录

  1. 简介
  2. 项目架构概览
  3. WebRTC 场景特殊考虑
  4. Nginx 反向代理配置
  5. Apache 反向代理配置
  6. 性能优化建议
  7. 安全配置
  8. 故障排除指南
  9. 总结

简介

本指南针对视频流服务器项目提供完整的反向代理配置方案。该项目是一个基于 WebRTC 和 WebSocket 的视频通话应用,支持 HTTP 轮询和 WebSocket 两种信令协议,以及公共模式和私有模式两种通信方式。

项目采用 Node.js + Express 构建,支持 HTTPS 和 WebSocket 升级,具备完整的 WebRTC 信令交换能力。反向代理配置对于部署此类实时通信应用至关重要,需要特别关注 WebSocket 升级、长连接保持、头部转发和压缩配置等方面。

项目架构概览

graph TB
subgraph "客户端应用"
A[WebRTC 客户端]
B[浏览器应用]
end
subgraph "反向代理层"
C[Nginx/Apache]
D[负载均衡器]
end
subgraph "应用服务器"
E[Express 服务器]
F[WebSocket 服务器]
G[HTTP 轮询服务器]
end
subgraph "数据库/存储"
H[会话存储]
I[文件上传存储]
end
A --> C
B --> C
C --> E
C --> F
C --> G
E --> H
E --> I
F --> H
G --> H

图表来源

核心组件分析

项目包含以下关键组件:

  1. Express 服务器:处理 HTTP 请求、静态文件服务和 API 路由
  2. WebSocket 服务器:处理实时信令消息和 WebRTC 信令交换
  3. HTTP 轮询服务器:提供 HTTP 轮询模式的信令服务
  4. 会话管理系统:管理用户会话和连接状态
  5. 静态资源服务:提供前端应用和媒体文件

章节来源

WebRTC 场景特殊考虑

WebSocket 升级要求

WebRTC 应用对 WebSocket 升级有严格要求:

sequenceDiagram
participant Client as 客户端
participant Proxy as 反向代理
participant Server as 应用服务器
participant WS as WebSocket服务器
Client->>Proxy : HTTP Upgrade 请求
Proxy->>Proxy : 检查 Upgrade 头部
Proxy->>Server : 转发升级请求
Server->>WS : 创建 WebSocket 连接
WS->>Server : 连接建立成功
Server->>Proxy : 返回 101 Switching Protocols
Proxy->>Client : 完成协议升级
Client->>WS : 开始实时通信

图表来源

长连接保持机制

项目实现了心跳检测机制来维持长连接:

  • 心跳间隔30秒发送一次 ping 消息
  • 超时检测60秒无活动自动断开连接
  • 活动跟踪:记录最后活动时间戳

通信模式支持

项目支持两种通信模式:

  1. 公共模式:所有客户端都可以直接通信
  2. 私有模式1对多房间通信1个host + 多个participants

章节来源

Nginx 反向代理配置

基础配置模板

以下提供完整的 Nginx 配置示例:

# HTTP 到 HTTPS 重定向
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    
    # 强制 HTTPS 重定向
    return 301 https://$server_name$request_uri;
}

# HTTPS 服务器配置
server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;
    
    # SSL 证书配置
    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 安全头部
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # 静态资源缓存
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }
    
    # WebSocket 升级配置
    location / {
        proxy_pass http://localhost:8080;
        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 86400;
        proxy_send_timeout 86400;
        
        # 代理缓冲区
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
    
    # API 端点配置
    location /api/ {
        proxy_pass http://localhost:8080/api/;
        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;
    }
    
    # 静态文件服务
    location /uploads/ {
        alias /path/to/your/uploads/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

负载均衡配置

# 负载均衡配置
upstream websocket_backend {
    server 127.0.0.1:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 weight=2 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 backup;
}

upstream http_backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    
    # WebSocket 负载均衡
    location / {
        proxy_pass http://websocket_backend;
        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 86400;
        proxy_send_timeout 86400;
    }
    
    # HTTP 负载均衡
    location /api/ {
        proxy_pass http://http_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;
    }
}

静态资源缓存策略

# 静态资源缓存配置
location ~* \.(css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable, stale-while-revalidate=31536000";
    add_header Vary Accept-Encoding;
    gzip_static on;
}

location ~* \.(png|jpg|jpeg|gif|ico|svg|webp)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    add_header Vary Accept-Encoding;
}

location ~* \.(woff|woff2|ttf|otf)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# 压缩配置
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript application/xml+rss image/svg+xml;
gzip_comp_level 6;
gzip_proxied any;
gzip_disable "MSIE [1-6]\.";

章节来源

Apache 反向代理配置

基础 Apache 配置

# 启用必要的模块
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule headers_module modules/mod_headers.so

<VirtualHost *:80>
    ServerName your-domain.com
    ServerAlias www.your-domain.com
    
    # HTTP 到 HTTPS 重定向
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=310,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName your-domain.com
    ServerAlias www.your-domain.com
    
    # SSL 配置
    SSLEngine on
    SSLCertificateFile /path/to/your/certificate.crt
    SSLCertificateKeyFile /path/to/your/private.key
    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384
    
    # 安全头部
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "DENY"
    Header always set X-Content-Type-Options "nosniff"
    
    # 反向代理配置
    ProxyPreserveHost On
    ProxyRequests Off
    
    # WebSocket 升级
    ProxyPass /ws/ ws://127.0.0.1:8080/
    ProxyPassReverse /ws/ ws://127.0.0.1:8080/
    
    # HTTP 轮询
    ProxyPass /api/ http://127.0.0.1:8080/api/
    ProxyPassReverse /api/ http://127.0.0.1:8080/api/
    
    # 静态资源
    ProxyPass /uploads/ http://127.0.0.1:8080/uploads/
    ProxyPassReverse /uploads/ http://127.0.0.1:8080/uploads/
    
    # 代理超时设置
    ProxyTimeout 86400
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

mod_proxy_wstunnel 模块启用

确保启用 WebSocket 支持:

# 启用 WebSocket 隧道
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

# WebSocket 升级配置
<LocationMatch "^/">
    ProxyPass ws://127.0.0.1:8080/
    ProxyPassReverse ws://127.0.0.1:8080/
    ProxySet match=Upgrade
    ProxySet force-proxy-request-1.0 1
</LocationMatch>

虚拟主机配置

# 主虚拟主机配置
<VirtualHost *:443>
    ServerName your-domain.com
    DocumentRoot /var/www/html
    
    # SSL 证书
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-domain.crt
    SSLCertificateKeyFile /etc/ssl/private/your-domain.key
    
    # 安全配置
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCompression off
    SSLSessionTickets off
    
    # 头部安全
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # 反向代理设置
    ProxyPreserveHost On
    ProxyRequests Off
    
    # WebSocket 支持
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L]
    
    # 一般 HTTP 请求
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

章节来源

性能优化建议

连接池配置

# 连接池优化
upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://backend;
        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;
        
        # 连接保持
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }
}

超时设置优化

# 超时配置优化
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

# WebSocket 超时
location / {
    proxy_read_timeout 86400;
    proxy_send_timeout 86400;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

错误处理配置

# 错误处理
error_page 502 503 504 /50x.html;
location = /50x.html {
    internal;
}

# 健康检查
location /health {
    access_log off;
    return 200 "healthy\n";
    add_header Content-Type text/plain;
}

# 缓存策略
location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ {
    add_header Cache-Control "public, immutable, stale-while-revalidate=31536000";
    expires 1y;
}

章节来源

安全配置

CORS 设置

项目默认启用了 CORS 支持,但建议在生产环境中进行更严格的配置:

# CORS 配置
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With, X-Real-IP" always;
add_header Access-Control-Max-Age 86400 always;

# 预检请求处理
location OPTIONS {
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With, X-Real-IP";
    add_header Access-Control-Max-Age 86400;
    return 204;
}

HSTS 配置

# HSTS 配置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;

安全头部

# 安全头部配置
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Feature-Policy "geolocation=(), microphone=()"
Header always set Expect-CT "enforce, max-age=86400"

SSL/TLS 优化

# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_dhparam /path/to/dhparam.pem;
ssl_ecdh_curve prime256v1;

章节来源

故障排除指南

WebSocket 连接问题

常见 WebSocket 连接问题及解决方案:

  1. 升级失败

    • 检查 UpgradeConnection 头部是否正确传递
    • 确认代理服务器版本支持 WebSocket 升级
  2. 连接超时

    • 增加 proxy_read_timeoutproxy_send_timeout
    • 检查防火墙设置允许 WebSocket 端口
  3. 心跳检测失败

    • 确认客户端和服务端的心跳配置一致
    • 检查网络中间设备是否丢弃长连接

性能问题诊断

# 启用详细日志
error_log /var/log/nginx/error.log debug;
access_log /var/log/nginx/access.log combined;

# 监控连接状态
location /status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

负载均衡问题

# 健康检查配置
upstream backend {
    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 backup;
}

# 会话粘性(可选)
ip_hash;

章节来源

总结

本指南提供了针对视频流服务器项目的完整反向代理配置方案。关键要点包括:

  1. WebSocket 升级:必须正确配置 Upgrade 头部和 Connection 字段
  2. 长连接保持:合理设置超时参数和心跳检测
  3. 负载均衡:支持多实例部署和故障转移
  4. 性能优化:连接池、缓存策略和压缩配置
  5. 安全配置CORS、HSTS 和安全头部设置

部署时建议:

  • 先在测试环境验证配置
  • 逐步增加流量监控
  • 定期检查日志和性能指标
  • 制定回滚和应急响应计划

通过正确的反向代理配置,可以确保 WebRTC 应用的稳定运行和良好用户体验。