WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)

时间:2022-10-21 23:50:16

使用消息队列

消息队列是本书WCF异步技术中的最后一个出场的。消息队列可以为消息传输提供持久性、可靠性和事务性。甚至,发送消息的客户端程序与接受消息的服务可以不必同时运行。但使用该灵活性需要付出一定的代价,那就是消息队列只能支持单向传输。因此如果使用该技术实现客户端程序和服务并且服务需要向客户端发送响应消息时,需要仔细的设计。另外,消息队列比其他传输协议更慢,这是因为它所支持的可靠性和可持续性;Windows操作系统需要把消息存储到磁盘。这意味着消息队列中的消息可以不受关机或者电源失败的影响;但这种稳健性在创建和传输消息时需要付出额外的I/O代价。
尽管MSMQ的编程模型非常简单,可能你曾经使用MSMQ构建过消息队列程序,但你仍然需要重视它。这是因为在WCF中你所使用的MSMQ技术与传统的C/S程序有根本的不同。但是,WCF有一个目标是:在发送和接受消息时保持一致性,而不管WCF底层使用了哪一个传输协议,因此使用消息队列的WCF与使用其他传输协议的WCF非常相似。但是,WCF使用的消息队列又和你过去曾经用的的消息队列技术有一些差别。
在本章最后一系列的练习中,你将看到使用消息队列作为传输协议实现单向异步操作是非常容易的。
 
练习:使用消息队列实现WCF服务
1. 使用Visual Studio,打开*\WCF\Step.by.Step\Solutions\Chapter12文件夹下的MSMQ解决方案
2. 在解决方案浏览器窗口,打开AdventureWorksAdminHost项目下的IService.cs文件
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
该文件中定义了一个IAdventureWorksAdmin的接口。该接口包含单个操作GenerateDailySalesReport。请注意该操作还通过OperationContract特性类的IsOneyWay属性指明了该操作为单向操作。这个设置很重要,因为通过消息队列实现的服务,其所有操作都必须是单向的。
3. 打开AdventureWorksAdminHost项目下的Service.cs文件
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
该文件包含了实现IAdventureWorksAdmin接口的AdventureWorksAdmin类。请注意GenerateDailySalesReport方法现在仅仅是等待10秒(模拟报表生成的过程)然后显示一个消息对话框以表示方法完成。
4. 在设计窗口下打开HostController.xaml文件。检查该文件,你会发现该文件是用于寄宿AdventureWokrsAdmin服务
5.使用WCF服务配置编辑器打开app.config文件
6. 在WCF配置编辑器的配置面板中,右键点击服务,然后选择创建新的服务
7. 在右边面板中,在名字属性处,输入AdventureWorksAdmin
8. 在配置面板中,右键点击AdventureWorksAdmin服务下的端点文件夹,然后选择创建新的服务端点
9. 在右边面板中,按照下表的内容设置该端点的属性
属性
名字 AdventureWorksAdminMsmqEndpoint
地址 Net.msmq://localhost/private/AdventureWorksAdmin
绑定 netMsmqBinding
服务合约 IAdventureWorksAdmin
消息队列URI由net.msmq和队列的名字组成。MSMQ通过与HTTP URL相似的方式识别队列,尽管与HTTP从学术意义上讲有一定程度的区别。URL的"private"部分指明其是一个私有的消息队列,这意味着该队列仅仅能够运行在本地计算机上。如果你使用的计算机位于Windows域中,那么你可以创建一个public的消息队列,这样域中的计算机都可以访问该消息队列。我们创建的消息队列的真实名字叫做AdventureWorksAdmin。

10. 在配置面板中,在绑定文件夹上点击右键,然后选择新的绑定配置。在创建新绑定配置对话框中,点击netMsmqBinding绑定类型,然后点击确认按钮
11. 在右边面板中,设置该绑定配置的名字为AdventureWorksAdminMsmqBindingConfig
你可以通过设置绑定属性以控制消息队列工作的诸多方面。比如,Durable属性决定消息是否可以不受处理过程失败、关机或者重启的影响而依旧存在;设置该属性为false那么将使消息容易受到破坏。ExactlyOnce属性涉及MSMQ的消息可靠性传输;设置该属性为true可以确保消息将被接收到一次并且仅仅一次,而且消息不会丢失或偶然地被并发实例接受两次。设置该属性为true要求消息队列必须是事务性的(使用计算机管理控制台创建消息队列时,可以指定一个队列是否为事务性队列)。
12. 点击安全标签,修改该绑定的安全模式属性为None
消息队列支持消息级别安全和传输级别安全,尽管实现传输级别安全是MSMQ特有的,并且不要求你配置SSL。如果你实现消息级别安全,你可以指定客户端证书的类型。你应该注意到MSMQ消息级别安全实现的验证机制要求配置消息队列服务器,该服务器必须为绑定所使用的消息队列提供一个证书。
13. 在配置面板,点击AdventureWorksAdminMsmqEndpoint端点定义,然后在右边的面板中,设置其绑定配置属性的值为AdventureWorksAdminMsmqBindingConfig
14. 保存配置文件然后退出WCF服务配置编辑器
15. 在Visual Studio中,生成AdventureWorksAdminHost项目。
 
实验:从WCF客户端向消息队列发送消息
1. 打开Visual Studio命令行工具窗口,然后转到*\WCF\Step.by.Step\Solutions\Chapter12\MSMQ\AdventureWorksAdminHost\bin\Debug文件夹下,然后输入下面的命令以生成客户端代理:
svcutil AdventureWorksAdminHost.exe
svcutil /namespace:*,AdventureWorksAdminTestClient.AdventureWorksAdmin adventure-works.com.2010.07.01.wsdl *.xsd /out:AdventureWorksAdminProxy.cs
为代理类生成的代码包含在AdventureWorksAdminProxy.cs文件中。请注意,当WCF服务使用MSMQ传输协议时,你不能使用Visual Studio自带的添加服务引用向导添加该WCF服务。
2. 返回到Visual Studio中,然后添加AdventureWorksAdminProxy.cs文件至AdventureWorksAdminTestClient项目。
3. 打开AdventureWorksAdminTestClient项目下的Programm.cs文件,该文件的main方法两次调用服务的GenerateDailySalesReport方法
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
4. 使用WCF服务配置编辑器编辑AdventureWorksAdminTestClient项目的app.config文件
5. 在配置面板,展开客户端文件夹,然后在端点上点击右键,然后选择创建新的客户端端点。
6. 在客户端端点面板中,使用下表的内容设置端点的属性:
属性
名字 MsmqBinding_AdventureWorksAdmin
地址 Net.msmq://localhost/private/AdventureWorksAdmin
绑定 netMsmqBinding
服务合约 AdventureWorksAdminTestClient.AdventureWorksAdmin.AdministrativeService
 
7. 基于netMsmqBinding类型添加一个绑定配置。设置该绑定名为为AdventureWorksAdminMsmqBindingConfig。并修改该绑定的安全模式为none
8. 返回到MsmqBinding_AdventureWorksAdmin端点定义,然后设置该端点的BindingConfiguration属性的值为AdventureWorksAdminMsmqBindingConfig
9. 保存配置文件并退出WCF服务配置编辑器
10. 在Programm.cs文件中,修改创建代理对象的声明:
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
 
到目前为止,你已经完成了服务和客户端程序的所有代码。接下来,你需要创建消息队列然后测试上述服务。
 
实验:创建AdventureWorksAdmin队列并测试该服务
1. 点击Windows的开始菜单,然后在我的电脑上点击右键,然后点击管理以启动计算机管理控制台。
2. 在计算机管理控制台中,在左边面板中展开服务和程序节点,然后展开消息队列节点,然后在private队列上点击右键,然后选择创建新的队列,最后选择创建私有队列。
3. 在创建私有队列对话框中,在名字处输入AdventureWorksAdmin,并选中事务性支持,然后点击确认按钮。
4. 不要关闭计算机管理控制台,然后回到Visual Studio。
5. 在非调适模式下运行解决方案。
在客户端控制台窗口中,按ENTER键以向服务发送两条GenerateDailySalesReport消息。请注意此时服务尚未启动,但客户端却成功地发送了这两条消息。按ENTER键关闭客户端控制台窗口。
6. 返回到计算机管理控制台,展开私有队列下的AdventurWorksAdmin队列,你将发现有两条消息显示在右边面板中。如下图所示:
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
7. 在AdventureWorks Admin Host窗口中,点击开始按钮
WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
服务将启动,然后依次从消息队列中获取消息,并处理消息。当消息处理完成后,服务的操作将显示一个消息框。当第二个消息对话框出现后,点击停止按钮停止服务并关闭AdventureWorks Admin Host窗口。
8. 返回到计算机管理控制台。你会发现第六步中显示的两条消息都已经消失。
9. 关机计算机管理控制台。
 
MSMQ提供了一个易于使用的机制以实现异步操作。但是,netMsmqBinding绑定限制你只能使用单向操作。如果一个服务需要发送响应,那么服务异步地发送一条消息至一个客户端程序可以连接的队列。这就涉及到为每一个客户端实现不同的消息,并且需要关联消息至每一个客户端;只有这样,客户端程序才知道哪一个响应消息对应哪一个请求消息。