# 反向代理配置

<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 应用的稳定运行和良好用户体验。