什么是Service Bus Queues
Service Bus Queue提供了"Brokered"消息通信模式。当使用Queues的时候,分布式应用的组件之间并不是直接通信,而是通过作为中介角色的Queue来交换消息。消息生产者将消息发送至Queue,而消息消费者从Queue中获取消息并处理。生产者可以连续不断地发送消息,并不需要等待消费者的返回响应信息,发送方和接收方完全是异步模式。并且和传统的队列一样,Service Bus Queue遵循先进先出的规则。
如图所示,Service Bus Queues位于云端,而生产者和消费者可以位于任何地方,可以位于云端,可以在企业数据中心内部,可以位于个人PC,也可以是移动的,部署在移动设备上,而这些终端通过Queue建立彼此之间的联系。
为什么使用Service Bus Queues
在涉及代码之前我们来看一看Service Bus Queues有哪些优势,为什么或者是在什么情况下我们需要使用Service Bus Queues。
Temporal decoupling(时间解耦?)
Temporal decoupling意思就是消息生产者和消费者没有必要同时在线,发送的消息将被存储在Service Bus中,消费者在需要的时候上线获取消息就行。
Loose Coupling(松耦合)
生产者与消费者不会互相干预,完全是独立的应用,一方出现问题并不影响另一方的执行,体现了各组件之间松耦合的设计模式。
平衡负载量
为什么会涉及负载的相关功能?我们来做个对比。假设使用Web service部署服务,两端的通讯通过调用web服务来完成,则在高峰期,web服务所在机器会因访问过多而造成非常大的负载,而在闲散时间负载水平又非常低,所以这时负载情况如下图中的曲线所示。而如果使用Service Bus Queue来实现两端的数据通信,消费者从Queue中不断获取消息并处理,如果处理能力强,则单位时间内处理的消息多,否则较少,所以消费者所在机器不会出现峰值的情况,而是一条直线,既能保证业务正常处理,又能充分利用服务器的资源,所以可以说实现了均衡负载量的功能。
负载均衡
接着上面说,一个消费者处理能力有限,我们完全可以增加多个消费者来从Queue中读取消息并进行处理,多个消费者可以并行处理,并且保证每个消息只处理一次。这个模式完全是负载均衡的模式,而且自动实现了负载均衡,并不需要任何的路由策略。
如何使用Service Bus Queues
如需使用Service Bus Queue,首先需要在项目中引用Service Bus程序集,可通过Manage NuGet Packages搜索Service Bus的最新版本并添加引用。添加引用之后,将自动为项目Config文件添加Service Bus终结点配置:
1: <appSettings>
2: <!-- Service Bus specific app setings for messaging connections -->
3: <add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[yourdomain].servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=[yourkey]" />
4: </appSettings>
在进行Queue操作时,将自动根据这个配置连接位于云端的Service Bus,当然我们也可以在运行时通过代码设定配置。
创建Service Bus Queue
1: string queueName = "MyQueue";
2: NamespaceManager namespaceClient = NamespaceManager.Create();
3: QueueDescription myQueue = null;
4: if (!namespaceClient.QueueExists(queueName))
5: {
6: myQueue = namespaceClient.CreateQueue(queueName);
7: }
8: else
9: {
10: myQueue = namespaceClient.GetQueue(queueName);
11: }
发送消息
首先创建QueueClient对象
1: MessagingFactory factory = MessagingFactory.Create();
2: QueueClient myQueueClient = factory.CreateQueueClient("MyQueue");
然后创建消息对象BrokeredMessage,在消息传输中,所有消息内容都需要封装成BrokeredMessage对象
1: BrokeredMessage message = new BrokeredMessage();
2: message.Label = "SalesReport";
3: message.Properties.Add("Name", "Steven");
4: message.Properties.Add("Email", "Steven@hotmail.com");
5: message.Properties.Add("ProductCode", "P476534");
6: message.Properties.Add("Count", 1);
最后发送消息
1: myQueueClient.Send(message);
接收消息
首先创建QueueClient对象
1: string queueName = "MyQueue";
2: MessagingFactory factory = MessagingFactory.Create();
3: QueueClient myQueueClient = factory.CreateQueueClient(queueName, ReceiveMode.PeekLock);
我们注意到在创建客户端时,使用了一个参数:ReceiveMode,这个参数决定了消息的接收方式,ReceiveMode枚举定义如下:
1: public enum ReceiveMode
2: {
3: PeekLock,
4: ReceiveAndDelete
5: }
ReceiveAndDelete,顾名思义,当客户端接收完消息以后,该消息即从队列中移除,其他客户端无法获取该消息。在这种模式下,消息最多被处理一次,但是处理过程中可能出现异常导致处理失败,所以这种模式适合应用可以容忍消息处理失败的情景中。
PeerLock,ReceiveMode的默认值,当客户端接收消息以后,并不移除,而是给消息上锁,此时其他客户端无法获取该消息。锁的过期时间默认为1分钟,可以自定义设置,最大可以设置为5分钟。如果处理成功,可以将消息从队列中移除(Complete),如果失败,可以将锁移除(Abandon),使得消息可以被其他客户端接收并处理。当应用无法容忍消息处理失败时,使用这种模式更为安全。
接收消息
1: BrokeredMessage message = myQueueClient.Receive();
2: if (message != null)
3: {
4: try
5: {
6: ProcessMessage(message);
7:
8: message.Complete();
9: }
10: catch
11: {
12: message.Abandon();
13: }
14: }
在具体例子中使用了两个Winform客户端程序来分别模拟发送方和接收方,点击 这里 下载源码。