# SignalR 生产环境配置指南 **文档版本**: 1.0 **创建日期**: 2026-01-14 **适用环境**: 生产环境 --- ## 一、Nginx 配置 ### 1.1 WebSocket 支持配置 SignalR 使用 WebSocket 协议,需要在 Nginx 中配置 WebSocket 支持。 **配置文件**: `/etc/nginx/sites-available/xiangyi` ```nginx # 上游服务器配置 upstream xiangyi_app_api { server localhost:5000; keepalive 32; } server { listen 80; listen 443 ssl http2; server_name app.zpc-xy.com; # SSL 证书配置 ssl_certificate /etc/nginx/ssl/app.zpc-xy.com.crt; ssl_certificate_key /etc/nginx/ssl/app.zpc-xy.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 普通 HTTP API 请求 location /xyqj/api/ { proxy_pass http://xiangyi_app_api/api/app/; 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; # 超时配置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # SignalR WebSocket 配置(关键配置) location /hubs/chat { proxy_pass http://xiangyi_app_api/hubs/chat; proxy_http_version 1.1; # WebSocket 必需配置 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; # 禁用缓存 proxy_cache_bypass $http_upgrade; proxy_buffering off; # 超时配置(WebSocket 需要长连接) proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; # 心跳配置 proxy_socket_keepalive on; } # 静态文件 location /uploads/ { alias /var/www/xiangyi/uploads/; expires 30d; add_header Cache-Control "public, immutable"; } } ``` ### 1.2 配置说明 **关键配置项**: 1. **proxy_http_version 1.1** - WebSocket 需要 HTTP/1.1 协议 2. **Upgrade 和 Connection 头** - 必须配置,用于协议升级 3. **超时时间** - `proxy_read_timeout 7d` - 设置为 7 天,支持长连接 - 可根据实际需求调整 4. **proxy_buffering off** - 禁用缓冲,确保消息实时传输 5. **proxy_socket_keepalive on** - 启用 TCP keepalive,保持连接活跃 --- ## 二、ASP.NET Core 配置 ### 2.1 Program.cs 配置 ```csharp // SignalR 配置 builder.Services.AddSignalR(options => { // 启用详细错误(生产环境建议关闭) options.EnableDetailedErrors = false; // 客户端超时时间(30秒) options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); // 心跳间隔(15秒) options.KeepAliveInterval = TimeSpan.FromSeconds(15); // 最大消息大小(32KB) options.MaximumReceiveMessageSize = 32 * 1024; // 流式传输缓冲区大小 options.StreamBufferCapacity = 10; }); // 如果使用 Redis 作为 SignalR 后端(多服务器部署) builder.Services.AddSignalR() .AddStackExchangeRedis(builder.Configuration.GetConnectionString("Redis"), options => { options.Configuration.ChannelPrefix = "SignalR"; }); ``` ### 2.2 appsettings.Production.json ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore.SignalR": "Warning", "Microsoft.AspNetCore.Http.Connections": "Warning" } }, "ConnectionStrings": { "Redis": "localhost:6379,password=your_redis_password" }, "SignalR": { "EnableDetailedErrors": false, "ClientTimeoutInterval": 30, "KeepAliveInterval": 15, "MaximumReceiveMessageSize": 32768 } } ``` --- ## 三、Redis 配置(多服务器部署) ### 3.1 为什么需要 Redis? 当部署多个应用服务器实例时,SignalR 需要使用 Redis 作为后端存储,以实现: - 跨服务器消息推送 - 连接状态共享 - 负载均衡支持 ### 3.2 安装 Redis NuGet 包 ```bash cd server/src/XiangYi.AppApi dotnet add package Microsoft.AspNetCore.SignalR.StackExchangeRedis ``` ### 3.3 配置 Redis ```csharp // Program.cs builder.Services.AddSignalR() .AddStackExchangeRedis(options => { options.Configuration.EndPoints.Add("localhost", 6379); options.Configuration.Password = "your_redis_password"; options.Configuration.ChannelPrefix = "SignalR"; options.Configuration.AbortOnConnectFail = false; }); ``` ### 3.4 Redis 配置文件 ```conf # /etc/redis/redis.conf # 绑定地址 bind 127.0.0.1 # 端口 port 6379 # 密码 requirepass your_redis_password # 最大内存 maxmemory 256mb # 内存淘汰策略 maxmemory-policy allkeys-lru # 持久化 save 900 1 save 300 10 save 60 10000 ``` --- ## 四、防火墙配置 ### 4.1 开放端口 ```bash # 开放 HTTP/HTTPS 端口 sudo ufw allow 80/tcp sudo ufw allow 443/tcp # 如果 Redis 需要外部访问 sudo ufw allow 6379/tcp ``` ### 4.2 安全组规则(云服务器) **入站规则**: - HTTP: 80 - HTTPS: 443 - Redis: 6379(仅内网) --- ## 五、SSL/TLS 配置 ### 5.1 获取 SSL 证书 **使用 Let's Encrypt**: ```bash sudo apt-get install certbot python3-certbot-nginx sudo certbot --nginx -d app.zpc-xy.com ``` ### 5.2 自动续期 ```bash # 添加定时任务 sudo crontab -e # 每天凌晨 2 点检查并续期 0 2 * * * certbot renew --quiet ``` ### 5.3 强制 HTTPS ```nginx server { listen 80; server_name app.zpc-xy.com; return 301 https://$server_name$request_uri; } ``` --- ## 六、监控与日志 ### 6.1 SignalR 连接监控 **创建监控端点**: ```csharp // Controllers/MonitorController.cs [ApiController] [Route("api/monitor")] public class MonitorController : ControllerBase { [HttpGet("signalr/stats")] public IActionResult GetSignalRStats() { return Ok(new { OnlineUsers = ChatHub.GetOnlineUserCount(), Timestamp = DateTime.Now }); } } ``` ### 6.2 日志配置 **Serilog 配置**: ```json { "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "Microsoft.AspNetCore.SignalR": "Warning", "Microsoft.AspNetCore.Http.Connections": "Warning" } }, "WriteTo": [ { "Name": "File", "Args": { "path": "/var/log/xiangyi/signalr-.log", "rollingInterval": "Day", "retainedFileCountLimit": 30 } } ] } } ``` ### 6.3 性能监控 **关键指标**: - 在线用户数 - 消息推送成功率 - 平均消息延迟 - 连接建立/断开频率 - 内存使用情况 **监控工具**: - Application Insights - Prometheus + Grafana - ELK Stack --- ## 七、性能优化 ### 7.1 连接池配置 ```csharp builder.Services.AddSignalR(options => { // 限制并发连接数 options.MaximumParallelInvocationsPerClient = 1; // 启用消息压缩 options.EnableDetailedErrors = false; }); ``` ### 7.2 消息压缩 ```csharp builder.Services.AddSignalR() .AddMessagePackProtocol(); // 使用 MessagePack 协议(更高效) ``` ### 7.3 数据库优化 ```sql -- 为聊天表添加索引 CREATE INDEX IX_ChatMessage_SessionId_CreateTime ON Chat_Message(SessionId, CreateTime DESC); CREATE INDEX IX_ChatMessage_ReceiverId_IsRead ON Chat_Message(ReceiverId, IsRead); CREATE INDEX IX_ChatSession_User1Id_User2Id ON Chat_Session(User1Id, User2Id); ``` --- ## 八、故障排查 ### 8.1 连接失败 **检查清单**: 1. Nginx 配置是否正确 2. WebSocket 是否被防火墙阻止 3. SSL 证书是否有效 4. 后端服务是否运行 **诊断命令**: ```bash # 检查 Nginx 配置 sudo nginx -t # 查看 Nginx 日志 sudo tail -f /var/log/nginx/error.log # 检查端口监听 sudo netstat -tlnp | grep 5000 # 测试 WebSocket 连接 wscat -c wss://app.zpc-xy.com/hubs/chat ``` ### 8.2 消息丢失 **可能原因**: - Redis 连接断开 - 消息队列满 - 客户端未正确监听事件 **解决方案**: 1. 检查 Redis 连接状态 2. 增加消息队列大小 3. 实现消息持久化和重试机制 ### 8.3 性能问题 **优化建议**: 1. 启用 Redis 集群 2. 使用 MessagePack 协议 3. 实现消息批量推送 4. 优化数据库查询 5. 使用 CDN 加速静态资源 --- ## 九、安全配置 ### 9.1 认证授权 ```csharp // ChatHub.cs [Authorize] // 必须登录才能连接 public class ChatHub : Hub { // 验证用户权限 public override async Task OnConnectedAsync() { var userId = GetCurrentUserId(); if (userId <= 0) { Context.Abort(); return; } await base.OnConnectedAsync(); } } ``` ### 9.2 速率限制 ```csharp // 限制消息发送频率 public class RateLimitAttribute : ActionFilterAttribute { private static readonly ConcurrentDictionary LastMessageTime = new(); public override void OnActionExecuting(ActionExecutingContext context) { var userId = GetUserId(context); var now = DateTime.Now; if (LastMessageTime.TryGetValue(userId, out var lastTime)) { if ((now - lastTime).TotalSeconds < 1) // 1秒内只能发送1条 { context.Result = new StatusCodeResult(429); // Too Many Requests return; } } LastMessageTime[userId] = now; base.OnActionExecuting(context); } } ``` ### 9.3 消息过滤 ```csharp // 敏感词过滤 public async Task FilterSensitiveWords(string content) { // 实现敏感词过滤逻辑 return content; } ``` --- ## 十、部署检查清单 ### 10.1 部署前检查 - [ ] Nginx 配置已更新 - [ ] SSL 证书已配置 - [ ] Redis 已安装并配置 - [ ] 防火墙规则已配置 - [ ] 日志目录已创建 - [ ] 监控已配置 ### 10.2 部署后验证 - [ ] WebSocket 连接成功 - [ ] 消息实时推送正常 - [ ] 断线重连正常 - [ ] 多设备同时在线正常 - [ ] 性能指标正常 - [ ] 日志记录正常 ### 10.3 压力测试 ```bash # 使用 Artillery 进行压力测试 npm install -g artillery # 创建测试脚本 signalr-test.yml artillery run signalr-test.yml ``` **测试脚本示例**: ```yaml config: target: "wss://app.zpc-xy.com" phases: - duration: 60 arrivalRate: 10 engines: ws: timeout: 30000 scenarios: - name: "SignalR Connection Test" engine: ws flow: - connect: url: "/hubs/chat?access_token={{token}}" - think: 5 - send: '{"type":1,"target":"SendMessage","arguments":["Hello"]}' - think: 10 ``` --- ## 十一、回滚方案 ### 11.1 快速回滚 如果部署后出现问题,可以快速回滚: ```bash # 回滚到上一个版本 cd /var/www/xiangyi/app-api git checkout previous-version dotnet publish -c Release -o /var/www/xiangyi/app-api/publish sudo systemctl restart xiangyi-app-api ``` ### 11.2 降级方案 如果 SignalR 出现问题,可以临时禁用实时推送: ```csharp // Program.cs if (!builder.Configuration.GetValue("SignalR:Enabled")) { // 不注册 SignalR } else { builder.Services.AddSignalR(); app.MapHub("/hubs/chat"); } ``` --- ## 十二、总结 SignalR 生产环境配置要点: 1. **Nginx 配置** - 正确配置 WebSocket 支持 2. **SSL/TLS** - 使用 wss:// 协议 3. **Redis** - 多服务器部署必需 4. **监控** - 实时监控连接状态和性能 5. **安全** - 认证、授权、速率限制 6. **优化** - 连接池、消息压缩、数据库索引 完成以上配置后,SignalR 即可在生产环境稳定运行。