Azure应用WebSocket仅在先浏览器访问服务端时可正常连接问题
Azure WebSocket握手返回302错误排查与解决
排查优先级从高到低
302是标准HTTP重定向响应,你遇到的「手动用浏览器访问一次服务地址后WebSocket就正常」的现象,本质是这次手动请求提前改变了某层组件的状态,后续请求不再触发重定向,按以下顺序查就行:
- 先查Azure前置接入层的重定向规则
首先看你用的Azure服务前面的托管层有没有配跳转:包括App Service/Function自带的Easy Auth(身份验证模块)、Front Door/Application Gateway的HTTP转HTTPS规则、自定义域名跳转、默认站点页跳转配置。
这类问题的逻辑很简单:第一次发WebSocket握手请求的时候,接入层没识别到请求里的WebSocket Upgrade头,直接把它当成普通的未鉴权/非HTTPS请求,回302跳去登录页或者HTTPS地址;你用浏览器手动访问的时候,浏览器会自动跟着302跳完整个流程——完成鉴权、协商好HTTPS、拿到会话cookie,之后再发WebSocket请求,带了对应cookie、走对了协议,自然就不会被拦。 - 再查服务冷启动问题
如果你把服务部署在消费计划Azure Function、免费/共享层App Service这类有冷启动机制的资源上,第一次请求打过来的时候,实例才开始拉代码启动,宿主还没加载完你的应用逻辑,前置托管层会先回302跳转到临时预热页或者默认欢迎页;手动访问一次刚好把冷启动流程跑完,实例加载完WebSocket处理逻辑之后,后续握手请求就能正常响应。 - 查服务端中间件的注册顺序
翻下你服务端的代码,看中间件注册顺序对不对:如果WebSocket升级处理的中间件,注册在了HTTPS跳转、登录鉴权、默认路由重定向这些会返回302的中间件后面,那请求进来先走到重定向逻辑,直接就回302了,根本到不了WebSocket处理的代码。 - 最后查客户端请求配置
看下客户端连WebSocket的地址是不是用了ws://而不是wss://,有没有漏带Connection: Upgrade、Upgrade: websocket这两个标准握手头。WebSocket客户端默认不会跟随302跳转,只要服务端回302就直接报握手失败;但普通浏览器访问HTTP地址的时候会自动跳HTTPS,甚至会写HSTS缓存让之后的请求默认走HTTPS,刚好和你遇到的现象匹配。
解决方案
- 先抓一次失败握手的响应包,看302响应头里的
Location字段值:如果跳的是Azure AD或者登录页,就把WebSocket请求的路径加到鉴权白名单里,或者提前给客户端配好访问凭证;如果跳的是https开头的地址,直接把客户端的连接地址改成wss://开头的全路径,不要用明文ws协议碰跳转。 - 给服务开Always On(始终在线)配置,配上健康检查预热路径,避免实例空闲被回收、冷启动返回非预期响应。
- 调整服务端中间件的注册顺序,把WebSocket升级处理逻辑放到所有可能返回重定向的中间件最前面,保证带Upgrade头的请求优先被WebSocket模块处理。
- 如果你开了App Service的ARR实例亲和性,确认客户端发后续请求的时候能正确带上
ARRAffinitycookie,避免被路由层重定向到其他未预热的实例。
内容的提问来源于stack exchange,提问作者Anatoliy Kiguradze
相关产品推荐
相关产品推荐

