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

632 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 反向代理配置
<cite>
**本文档引用的文件**
- [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)
</cite>
## 目录
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
<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 支持:
```apache
# 启用 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>
```
### 虚拟主机配置
```apache
# 主虚拟主机配置
<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>
```
**章节来源**
- [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 应用的稳定运行和良好用户体验。