
本文揭示 signalr 在 windows 10 iis 环境下因系统级连接数限制(默认仅 10 并发)导致 axios 请求长期处于 pending 状态的根本原因,并提供可落地的生产环境部署优化方案。
本文揭示 signalr 在 windows 10 iis 环境下因系统级连接数限制(默认仅 10 并发)导致 axios 请求长期处于 pending 状态的根本原因,并提供可落地的生产环境部署优化方案。
在使用 SignalR 实现拍卖场景实时竞价(如竞标价格推送)时,若前端频繁创建 HubConnection 实例却未正确复用或销毁,极易触发后端连接资源瓶颈——尤其当后端部署于开发/测试环境(如 Windows 10 + IIS)时,该问题尤为突出。
根本原因分析
Windows 10 自带的 IIS Express 或桌面版 IIS 默认启用 并发连接数限制(Concurrent Connection Limit),通常为 10 个(部分版本甚至低至 3)。而 SignalR 的 WebSocket(或长轮询)连接属于持久化 HTTP 连接,每个客户端实例会独占一个连接槽位。一旦达到上限:
- 新用户无法建立 SignalR 连接;
- 同一页面内后续发起的 Axios 请求(即使与 SignalR 无关)将被浏览器强制排队,处于
pending状态,直至有空闲连接释放; - 页面刷新会重复触发
hubConnectionBuilder.start(),但旧连接未显式关闭,加剧连接泄漏。
⚠️ 注意:你提供的代码中存在两个关键隐患:
-
连接未复用:每次调用
getUpcomingLots()都新建HubConnectionBuilder,导致连接实例不断累积; -
缺少连接生命周期管理:未调用
hubConnectionBuilder.stop(),也未处理组件卸载(如 ReactuseEffect cleanup),造成内存与连接泄漏。
✅ 正确实践应如下:
// 使用 React Hook 管理单一、持久化的 SignalR 连接
import { useEffect, useRef, useState } from 'react';
import * as signalR from '@microsoft/signalr';
const useSignalRAuction = (auctionId: string, customerId: string) => {
const [upcomingLots, setUpcomingLots] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const hubConnectionRef = useRef<signalR.HubConnection | null>(null);
useEffect(() => {
const connect = async () => {
if (hubConnectionRef.current?.state === signalR.HubConnectionState.Connected) return;
const connection = new signalR.HubConnectionBuilder()
.withUrl(`${HUBURL}?auctionId=${auctionId}&customerId=${customerId}`, {
// ✅ 移除非法 header(Cross-Origin-Resource-Policy 不是请求头,且 * 值无效)
// 正确做法:由后端配置 CORS,前端无需手动设
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets,
})
.withAutomaticReconnect()
.build();
hubConnectionRef.current = connection;
try {
await connection.start();
console.log('SignalR connected');
connection.on('SendUpcomingLots', (data) => {
setUpcomingLots(data);
});
// ✅ 启动成功后,再发起 Axios 初始化数据请求(避免竞态)
await axios.get(`${APIURL}?auctionId=${auctionId}&customerId=${customerId}`);
setLoading(false);
} catch (err) {
console.error('SignalR connection failed:', err);
setLoading(false);
}
};
connect();
// ✅ 清理:组件卸载时断开连接
return () => {
if (hubConnectionRef.current?.state === signalR.HubConnectionState.Connected) {
hubConnectionRef.current.stop().catch(console.error);
}
};
}, [auctionId, customerId]);
return { upcomingLots, loading };
};最关键的生产环境修复措施
如答案所述,部署环境升级是治本之策:
- ❌ 开发机 Windows 10 + IIS → 受限于操作系统许可,硬性限制并发连接数(10);
- ✅ 生产环境必须部署于 Windows Server / Linux VM + Kestrel/Nginx 或 Azure App Service / AWS EC2 等无连接数限制的服务器;
- SignalR 后端需配置
MaximumParallelConnectionsPerClient = 1(默认)并启用WebSockets,同时确保反向代理(如 Nginx)正确透传 Upgrade 头。
额外建议
- 前端启用连接健康检查:监听
onclose事件并自动重连; - 后端启用 SignalR 日志(
LogLevel.Debug),监控连接数与错误码(如409 Conflict表示连接超限); - 对高频竞价场景,考虑引入 Redis Pub/Sub 作为 SignalR 的扩展层,解耦高并发写入压力。
通过环境升级 + 连接复用 + 生命周期管控三管齐下,即可彻底解决“Axios pending”困局,保障万级用户实时竞价的稳定性与响应性。


















