基于DirectLine API、.Net及JS创建多Microsoft Bot实例并解决Live Assist单会话限制
问题1:多Bot实例创建与可用性轮询实现
我之前帮不少团队搭建过多Bot实例的架构,结合DirectLine API、.NET和JavaScript的实现,给你梳理下具体步骤:
一、创建多个Bot实例
不管用哪种语言,核心是给每个Bot实例配置独立的资源(比如Azure Bot Service的独立实例,每个都有专属的DirectLine密钥和端点)。
.NET 端实现
首先把多个Bot的配置统一管理,别硬编码在代码里,建议放在appsettings.json中:
"BotInstances": [ { "Id": "bot-support-team", "DirectLineSecret": "YOUR_SECRET_1", "Endpoint": "https://directline.botframework.com/v3/directline" }, { "Id": "bot-sales-team", "DirectLineSecret": "YOUR_SECRET_2", "Endpoint": "https://directline.botframework.com/v3/directline" } ]
然后写个轻量的工厂类,用来根据ID快速获取对应的DirectLine客户端,代码更整洁易维护:
public class BotClientFactory { private readonly IConfiguration _config; public BotClientFactory(IConfiguration config) => _config = config; public DirectLineClient GetClient(string botInstanceId) { var botConfig = _config.GetSection("BotInstances").Get<List<BotConfig>>() .FirstOrDefault(b => b.Id == botInstanceId); if (botConfig == null) throw new ArgumentException($"找不到ID为{botInstanceId}的Bot实例"); return new DirectLineClient(new Uri(botConfig.Endpoint), new DirectLineClientCredentials(botConfig.DirectLineSecret)); } } public class BotConfig { public string Id { get; set; } public string DirectLineSecret { get; set; } public string Endpoint { get; set; } }
JavaScript 端实现
同样先把多Bot的配置存在对象数组里:
const botInstances = [ { id: 'bot-support-team', directLineSecret: 'YOUR_SECRET_1', endpoint: 'https://directline.botframework.com/v3/directline' }, { id: 'bot-sales-team', directLineSecret: 'YOUR_SECRET_2', endpoint: 'https://directline.botframework.com/v3/directline' } ];
然后写个函数动态创建DirectLine客户端:
function getDirectLineClient(botInstanceId) { const bot = botInstances.find(b => b.id === botInstanceId); if (!bot) throw new Error(`找不到ID为${botInstanceId}的Bot实例`); return new DirectLine({ secret: bot.directLineSecret, domain: bot.endpoint }); }
二、可用性轮询实现
核心是定期检测每个Bot的健康状态,把用户请求路由到可用的实例上。
1. 健康检测逻辑
推荐调用DirectLine的/tokens/generate接口来验证——这个接口轻量,能快速返回Bot的可用性:
.NET 端检测方法
public async Task<bool> IsBotAvailable(string botInstanceId) { var client = _botClientFactory.GetClient(botInstanceId); try { await client.Tokens.GenerateTokenForNewConversationAsync(); return true; } catch (Exception) { return false; } }
JavaScript 端检测方法
async function isBotAvailable(botInstanceId) { const bot = botInstances.find(b => b.id === botInstanceId); if (!bot) return false; try { const response = await fetch(`${bot.endpoint}/tokens/generate`, { method: 'POST', headers: { 'Authorization': `Bearer ${bot.directLineSecret}` } }); return response.ok; } catch (err) { return false; } }
2. 轮询与路由策略
- 定期轮询:用定时器维护可用实例列表——.NET可以用
IHostedService后台服务,JS用setInterval,比如每隔5分钟检测一次所有Bot的状态。 - 路由逻辑:用户发起聊天时,从可用列表里选一个实例(简单点用轮询法,或者根据负载情况调整),再用该实例的客户端创建会话。
举个.NET端的路由示例:
public async Task<string> GetAvailableBotInstanceId() { var botConfigs = _config.GetSection("BotInstances").Get<List<BotConfig>>(); var availableBots = new List<string>(); foreach (var bot in botConfigs) { if (await IsBotAvailable(bot.Id)) { availableBots.Add(bot.Id); } } if (!availableBots.Any()) throw new InvalidOperationException("当前没有可用的Bot实例"); // 简单轮询策略:取第一个可用实例,也可以维护索引递增实现轮询 return availableBots[0]; }
问题2:Live Assist仅支持单个并发会话的上线问题
本地正常但上线出问题,这种环境差异导致的bug我见得很多,大概率是会话隔离或者配置没跟上,给你列几个排查方向:
一、先查会话标识的唯一性
Live Assist靠唯一的会话ID区分不同用户的聊天,如果上线后所有用户复用同一个ID,肯定会挤掉之前的会话:
- 检查前端创建Live Assist会话时,是不是每次都生成新的UUID或用「用户ID+时间戳」当会话ID?别复用全局变量里的旧ID。
- Bot把用户路由到Live Assist时,有没有正确传递唯一的用户/会话上下文?比如调用Live Assist API时,
conversationId或userId参数是不是每个用户都不一样。
二、检查Live Assist的后台配置
- 并发限制:登录Live Assist管理后台看看,是不是误把全局并发会话数设成1了?很多测试环境默认有这个限制,上线前得改成生产需要的数值。
- Webhook状态:如果Bot和Live Assist用Webhook交互,确认生产环境的Webhook地址正确,且没被防火墙/反向代理拦截——Webhook不通的话,会话状态同步不了,会引发奇怪的并发问题。
- 会话超时:会不会超时设置太短,旧会话没被清理导致新会话创建失败?把超时调到30分钟以上试试,确保闲置会话能及时回收。
三、排查环境差异
- SDK版本:本地和生产用的DirectLine、Live Assist SDK版本是不是一致?旧版本SDK可能存在并发会话的bug,尽量升级到最新稳定版。
- 服务器资源:生产服务器的CPU、内存是不是不够?资源跑满的话,Live Assist的会话处理线程会被阻塞,自然没法处理多个会话,去监控平台看看资源使用率。
- 负载均衡配置:如果用了反向代理或负载均衡,有没有开启会话粘滞?没开的话,同一个会话可能被分到不同服务器实例,引发冲突。
内容的提问来源于stack exchange,提问作者bmo
相关产品推荐
相关产品推荐

