上一篇文章中,介绍了Shuttle ESB架构模型中的三个重要部分。
今天,我们继续介绍剩余的三个内容:模式和消息路由。
四、模式
Request/Response(请求/响应模式)
对基于Request/Response消息机制的内容。你能够看WiKi的一些文章:http://en.wikipedia.org/wiki/Request-response
向一个终端发送请求。运行某项功能,你能够发送一个命令消息:
bus.Send(new RequestMessage());
虽然这是一个很easy的模式,可是,它却构成了一种耦合紧密的行为。虽然如此,这也未必是一件坏事。在很多情况下这是绝必需的。
通常,命令消息的Handler(处理程序)。进行业务逻辑与消息的处理。可是非常多时候。请求须要有响应。
响应能够以命令消息或者事件消息的形式返回。
使用的时候很easy。你仅仅须要通过服务总线实例进行例如以下调用:
bus.Send(new ResponseMessage(), c => c.Reply());
当然,仅仅要你愿意,你能够将“响应”作为事件消息返回。来达到解耦合的目的。那么这将不再是请求/响应模式了,而是公布订阅模式。
请求/响应模式的优点是:它提供了一种机制,使调用者发出调用请求后。可以收到服务端的反应。
Publish/Subscribe(公布订阅模式)
对于基础公布订阅消息模式的很多其它内容,你能够看这里:http://en.wikipedia.org/wiki/Publish/subscribe
这样的模式的特点就是。让公布者和订阅者之间没有行为耦合。实际上,一个事件消息可能都没有订阅者。
可是这是不太符合实际情况的。
太多的实践证明,大多数情况下,我们要求至少要有一个订阅者。
公布一个事件消息,你能够採用例如以下格式:
bus.Send(new ResponseMessage(), c => c.Reply());
消息发送后。每个订阅者会都到接收到自己的消息。
这全然不同于一对一的消息分配处理机制。
消息分发
可想而知,假设一个端点接收太多的消息。那么处理这些消息就会端点处理能力减少,并且变得臃肿不堪。
这样的情况下,能够将消息改分配到服务节点上。
假设该终端接收到一个服务节点的请求消息,它将向其它服务节点自己主动分配该消息。一个终端能够配置成仅仅发送消息。配置非常easy,仅仅须要设置收件箱标签分配属性为true就可以。
由于消息分布都集成到收件箱。在处理同样端点时。仅仅须要在多个不同的机器上安装一对一的消息。你接收消息的一端。须要一个控制收件箱的配置。
由于全部的Shuttle消息都须要处理,而不是在队列中保持等待状态。
每个服务网站在配置中唯一标识。端点的控制收件箱须要例如以下配置:
<configuration>
<configSections>
<section name="serviceBus" type="Shuttle.ESB.Core.ServiceBusSection, Shuttle.ESB.Core"/>
</configSections>
<serviceBus>
<control
workQueueUri="msmq://./control-inbox-work"
errorQueueUri="msmq://./shuttle-error"/>
<inbox
distribute="true"
workQueueUri="msmq://./inbox-work"
errorQueueUri="msmq://./shuttle-error"/>
</serviceBus>
</configuration>
不论什么接收消息的一端都能这样配置。
然后,你就能够依据你的须要,建立多个服务节点。随着相关的全部公布者的增多,就会形成一个消息的逻辑终点。公布者的配置例如以下:
<configuration>
<configSections>
<section name="serviceBus" type="Shuttle.ESB.Core.ServiceBusSection, Shuttle.ESB.Core"/>
</configSections>
<serviceBus>
<worker
distributorControlWorkQueueUri="msmq:///control-inbox=work" />
<inbox
workQueueUri="msmq://./workerN-inbox-work"
errorQueueUri="msmq://./shuttle-error"
threadCount="15">
</inbox>
</serviceBus>
</configuration>
仅仅要应用程序配置文件包括一个闲置线程的标记。它就会发送一个消息给公布者,表明一个线程成为可运行的。然后订阅者将为每一个可用的线程公布消息。
当应用程序配置文件包括工人标记每一个线程去闲置将消息发送到经销商表示。一个线程已成为可运行的话。
经销商将为每一个可用的线程发送消息。
消息分发的特例
一些队列不须要消息分发。不使用客户终端,而是用它的还有一个实例。也可以使用同样的输入队列。这样的机制适用于代理。由于代理通过消费者线程执行的消耗。集中管理消息。由于消费者来自哪里都无所谓。所以队列可以给各个线程使用。
像基于MSMQ或者基于SqlServer的队列,这些都是通过启一个线程执行host。使用Handler进行消息处理。
代理的方式不同于这样的方式。在代理方式中,过程A将不知道这些消息所消耗的过程,并且导致B过程可能向其它端点获取消息。
五、消息路由
通常。我们说发送一个消息。依据“发送”,我们就确定它是一个命令消息。可是,它不一定必须是命令消息。你也能够给一个特定端点发送一个事件消息。实际情况下。很多其它的往往是发送事件消息。而不是命令消息。
消息发送后,通过调用服务总线实例相关的重载方法:
TransportMessage Send(object message);
TransportMessage Send(object message, Action<TransportMessageConfigurator> configure);
仅仅有那些没有RecipientInboxWorkQueueUri集的信息。将会通过服务总线进行传输。
假设你须要訪问不论什么可用的信息源数据。传输信息的Envelop将被退回。
Shuttle ESB採用了ImessageRouteProvider的实现。来确认消息发送。
public interface IMessageRouteProvider
{
IEnumerable<string> GetRouteUris(object message);
} The message route provider to use is specified when constructing the service bus: bus = ServiceBus
.Create(c => c.MessageRouteProvider(new DefaultForwardingRouteProvider())
.Start();
默认消息路由提供者,使用应用配置文件。来确定往哪发送消息:
<?xml version="1.0" encoding="utf-8" ? >
<configuration>
<configSections>
<section name="serviceBus" type="Shuttle.ESB.Core.ServiceBusSection, Shuttle.ESB.Core"/>
</configSections>
<serviceBus>
<messageRoutes>
<messageRoute uri="msmq://serverA/inbox">
<add specification="StartsWith" value="Shuttle.Messages1" />
<add specification="StartsWith" value="Shuttle.Messages2" />
</messageRoute>
<messageRoute uri="sql://serverB/inbox">
<add specification="TypeList" value="DoSomethingCommand, Assembly" />
</messageRoute>
<messageRoute uri="msmq://serverC/inbox">
<add specification="Regex" value=".+[Cc]ommand.+" />
</messageRoute>
<messageRoute uri="sql://serverD/inbox">
<add specification="Assembly" value="TheAssemblyName" />
</messageRoute>
</messageRoutes>
</serviceBus>
</configuration>
IMessageRouteProvider接口的每个实现,都能决定一个实现线路。
然而,它都须要从给定的消息发送。一个典型的场景,以及defaultmessagerouteprovider的工作方式,是使用完整的类型名称来确定目标。
注意:使用发送的每一个消息类型。仅仅能被发送到一个端点。
原文地址:http://shuttle.github.io/shuttle-esb/architecture/#Concepts