你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于: SDK v4
中间件只是一个类,位于适配器和机器人逻辑之间,在初始化期间添加到适配器的中间件集合中。 SDK 可让用户自行编写中间件或添加其他人创建的中间件。 进出机器人的每个活动都流经中间件。
适配器通过机器人中间件管道处理传入活动并将其定向到机器人的逻辑,然后再次返回。 当每个活动流入和流出机器人时,每个中间件都可以在机器人逻辑运行前后对其进行检查或执行操作。
在跳转到中间件之前,请务必 一般了解机器人 及其 处理活动的方式。
中间件用途
翻译改进:问题经常出现:“何时应将动作作为中间件实现,而不是使用正常的机器人逻辑?”中间件提供了额外的机会,在处理每次会话轮次的前后与用户的对话流交互。 中间件还允许根据需要存储和检索有关聊天的信息,并调用其他处理逻辑。 下面是一些常见方案,其中显示了中间件的有用位置。
检查或处理每项活动
有很多情况要求您的机器人在每个活动或某一类型的每个活动中执行某些任务。 例如,如果机器人未生成此轮次响应,则可能需要记录机器人接收的每个消息活动或提供回退响应。 中间件是处理此类进程的绝佳位置,因为它可以在机器人逻辑的其他部分执行之前和之后发挥作用。
修改或增强轮次上下文
机器人在活动中提供的信息之外拥有额外资料时,某些对话可能会更加富有成果。 在本例中,中间件可以查看到目前为止它拥有的聊天状态信息,查询外部数据源,并在将执行传递到机器人逻辑之前将其追加到 轮次上下文 对象。
SDK 定义可记录传入和传出活动的日志记录中间件,但也可以定义自己的中间件。
机器人中间件管道
对于每个活动,适配器按添加中间件的顺序调用中间件。 适配器传入当前回合的上下文对象和下一个委托对象,中间件调用委托,将控制权传递给管道中的下一个中间件。 中间件还有机会在完成方法之前,在下一个委托返回后执行操作。 可以将它视为每个中间件对象都有针对管道中跟踪它的中间件对象的第一次和最后一个机会。
例如:
- 第一个中间件对象的轮次处理程序在调用 下一步之前执行代码。
- 第二个中间件对象的轮次处理程序在调用 下一步之前执行代码。
- 机器人的轮次处理程序执行并返回。
- 第二个中间件对象的轮次处理程序在返回之前执行任何剩余的代码。
- 第二个中间件对象的轮次处理程序在调用 下一步之前执行代码。
- 第一个中间件对象的轮次处理程序在返回之前执行任何剩余的代码。
如果中间件不调用下一个委托,适配器将不会调用任何后续的中间件或机器人轮次处理程序,并且管道将被短路。
机器人中间件管道完成后,轮次将结束,轮次上下文将超出范围。
中间件或机器人可以生成响应并注册响应事件处理程序,但请记住,响应在单独的进程中进行处理。
中间件顺序
由于添加中间件的顺序决定了中间件处理活动的顺序,因此必须确定应添加中间件的顺序。
注释
这旨在为你提供一种适用于大多数机器人的常见模式,但请务必考虑每个中间件将如何与其他人交互,以满足你的情况。
负责每个机器人的最低级别任务的中间件应首先添加到中间件管道。 示例包括日志记录、异常处理和转换。 根据需求对这些消息进行排序,例如,是否希望先转换传入消息,然后再存储消息,或者消息存储应首先进行,这可能意味着不会转换存储的消息。
机器人特定的中间件应最后添加到中间件管道,你实现的中间件会在发送到机器人的每个消息上执行一些处理。 如果您的中间件使用了机器人上下文中设定的状态信息或其他信息,请在修改状态或上下文的中间件之后,再将其添加到中间件管道中。
短路
中间件和响应处理程序中的一个重要概念是中断处理。 如果执行要继续执行其后面的层,则需要中间件(或响应处理程序)通过调用 下一个 委托来传递执行。 如果在该中间件(或响应处理程序)中未调用下一个委托,那么整个关联的管道将中断,并且不会执行后续层。 这意味着将跳过所有机器人逻辑以及管道中任何中间件。 您的中间件与响应处理程序在某次调用中产生短路时之间的差异是细微的。
当中间件跳过处理一个轮次时,不会调用机器人轮次处理器,但在此之前管道中执行的所有中间件代码仍将正常完成运行。
对于事件处理程序,不调用 下一 步意味着取消事件,这与跳过逻辑的中间件大相径庭。 如果不处理事件的其余部分,适配器永远不会发送它。
小窍门
如果对响应事件进行短路,例如 SendActivities,请确保这是你打算的行为。 否则,可能会导致难以修复的错误。
响应事件处理程序
除了应用程序和中间件逻辑之外,还可以将响应处理程序(有时也称为事件处理程序或活动事件处理程序)添加到上下文对象。 在执行实际响应之前,当关联响应发生在当前上下文对象上时,将调用这些处理程序。 当你知道自己会想要在实际事件之前或之后,对当前响应的其余部分的每个此类活动执行某些操作时,这些处理程序非常有用。
警告
请注意不要从其各自的响应事件处理程序中调用活动响应方法,例如,从发送活动处理程序内部调用发送活动方法。 这样做可以生成无限循环。
请记住,每个新活动都会获得一个新的线程来进行执行。 创建处理活动的线程时,该活动的处理程序列表将复制到该新线程。 在此之后添加的任何处理程序将不会用于该具体活动事件。 在上下文对象上注册的处理程序的处理方式与适配器管理中间件管道的方式类似。 也就是说,处理程序按照添加的顺序被调用,调用下一个委托将控制权传递给下一个注册的事件处理程序。 如果处理程序不调用下一个委托,就不会调用任何后续事件处理程序,导致事件中断,适配器不会将响应发送到通道。
处理中间件中的状态
保存状态的常见方法是调用轮次处理程序末尾的保存更改方法。 下面是一个示意图,重点在于通话。
此方法的问题是,通过一些自定义中间件进行的状态更新在机器人回合处理程序返回后将不会被保存到持久存储中。 解决方案是通过在中间件堆栈的开头添加一个自动保存更改中间件的实例,或者至少在可能更新状态的任何中间件之前,从而将对保存更改方法的调用移到自定义中间件完成之后。 执行过程如下所示。
添加需要更新的状态管理对象到机器人状态集对象,并在创建自动保存更改中间件时使用该对象进行操作。