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

Azure Echobot的Directline端点间歇性WebSocket超时问题咨询

问题背景

我们通过Azure模板创建了Web App Bot(Echobot),在线地址为http://18.194.88.194/echobot/,但约40%的概率会遇到WebSocket连接超时错误:

WebSocket连接到 'wss://directline.botframework.com/v3/directline/conversations/EH9EbbBIasz8o90sZSeAwT-9/stream?watermark=-&t=ew0KICAiYWxnIj...(snip) 失败:Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT

相关代码

客户端代码:botclient.js

(async function() {
  let {token, conversationId} = sessionStorage;
  const delay = 1800000; //const delay = 20000;
  const currentTime = new Date();
  const currentTimeUnix = currentTime.getTime();
  if ( sessionStorage['startTime'] && currentTimeUnix - sessionStorage['startTime'] > delay ) {
    sessionStorage.removeItem('token');
    token = sessionStorage['token'];
  }
  const payload = JSON.stringify({botname: 'echobot'});
  if (!token) {
    const res = await fetch(
      'https://ox38xh0fx5.execute-api.eu-central-1.amazonaws.com/dev/directline/token',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: payload,
      },
    );
    const {token: directLineToken} = await res.json();
    sessionStorage['token'] = directLineToken;
    token = directLineToken;
    console.log('token', token);
    const startTime = new Date();
    const startTimeUnix = startTime.getTime();
    sessionStorage['startTime'] = startTimeUnix;
  }
  const data = {
    // from: user,
    name: 'requestWelcomeDialog',
    type: 'event',
    value: {
      url: window.location.href,
    },
  };
  var botConnection = new window.WebChat.createDirectLine({token});
  window.WebChat.renderWebChat(
    {
      directLine: botConnection,
      userID: 'YOUR_USER_ID',
      username: 'Web Chat User',
      locale: 'en-US',
    },
    document.getElementById('webchat'),
  );
})().catch(err => console.log(err));

客户端代码:index.html

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
  <style>
    html, body { height: 100%; }
    body { margin: 0; }
    #webchat { height: 100%; width: 100%; }
  </style>
</head>
<body>
  <div id="webchat" role="main"></div>
  <script src="botclient.js">
  </script>
</body>
</html>

AWS Lambda令牌获取代码

import json
import boto3
from urllib.parse import urlencode
from urllib.request import Request, urlopen

BOT_SECRET = 'defaultSecret'
URL = 'https://directline.botframework.com/v3/directline/tokens/generate'
POST_FIELDS = {'foo': 'bar'}

def set_headers(req, secret):
  req.add_header('Content-Type', 'application/json')
  req.add_header('Authorization', f'Bearer {secret}')
  return req

def lambda_handler(event, context):
  print(event)
  s3 = boto3.client('s3')
  if event.get('botname', None) == 'echobot':
    response = s3.get_object(Bucket='directline', Key='echobotSecret')
  else:
    response = s3.get_object(Bucket='directline', Key=BOT_SECRET)
  secret = response['Body'].read().decode('utf-8').rstrip()
  request = Request(URL, urlencode(POST_FIELDS).encode())
  request = set_headers(request, secret)
  jsonresponse = urlopen(request).read()
  print(jsonresponse)
  return jsonresponse
排查与处理建议

结合你怀疑的本地网络问题,以及代码和服务架构,给你以下几个方向的建议:

本地网络配置排查

  • 验证网络限制:切换到不同网络(比如手机热点)测试,如果超时问题消失,说明本地企业网络/路由器存在WebSocket拦截或限流。此时需要联系网络管理员,将directline.botframework.com域名及对应的IP段加入白名单,确保wss协议(443端口)的流量不受限制。
  • 检查网络设备策略:查看路由器、防火墙是否开启了数据包过滤、QoS(服务质量)或流量整形策略,这些可能导致部分WebSocket握手包丢失。可以临时关闭这类策略测试,或者针对DirectLine服务配置优先转发规则。
  • 用工具测试连接稳定性:使用wscat命令行工具多次测试WebSocket连接,看是否有规律的超时:
    wscat -c "wss://directline.botframework.com/v3/directline/conversations/[你的会话ID]/stream?watermark=-&t=[你的有效令牌]"
    
    如果多次执行中出现超时,基本可以确认是网络层面的丢包问题。

客户端代码优化

  • 添加重连机制:Web Chat SDK自带重连能力,但可以手动配置增强的重试策略,提升连接成功率:
    var botConnection = new window.WebChat.createDirectLine({
      token,
      retryPolicy: {
        type: 'exponentialBackoff',
        maxRetries: 5,
        initialRetryInMs: 1000
      }
    });
    
  • 优化令牌过期判断:当前依赖本地计时的方式不够严谨,建议直接解析JWT令牌的exp字段来判断是否过期:
    function getTokenExpiration(token) {
      const payload = token.split('.')[1];
      const decoded = JSON.parse(atob(payload));
      return decoded.exp * 1000; // 转换为毫秒时间戳
    }
    
    // 替换原来的startTime判断逻辑
    if (token) {
      const expTime = getTokenExpiration(token);
      if (currentTimeUnix > expTime) {
        sessionStorage.removeItem('token');
        token = null;
      }
    }
    
  • 监听连接状态:添加连接状态监听,便于排查问题并触发手动重连:
    botConnection.connectionStatus$.subscribe(status => {
      console.log('当前连接状态:', status);
      // 状态对应值:0=连接中, 1=在线, 2=离线, 3=令牌过期, 4=连接失败
      if (status === 4) {
        console.error('WebSocket连接失败,尝试重连...');
        botConnection.reconnect();
      }
    });
    

服务端与DirectLine层面排查

  • 检查Azure Bot服务状态:登录Azure门户,查看Web App Bot的监控指标(CPU使用率、内存占用、连接数),确认是否存在服务频繁重启或资源不足的情况,这也可能导致WebSocket连接不稳定。
  • 验证令牌有效性:在本地直接调用DirectLine的令牌生成接口,对比Lambda返回的令牌是否一致,确保令牌没有权限问题或生成错误。
  • 查看DirectLine服务状态:检查Azure中DirectLine资源的监控数据,确认是否存在区域级别的服务波动,导致部分连接请求超时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 14:02:28