# 反向代理配置 **本文档引用的文件** - [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 场景特殊考虑](#webrtc-场景特殊考虑) 4. [Nginx 反向代理配置](#nginx-反向代理配置) 5. [Apache 反向代理配置](#apache-反向代理配置) 6. [性能优化建议](#性能优化建议) 7. [安全配置](#安全配置) 8. [故障排除指南](#故障排除指南) 9. [总结](#总结) ## 简介 本指南针对视频流服务器项目提供完整的反向代理配置方案。该项目是一个基于 WebRTC 和 WebSocket 的视频通话应用,支持 HTTP 轮询和 WebSocket 两种信令协议,以及公共模式和私有模式两种通信方式。 项目采用 Node.js + Express 构建,支持 HTTPS 和 WebSocket 升级,具备完整的 WebRTC 信令交换能力。反向代理配置对于部署此类实时通信应用至关重要,需要特别关注 WebSocket 升级、长连接保持、头部转发和压缩配置等方面。 ## 项目架构概览 ```mermaid 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 ``` **图表来源** - [src/server.ts:14-89](file://src/server.ts#L14-L89) - [src/index.ts:52-91](file://src/index.ts#L52-L91) - [src/websocket.ts:6-117](file://src/websocket.ts#L6-L117) ### 核心组件分析 项目包含以下关键组件: 1. **Express 服务器**:处理 HTTP 请求、静态文件服务和 API 路由 2. **WebSocket 服务器**:处理实时信令消息和 WebRTC 信令交换 3. **HTTP 轮询服务器**:提供 HTTP 轮询模式的信令服务 4. **会话管理系统**:管理用户会话和连接状态 5. **静态资源服务**:提供前端应用和媒体文件 **章节来源** - [src/server.ts:14-89](file://src/server.ts#L14-L89) - [src/index.ts:52-91](file://src/index.ts#L52-L91) - [src/websocket.ts:6-117](file://src/websocket.ts#L6-L117) ## WebRTC 场景特殊考虑 ### WebSocket 升级要求 WebRTC 应用对 WebSocket 升级有严格要求: ```mermaid 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 : 开始实时通信 ``` **图表来源** - [src/websocket.ts:15-117](file://src/websocket.ts#L15-L117) - [src/class/websockethandler.ts:27-115](file://src/class/websockethandler.ts#L27-L115) ### 长连接保持机制 项目实现了心跳检测机制来维持长连接: - **心跳间隔**:30秒发送一次 ping 消息 - **超时检测**:60秒无活动自动断开连接 - **活动跟踪**:记录最后活动时间戳 ### 通信模式支持 项目支持两种通信模式: 1. **公共模式**:所有客户端都可以直接通信 2. **私有模式**:1对多房间通信(1个host + 多个participants) **章节来源** - [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430) - [src/服务端接口与WebSocket消息类型.md:489-504](file://src/服务端接口与WebSocket消息类型.md#L489-L504) ## Nginx 反向代理配置 ### 基础配置模板 以下提供完整的 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"; } } ``` ### 负载均衡配置 ```nginx # 负载均衡配置 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; } } ``` ### 静态资源缓存策略 ```nginx # 静态资源缓存配置 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]\."; ``` **章节来源** - [src/server.ts:22-28](file://src/server.ts#L22-L28) - [src/server.ts:85-86](file://src/server.ts#L85-L86) - [package.json:9](file://package.json#L9) ## Apache 反向代理配置 ### 基础 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 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] 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/ ``` ### mod_proxy_wstunnel 模块启用 确保启用 WebSocket 支持: ```apache # 启用 WebSocket 隧道 LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so # WebSocket 升级配置 ProxyPass ws://127.0.0.1:8080/ ProxyPassReverse ws://127.0.0.1:8080/ ProxySet match=Upgrade ProxySet force-proxy-request-1.0 1 ``` ### 虚拟主机配置 ```apache # 主虚拟主机配置 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/ ``` **章节来源** - [src/server.ts:22](file://src/server.ts#L22) - [src/server.ts:25](file://src/server.ts#L25) ## 性能优化建议 ### 连接池配置 ```nginx # 连接池优化 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; } } ``` ### 超时设置优化 ```nginx # 超时配置优化 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"; } ``` ### 错误处理配置 ```nginx # 错误处理 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; } ``` **章节来源** - [src/websocket.ts:19](file://src/websocket.ts#L19) - [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430) ## 安全配置 ### CORS 设置 项目默认启用了 CORS 支持,但建议在生产环境中进行更严格的配置: ```nginx # 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 配置 ```nginx # 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; ``` ### 安全头部 ```apache # 安全头部配置 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 优化 ```nginx # 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; ``` **章节来源** - [src/server.ts:22](file://src/server.ts#L22) - [src/server.ts:25](file://src/server.ts#L25) ## 故障排除指南 ### WebSocket 连接问题 常见 WebSocket 连接问题及解决方案: 1. **升级失败** - 检查 `Upgrade` 和 `Connection` 头部是否正确传递 - 确认代理服务器版本支持 WebSocket 升级 2. **连接超时** - 增加 `proxy_read_timeout` 和 `proxy_send_timeout` - 检查防火墙设置允许 WebSocket 端口 3. **心跳检测失败** - 确认客户端和服务端的心跳配置一致 - 检查网络中间设备是否丢弃长连接 ### 性能问题诊断 ```nginx # 启用详细日志 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; } ``` ### 负载均衡问题 ```nginx # 健康检查配置 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; ``` **章节来源** - [src/websocket.ts:27-115](file://src/websocket.ts#L27-L115) - [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430) ## 总结 本指南提供了针对视频流服务器项目的完整反向代理配置方案。关键要点包括: 1. **WebSocket 升级**:必须正确配置 Upgrade 头部和 Connection 字段 2. **长连接保持**:合理设置超时参数和心跳检测 3. **负载均衡**:支持多实例部署和故障转移 4. **性能优化**:连接池、缓存策略和压缩配置 5. **安全配置**:CORS、HSTS 和安全头部设置 部署时建议: - 先在测试环境验证配置 - 逐步增加流量监控 - 定期检查日志和性能指标 - 制定回滚和应急响应计划 通过正确的反向代理配置,可以确保 WebRTC 应用的稳定运行和良好用户体验。