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
相关产品推荐
相关产品推荐

