You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure日历技能Bot切换时WebSocket超时异常排查与修复咨询

Troubleshooting WebSocket Timeout When Handoff to Calendar Skill Bot (AAD Token Suspected)

嘿,看起来你在把对话切换到Calendar Skill Bot的时候碰到了WebSocket超时的问题,而且你已经怀疑这和AAD令牌有关——这确实是跨Bot技能调用里非常常见的排查方向。下面我来一步步帮你确认问题根源,以及对应的修复思路:

一、先确认AAD令牌是不是问题根源

技能Bot之间的调用完全依赖AAD令牌做身份验证,令牌失效、配置错误都会直接导致连接失败(表现为超时,因为服务端会静默拒绝未授权请求,客户端一直等不到响应)。咱们可以从这几个点验证:

  • 检查令牌的核心字段有效性
    在你的GetTokenCallback回调函数里加日志,输出令牌的关键信息(别泄露敏感内容,比如只打exp过期时间、aud受众、iss颁发者这些字段)。然后用本地的JWT解析工具(比如jwt.io,别用在线工具避免泄露)验证:

    • 令牌有没有过期:exp对应的时间必须在当前时间之后
    • 受众aud是否匹配Calendar Skill Bot的AAD应用ID:如果受众不对,技能Bot会直接拒绝连接
    • 颁发者iss是否是你当前使用的AAD租户(格式比如https://login.microsoftonline.com/{你的租户ID}/v2.0)
    • 是否包含正确的权限范围:必须有https://api.botframework.com/.default这类Bot技能调用所需的范围
  • 手动模拟令牌调用测试
    用Postman手动调用AAD的token端点获取有效令牌:

    POST https://login.microsoftonline.com/{你的租户ID}/oauth2/v2.0/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id=你的主BotAAD应用ID&client_secret=你的主Bot应用密钥&grant_type=client_credentials&scope=https://api.botframework.com/.default
    

    拿到令牌后,临时修改代码里的令牌回调,直接返回这个手动获取的令牌,再尝试切换到技能Bot。如果连接成功,说明问题肯定出在你的令牌获取流程上;如果还是超时,那就要排查网络或者其他配置问题了。

  • 确认令牌回调是否正常工作
    在GetTokenCallback里加日志,看看当技能调用需要令牌时,这个回调是不是被正确触发了,并且返回了有效的令牌。如果回调没触发,或者返回null/空值,那WebSocket连接肯定会因为身份验证失败而超时。

二、如果令牌没问题,排查其他超时原因

要是确认令牌是有效的,那咱们就得看看其他可能导致WebSocket连接超时的因素:

  • 检查网络连通性

    • 确认主Bot所在的环境(比如Azure App Service)能访问Calendar Skill Bot的WebSocket端点:可以用PowerShell的Test-NetConnection {技能Bot域名} -Port 443测试端口是否能连通
    • 排查防火墙/NSG(网络安全组)/代理:看看是不是有规则阻止了WebSocket连接,比如Azure App Service的出站规则有没有允许访问技能Bot的域名,代理服务器是否支持WebSocket协议
  • 验证技能Bot端点配置

    • 确认_skillManifest.Endpoint是正确的WebSocket格式:必须是wss://{技能Bot域名}/api/messages(注意是wss,WebSocket的安全协议,不是https)
    • 检查技能Bot本身是否正常运行:直接访问https://{技能Bot域名}/api/messages,应该能收到BotFramework适配器的默认响应(比如"Hello, I'm a bot!"),如果技能Bot宕机,也会导致连接超时
  • 调整WebSocket客户端的超时配置
    你可以给WebSocketClient加自定义配置,调整心跳和超时参数,避免因为默认设置太宽松导致超时:

    var wsOptions = new ClientWebSocketOptions();
    wsOptions.KeepAliveInterval = TimeSpan.FromSeconds(30); // 缩短心跳间隔,维持连接
    wsOptions.ConnectTimeout = TimeSpan.FromSeconds(10); // 缩短连接超时,快速失败便于排查
    
    _streamingTransportClient = new WebSocketClient(
        EnsureWebSocketUrl(_skillManifest.Endpoint.ToString()),
        new SkillCallingRequestHandler(
            turnContext, _botTelemetryClient, GetTokenCallback(turnContext, tokenRequestHandler), GetHandoffActivityCallback()),
        headers,
        wsOptions); // 传入自定义配置
    await _streamingTransportClient.ConnectAsync();
    

三、对应修复建议

根据上面的排查结果,咱们可以针对性修复:

  • 如果是令牌问题

    • 令牌过期:用Microsoft.Identity.Client库的AcquireTokenForClient方法,它会自动处理令牌缓存和过期刷新,不用自己手动管理
    • 受众/权限不对:去Azure AD里调整主Bot应用的权限,确保它拥有访问Calendar Skill Bot的权限,并且令牌请求的scope参数正确
    • 回调未触发:检查SkillDialog的配置,确保tokenRequestHandler参数正确传递,回调函数的逻辑没有错误
  • 如果是网络/端点问题

    • 调整防火墙/NSG规则,允许主Bot到技能Bot的出站WebSocket连接
    • 修复技能Bot的端点配置,确保wss端点正常运行
    • 代理问题:给WebSocket客户端配置代理,或者在Azure App Service的应用设置里配置代理信息
  • 代码层面优化
    给连接逻辑加异常捕获和重试,避免临时网络波动导致的超时:

    try
    {
        await _streamingTransportClient.ConnectAsync();
    }
    catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
    {
        // 遇到超时重试一次
        await Task.Delay(1000);
        await _streamingTransportClient.ConnectAsync();
    }
    catch (Exception ex)
    {
        // 记录详细异常日志,便于后续排查
        _botTelemetryClient.TrackException(ex);
        throw;
    }
    

内容的提问来源于stack exchange,提问作者Rayban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:44:33