Docker Compose部署ASP.NET Core API:Nginx下SignalR无法连接求助
问题描述
我正在学习用Docker Compose部署应用,现有一个带SignalR端点的ASP.NET Core Web API,直接在主机运行时一切正常,但通过Nginx反向代理后无法连接SignalR,不过API其他功能正常,求解决建议。
Docker Compose 配置
version: "3.7" services: proxy: build: ./nginx ports: - 80:80 depends_on: - app1 - app2 app1: build: ./API ports: - 8080:80 working_dir: /app environment: DATABASE_URL: postgres://postgres:postgrespw@127.0.0.1:5432/datingapp REDIS_HOST: redis REDIS_PORT: 6379 depends_on: - postgres - redis app2: build: ./API ports: - 8081:80 working_dir: /app environment: DATABASE_URL: postgres://postgres:postgrespw@127.0.0.1:5432/datingapp REDIS_HOST: redis REDIS_PORT: 6379 depends_on: - postgres - redis redis: image: redis:6.2.6-alpine ports: - 6379:6379 postgres: image: postgres:latest environment: POSTGRES_PASSWORD: postgrespw
Nginx 配置
worker_processes 1; events { worker_connections 1024; } http { upstream backend { server api1:80; server api2:80; } server { listen 80; location / { proxy_pass http://backend; proxy_set_header Host $host; } } }
错误信息
- WebSocket错误:WebSocket连接到
ws://localhost/chatHub失败,握手时收到意外响应码400 - Nginx内部日志:提示
upstream "backend" 中没有可用的服务器 - 后端服务器日志:完成客户端握手失败,读取握手响应时出错,服务器返回状态码400,预期为101
解决建议
1. 修正Nginx上游服务名称
Docker Compose中后端服务名称是app1和app2,但Nginx上游配置里写的是api1:80和api2:80,这会导致Nginx无法找到后端服务,修正后的上游配置应为:
upstream backend { server app1:80; server app2:80; }
2. 补充Nginx WebSocket代理配置
SignalR依赖WebSocket传输,当前Nginx配置未启用相关支持,需要在location /块中添加以下配置:
location / { proxy_pass http://backend; proxy_set_header Host $host; # WebSocket握手必需的头信息 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_cache_bypass $http_upgrade; # 传递客户端真实IP和请求协议 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; # 适配SignalR长连接的超时设置 proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; }
3. 配置ASP.NET Core识别反向代理
在项目的Program.cs中添加正向代理支持,确保应用能正确识别客户端的真实请求信息:
builder.Services.AddSignalR(); // 启用正向代理头解析 app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); // 映射你的SignalR Hub路由,替换为实际路径 app.MapHub<ChatHub>("/chatHub");
4. 验证Redis连接(可选)
如果使用Redis作为SignalR分布式缓存,可进入后端容器测试Redis连接是否正常:
docker exec -it <app1容器ID> redis-cli -h redis ping
返回PONG则表示连接正常。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

