本文关注这种这样的情况:orchestration中的消息通过发送端口(无论是单向发送端口还是双向发送端口)发送消息,需要在orchestration获得发送消息是否正常的回应,如果回应正常,则流程正常执行,如果回应不正常,orchestration如何进行异常处理。
首先,orchestration发送端口主要有两个类别,一般发送端口和web发送端口。
一般发送端口就是通过在工具箱中拖拽Port形状到orchestration形成的发送端口。
Web发送端口是通过biztalk项目引用webservices形成的web端口类型,是biztalk用来消费外部web services的方法。
这两种发送端口对发送出去的消息的回应处理机制不一样,所以分别讨论。
一般发送端口需要Delivery Notification属性设置为 Transmitted后,orchestration才会要求物理发送端口返回ACK和NACK消息。
如果一般发送端口未将Delivery Notification属性设置为 Transmitted,orchestration的发送端口把消息发送到messagebox,并能路由到物理发送端口(也可能是其它可以订阅消息的服务),则认为消息已经成功发送。至于消息在物理发送端有没有被成功的发送出去不影响到orchestration的运行。这种情况下,不会因为物理发送端口的问题引起orchestration发送端口的异常,所以本文只讨论一般发送端口被设置为Transmitted的情况。
关于详细的ACK和NACK的原理和测试,请参看《深入biztalk中Delivery Notification和ACK、NACK机制》《biztalk中ACK、NACK详测示例》两篇文章。
orchestration发送端口把消息发送出去的同时,在发送端口处产生一个实例订阅,订阅发送端口返回来的ACK或NACK信息。
消息发送后,orchestration继续往下走。
如果是双向发送端口,orchestration流程运行到返回消息的接收形状停下来,等待消息的返回。收到返回消息后orchestration流程继续运行下去。
如果收到ACK消息,表示消息发送成功;如果收到NACK,orchestration的发送端口会抛出一个DeliveryFailureException异常。
根据发送形状是否在scope中,分两种情况:
一般的,设置了发送端口的Delivery Notification属性就是为了在orchestration获知消息发送出去后有没有被成功的处理,所以一般都会在发送形状外面加上一个scope,用于捕获消息发送后不成功产生的异常。
一个非atomic类型的scope形状,可以有多个Exception Handler(跟C#中的catch语句块相似,scope本身就相当于try语句块了),NACK消息将引发DeliveryFailureException异常,所以这种情况下Exception Handler的捕获异常类型设置为DeliveryFailureException类型。
消息发送出去后,orchestration继续往下走,直到遇到非atomic类型的scope的边界,orchestration暂停,等待发送端口订阅的ACK或NACK消息返回。
Figure 1. 一般发送端口,在scope中的发送形状
Orchestration在等待ACK或NACK消息期间服务状态处于运行状态,但是如果等待的时间比较长,超过了一定的时间,Orchestration服务实例会被冻结(dehydrate),整个Orchestration被序列化保存到数据库以节省资源。直到接收到ACK或NACK消息,Orchestration再被激活接收消息并处理。
Orchestration的发送端口接收到ACK消息,不做其他的处理,只是使暂停在scope边界处的Orchestration继续往下运行。
Orchestration的发送端口接收到NACK消息,会在发送端口出产生一个DeliveryFailureException异常并抛出。
异常在scope范围内抛出,被scope的Exception Handler捕获,在Exception Handler内进行异常处理。
如果接收形状没有被放置在scope中,或者scope的类型是atomic的,发送形状把消息发送出去后,Orchestration流程继续往下走,即时碰到atomic类型的scope的边界也不会停留,直到走到整个流程结束的边界,然后暂停等待ACK或NACK消息的返回。
Orchestration的发送端口接收到ACK消息,不做其他的处理,只是使暂停的Orchestration继续往下运行,正常结束Orchestration。
Orchestration的发送端口接收到NACK消息,会在发送端口出产生一个DeliveryFailureException异常并抛出。
由于没有Exception Handler,异常在Orchestration不被捕获,成为未被捕获的异常,在事件日志中可以看到一个未被捕获的异常事件。Orchestration服务实例被挂起。
Web发送端口没有Delivery Notification属性,所以Orchestration的web发送端口向物理发送端口发送消息中不会包含要求返回ACK或NACk的标志。
但是配置为SOAP适配器的物理发送端口会自动返回ACK或NACk消息。
注意:
Web类型发送端口无论是调用的有返回参数的webmethod还是无返回参数的webmethod,web类型发送端口都是具有request和response的双向端口。调用无返回参数的webmenthod,response的消息类型是一个没有消息部分只用消息上下文的web多部分消息类型。
orchestration发送端口把消息发送后,orchestration继续往下走。
orchestration流程运行到返回消息的接收形状停下来,等待消息的返回。
同样,在等待期间,orchestration服务实例处于运行状态,但是超过了一定的时间orchestration服务实例会被冻结(dehydrate),直到收到返回消息。
如果soap端口正常的把消息发送出去并接受到返回消息,则orchestration会在返回消息的接收形状接收到正常的返回消息,orchestration流程正常的运行下去。
如果soap端口产生异常,比如发送到WS的请求,在服务端返回了异常,或者soap端口到WS的网络不通,也或WS服务端需要身份验证而SOAP端口没有提供身份凭据等等,这时物理发送端口会返回给orchestration一个NACK消息。
收到NACK消息后,发送端口抛出SoapException异常。
根据发送形状是否在scope中,分两种情况:
Figure 2. web发送端口,在scope中的发送形状
发送形状被放置在非atomic的scope中,Exception Handler的捕获异常类型设置为SoapException类型(可能需要引用System.Web.Services.dll)。
Orchestration收到NACK消息后,抛出的SoapException异常就会被捕获,在Exception Handler内进行异常处理。
由于没有Exception Handler,异常在Orchestration不被捕获,成为未被捕获的异常,在事件日志中可以看到一个未被捕获的异常事件。Orchestration服务实例被挂起。这里请注意一点:atomic scope的 Synchronized属性改成True,否则会编译不过。