使用路由服务类

实现手动路由无疑是非常强大的技术,但是常见的场景下你所希望的仅仅是,基于请求的某些特性而不是编写一些动态的算法以实现路由消息。为了处理这样的场景,WCF提供了RoutingService类,该类位于System.ServiceModel.Route命名空间下。给命名空间下的类图如下图所示:
RoutingService类的目的在于:当消息达到时,基于内容实现路由。你可以配置RoutingService对象,使其检查消息头部的信息然后路由消息;甚至还可以使其转化消息体的内容然后基于转化后的内容路由请求。你可以通过包含一个或多个路由过滤器(过滤器指定了与消息的匹配条件以及和当匹配成功后消息推送目的地信息)的过滤表配置RoutingService类。一个路由过滤器实际上是MessageFilter类的实例。
你可以动态地创建MessageFilter对象,并将其与RoutingService对象关联。但大多数完成方式是静态地为每个路由过滤器添加过滤信息到寄宿RoutingService对象的应用程序的配置文件中;并使WCF运行时在运行服务时根据配置文件创建必要的MessageFilter对象。在下面练习中我们也将使用该方式。
在下面的练习中,你将更改ShoppingCartService服务的路由策略。不再使用负载均衡算法交替地发送请求至在不同端口侦听请求的ShoppingCartService实例;你将基于请求的类型路由消息:AddItemToCart消息和RemoveItemFromCart消息将被路由到ShoppingCartService服务的一个实例,而GetShoppingCart和CheckOut消息将路由到另外一个实例。
练习:寄宿和配置RoutingService服务
1. 使用Visual Studio打开WCF\Step.by.Step\Solutions\Chapter14\ShoppingCartServiceWithRouter文件夹下的ShoppingCart.sln解决方案。
该方案包含持续性ShoppingCartService服务,ShoppingCartServiceHost和ShoppingCartGUIClient项目,它从第七章复制过来。当前,ShoppingCartService服务配置了两个HTTP端点,这两个端点在9010和9020侦听请求,它们使用BasicHttpContextBinding绑定。
2. 添加一个新的控制台应用程序项目到ShoppingCart解决方案中。该控制台项目的名字为StaicRouter,并保存在WCF\Step.by.Step\Solutions\Chapter14\ShoppingCartServiceWithRouter文件夹下。
3. 引用System.ServiceModel, System.ServiceModel.Routing组件到StaticRouter项目,然后再引用项目ShopingCartService到StaticRouter项目。
4. 打开StaticRouter项目的Programm.cs文件;然后在文件的头部添加下面的using语句
5. 添加下面的代码(高亮部分)到programcs文件main方法中:
上述的代码你现在应该非常熟悉。该代码创建RoutingService类的一个实例,然后将其寄宿在ServiceHost对象中。你将在后续的步骤中为该服务定义配置文件。你还将制定ShoppingCartService服务的地址以使客户端的请求能路由到该地址。
6. 为StaticRouter项目添加配置文件,然后使用WCF服务配置管理器打开该配置文件。
7. 在配置面板,在服务文件夹上点击右键,然后点击创建新的服务。在右边的面板中,在名字字段处输入System.ServiceModel.Routing.RoutingService。该名字为RoutingService类的完整名。
8. 在配置面板,选择新创建服务,然后在其文件夹下的端点处点击右键,然后选择创建新的服务端点。在服务端点面板,按照下表的内容设置对应的属性的值。
属性
地址
http://localhost:9000/ShoppingCartService/ShoppingCartService.svc
绑定
basicHttpContextBinding
合约
System.ServiveModel.Routing.IRequestReplyRouter
合约定义了RoutingService对象实现的消息传输模式。IRequestReply接口基于一个通道处理基本的请求/回复双向模式,推送客户端的请求消息至服务并路由服务的响应消息到对应的客户端。还可以使用其他的合约。比如IDuplexSessionRouter,该接口允许RoutingService对象路由服务器的回调消息到客户端;或者ISimplexSessionRouter,该接口单向地路由消息到实现Session的服务;或者ISimplexDatagramRouter,该接口支持没有提供Session的服务。
注意:在第16章,我们将详细介绍如何创建并使用双向通道。
IRequestReplyRouter接口定义在System.ServiceModel.Routing命名空间下,其内容如下所示:
IRequestReplyRouter接口允许RoutingService类异步地推送请求和响应消息;该接口还支持事务。请注意Action和ReplyAction属性均被标注为*.
9. 在配置面板,展开高级文件夹,然后点击服务行为文件夹。在服务行为面板中,点击创建新的服务行为配置链接。
10. 在右边面板中,清除行为的名字,然后点击添加按钮,然后选择添加一个路由行为元素。该元素包含了你可以用来配置RoutingService服务的行为或者用以指定路由表名字的属性。
11. 在配置面板,展开未命名行为,然后点击路由元素。在右边的面板中,在FilterTableName字段处输入ShoppingCartServiceRoutingTable,请确认RouteOnHeadersOnly属性的值为True,并设置SoapProcessingEnabled属性为False。
你将在后续的步骤中为ShoppingCartServiceRoutingTable过滤表指定消息过滤元素。RouterOnHeadersOnly属性表明:过滤表中过滤元素在路由经过RoutingService服务的消息时,是仅仅定义过滤消息头的规则,还是过滤消息内容的规则。在本练习中,将根据消息头包含的请求动作信息过滤消息,因此RouterOnHeadersOnly属性设置为True。
当RoutingService服务接收到一条请求消息,路由服务基于不同的绑定路由该请求到一个目标服务,这可能与消息传输需求的实现有所不同。SoapProcessingEnabled属性指定了RoutingService服务是否在按照绑定的要求转换消息。如果该属性设置为false,那么路由服务不对消息做任何更改就直接推送消息至目标服务;否则,RoutingService服务将检查消息并将消息的格式转换为目标服务需求的格式。在本练习中,ShoppingCartService服务使用BasicHttpContextBinding绑定在服务和客户端程序之间传输包含了服务实例ID上下文信息。由于你需要将这些上下文信息没有任何干扰的经过RoutingService,因为该属性设置为false。
12. 在配置面板,展开客户端文件夹,然后再端点文件夹上点击右键,然后在添加创建新的客户端端点。在客户端端点面板,按照下表的内容设置对应的属性的值:
属性
名字
ShoppingCartServieHttpEndpoint1
地址
http://localhost:9010/ShoppingCartService/ShoppingCartService.svc
绑定
basicHttpBinding
合约
*
地址与ShoppingCartHost程序寄宿的ShoppingCartService服务的第一个端点地址相匹配。合约中*号字符表明服务接收任何消息而不是某些指定的服务合约的消息。
请注意Binding属性设置为basicHttpBinding而不是basicHttpContextBinding。客户端程序使用BasicHttpContextBinding绑定连接到RoutingService服务,其使得在消息头部中包含了诸如服务实例的ID这样的上下文信息。如果路由服务也使用上下文绑定连接到ShoppingCartService服务,那么RoutingService服务将会处理从ShoppingCartService服务接收到消息中的上下文信息,把这些上下文信息从消息头部中删除,因此这些上下文信息不会传递给客户端程序。而制定BasicHttpBindg绑定后则会阻止RoutingService服务再 把从ShoppingCartService服务响应的消息回传给客户端之前,从响应消息中查询上下文信息并删除这些上下文信息。此外,在前面步骤中我们已经提到,设置SoapPrecessingEnabled属性为false也阻止了RoutingService服务移除客户端程序发送消息中的上下文信息,因此RoutingService服务直接推送这些消息只ShoppingCartService--不做任何更改。
13. 按照下表内容添加第二个客户端端点
属性
名字
ShoppingCartServieHttpEndpoint1
地址
http://localhost:9020/ShoppingCartService/ShoppingCartService.svc
绑定
basicHttpBinding
合约
*
14. 保存配置文件,然后退出WCF服务配置管理器
15. 打开StaticRouter项目下的App.config文件,你将会看到上述的端点已经添加到配置文件中。
<fliters>元素中的过滤器列表定义了路由消息的规则。每个过滤器都有一个唯一的名字并且指定了一个filterType,过滤类型指定消息过滤器对象创建的过滤消息的类型。Action类型会导致WCF运行时创建一个ActionMessengerFilter对象,该对象可以基于消息头中的Action元素过滤请求。filterData属性指定了与Action对应的值。如果一个Action与filterData的值匹配,WCF运行时检查<filterTable>片段内的与filter名字像对应的每个实体;然后把消息路由到匹配实体指定的端点。比如,如果RoutingService服务接收到一个消息,该消息的头部的action值为http://
adventure-works.com/2010/06/04/ShoppingCartService/AddItemToCart,那么WCF运行时将路由消息至过滤表中ShoppingCart1实体定义的端点ShoppingCartServiceHttpEndpoint1。过滤表中的EndpointName属性引用<client>片段内定义的端点。
使用WCF,你还可以基于其他条件过滤消息。比如,你可以指定EndpointAddress以定义一个EndpointAddressMessageFilter。如果你希望基于消息体的内容执行过滤,你可以通过XPath创建一个XPathMessageFilter对象,此时flterData属性用于定义消息中数据的路径并且该属性的值对应一个Xpath表达式。
更过关于其他过滤类型的详细信息,请参考http://msdn.microsoft.com/en-us/library/system.servicemodel.routing.configuration.filtertype.aspx).
16. 重新生成项目。
现在你可以测试RoutingService宿主程序和配置。但是,为了演示消息被正确的路由到两个ShoppingCartService服务端点,你将配置ShoppingCartHost程序,并添加一个服务行为已显示每条接收和发送消息的动作和地址。
练习:测试RoutingService服务
1. 在ShoppingCartHost项目中,引用MessageInspector组件。
2. 使用WCF服务配置管理器打开ShoppingCartHost项目的App.config文件。在配置面板,展开高级文件夹,展开扩展,然后点击行为元素扩展。
3. 在右下面板,点击创建新的行为元素扩展。在扩展配置元素编辑器中,在名字文本框处,输入messageInspector
添加类型字段,然后该字段后的省略号按钮,在行为扩展类型浏览对话框中,选择Chpater14文件夹,然后点击MessageInspector组件,然后点击打开按钮。在行为扩展类型类型对话框中,点击MessageInspector.ShoppingCartBehaviroExtensionElement,然后点击打开按钮。
在扩展配置元素编辑对话框中,点击确认按钮。
4. 在配置面板,展开高级文件夹下的服务行为,然后点击DurabelServiceBehavior行为。在右边面板中,点击添加按钮,然后添加messageInspector行为元素至DurableServiceBehavior行为。
5. 保存配置文件并退出WCF服务配置管理器
6. 在解决方案浏览器窗口,在ShoppingCart方案上点击右键,然后设置方案的启动项目。把StaticRouter项目添加到启动项目组中。然后点击确认按钮
7. 在非调适模式下启动解决方案。Shopping Cart GUI客户端窗口将出现,同事还会出现一个ShoppingCartHost控制台程序和StaticRouter控制台程序。
8. 在Shopping Cart GUI窗口中的产品编码处输入SA-M198,然后点击添加按钮。接着继续添加另外一个产品WH-H098到购物车中。最后点击结算按钮。
客户端程序将得到与我们之前练习一样的结果。
9. 切换到ShoppingCartHost项目的控制台窗口。你将看到消息探测器所显示的消息。确认所有AddItemToCart请求都发送至在9010端口侦听的服务;而Chekcout消息发送至在9020端口侦听的服务。
10. 关闭Shopping Cart GUI窗口,分别在控制台窗口中按ENTER键关闭服务寄宿窗口和StaticRouter窗口。

总结

在本章,你已经了解到如何通过配置服务发现以从服务的实现中分离服务的地址;此外你还学习到WCF所支持的三种常见的服务发现模式:ad hoc, 声明和托管。
你还仔细地研究了如何实现路由WCF服务。你已经了解到WCF服务的运行时如何确定怎么处理请求消息。接收到消息的通道分发器逐个查询其端点分发器对象。一个端点分发器对外公开AddressFilter和ContractFilter属性,ChannelDispatcher对象使用这两个属性以发现该端点分发器是否可接收消息。被通道分发器选中的端点分发器开始处理消息并调用服务对应的方法。你可以通过提供自己的AddressFilter和ContractFilter对象,以及实现IDispatchOperationSelector接口;以实现自定义端点分发器接收和处理消息的方式。
此外,你还看到如何定义一个通用的WCF服务,该服务可以作为其他服务的路由器,该路由服务实现了一个方法,该方法可以接收任何消息并推送消息到可以处理这些消息的服务。
最后,你了解到如何使用和配置RoutingService类以实现基于在配置文件中的定义的信息路由消息。

WCF 4.0 进阶系列 – 第十四章 检测服务和路由消息(第四部分)相关推荐

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

    单向操作特别适用于"触发然后忘记"场景,在该场景中,客户端程序并不期望服务回传任何信息.但是,许多操作并不适用于这种情况,其向客户端程序返回数据.为了处理这些情况,WCF支持异步操 ...

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

    使用消息队列 消息队列是本书WCF异步技术中的最后一个出场的.消息队列可以为消息传输提供持久性.可靠性和事务性.甚至,发送消息的客户端程序与接受消息的服务可以不必同时运行.但使用该灵活性需要付出一定的 ...

  3. WCF 4.0 进阶系列 – 第十六章 使用回调合约发布和订阅事件(第二部分)

    使用回调合约通知客户端单向操作的结果 使用回调合约的原则是,提供一个服务,该服务采用单向操作-不返回任何信息-的方式通知客户端程序.本小节的例子基于之前描述过的更改产品价格场景.当客户端程序调用Pro ...

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

    当客户端程序调用一个单向操作后,客户端可以继续运行而不用等待服务完成该操作.你可以通过操作合约指定单向操作行为.达到该目的的最简单方式是在当以操作时设置Operation-Contract特性类的Is ...

  5. html第四章课后作业,物理化学答案——第四章化学平衡习题解答.doc

    物理化学答案--第四章化学平衡习题解答.doc 第四章 化学平衡一.基本公式和内容提要1. 化学反应的方向和限度(1)反应系统的吉布斯自由能和反应进度反应进行过程中,A和B均各以纯态存在而没有相互混合 ...

  6. WCF4.0进阶系列--第四章 保护企业内部的WCF服务(转)

    http://www.cnblogs.com/yang_sy/archive/2011/05/24/2054834.html [摘要] 安全是任何系统至关重要的一个方面,尤其当该系统由分布式的程序和服 ...

  7. 《操作系统真象还原》第十五章 ---- 实现系统交互 操作系统最终章 四十五天的不易与坚持终完结撒花 (下)(遗憾告终)

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 实现exec的思路与启发 遗憾告终 专栏博客链接 <操作系统真象还原>从零开始自制操作系统 全章节博客链接 相关查阅 ...

  8. 《操作系统真象还原》第十五章 ---- 实现系统交互 操作系统最终章 四十五天的不易与坚持终完结撒花(上)

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 闲聊时刻 实现fork 实现fork的介绍 实现fork的原理 编写完的thread.c(fork_pid) 编写完的thread.h(str ...

  9. c语言第四章作业,大学C语言第四章作业答案

    大学C语言第四章作业答案,期末考试的题库,二级C语言的练习 第四章课后习题参考程序 三.编程 1.输入一个正整数,判断该数为奇数还是偶数. 参考程序:(1) #include int main() { ...

最新文章

  1. 【iOS】Socket/TCP 通信 发送 NSString 字符串格式数据
  2. redhad yum 安装mysql_yum安装Mysql
  3. python 自动化-利用Python语言实现实验室自动化
  4. rhel配置磁盘分区_rhel配置磁盘分区_centos系统三套硬盘分区方案[图文设置版]
  5. 红黑树的理解与 Java 实现
  6. 《转》程序员必须知道的10大基础实用算法及其讲解
  7. 怎么查看一个网站是用什么语言编写的?
  8. 【有趣】Python之禅
  9. mysql主从数据库不同步的2种解决方法(转)
  10. BoundsChecker 使用方法
  11. 如何入门Python与机器学习
  12. MyScript ---LateX公式编辑排版
  13. 软件开发应遵循的原则
  14. pythonsqrt函数用法_C语言sqrt函数的实例用法讲解
  15. mysql 问号作用,在“WHERE column =?”中MySQL中问号的意义是什么?
  16. 选择华为账号第三方登录,让你无法拒绝的3个理由
  17. 可以删除电脑文件的c语言程序,win7电脑c盘都有哪些文件可以删除
  18. leetcode 18. 四数之和 (C++)
  19. 日本語トレーニング44
  20. idea怎么设置热启动

热门文章

  1. Linux Command Memo
  2. android 性能测试工具下载,Android性能测试 一些适用于Android Studio的代码审查和性能测试工具...
  3. 通达信公式作副图监控
  4. python cv 全景拼接
  5. 视频会议的图像清晰度由什么决定
  6. python popen 参数_Python – 如何传递一个字符串到subprocess.Popen(使用stdin参数)?
  7. 扫码枪收银有手续费吗_生鲜店的收银系统应该如何选择?
  8. ransac算法_增强现实(AR)算法第四讲
  9. 数通工程师的前景怎么样?好就业吗?
  10. windows系统安装node.js