快速入门系列--WCF--06并发限流、可靠会话和队列服务
这部分将介绍一些相对深入的知识点,包括通过并发限流来保证服务的可用性,通过可靠会话机制保证会话信息的可靠性,通过队列服务来解耦客户端和服务端,提高系统的可服务数量并可以起到削峰的作用,最后还会对之前的事务知识做一定补充。
对于WCF服务来说,其寄宿在一个资源有限的环境中,为了实现服务性能最大化,需要提高其吞吐量即服务的并发性。然而在不进行流量控制的情况下,并发量过多,会使整个服务由于资源耗尽而崩溃。因此为相对平衡的并发数和系统可用性,需要设计一个闸门(Throttling)控制并发的数量。
由于WCF的并发出来属于服务自身的行为,因此通过服务行为对其进行控制,ServiceBehaviorAttribute(之后回调的CallbackBehaviorAttribute与此类似)中的ConcurrencyModel属性定义了Single、Reentrant和Multiple三种典型的并发模式,Single表示一个实例上下文InstanceContext只能用于单一请求的处理,Reentrant也表示一个实力上下文某一时刻只能用于对单一请求的处理,但若涉及回调,也可以用于其他服务调用请求的处理,Multiple表示一个实力上下文可以同时处理多个服务请求。此外,当将服务行为的ReleaseServiceInstanceOnTransactionComplete属性设置为true,其同步模式必须是Single,因为不能在其他请求还在处理中时释放实例。此外,可以通过设置UserSynchronizationContext属性为false来禁止并发操作。
可以通过设置System.ServiceModel.Description.ServiceThrottlingBehavior的相关属性来限流,包括:
MaxConcurrentCalls:当前ServiceHost能够处理的最大并发消息数量,默认为单核16。
MaxConcurrentInstances:当前ServiceHost允许存在的服务实例上下文的数量,默认为116。
MaxConcurrentSessions:当亲ServiceHost允许的最大并发会话数量,默认为100。
实际上WCF在其内部构建一个专门的内部组件FlowThrottle,其包含一个Capacity属性,表示最大流量,以及一个队列和计数器。ServiceThrottle三个流量限制器就像是设置在信道分发器中的三道闸门,第一道限制并发会话的流量,第二道限制并发请求的数量,第三道限制并发实例上下文的数量。为什么是这样的判断顺序,仍然有疑问?
作为一个通信基础平台,需要保持消息的可靠性,由于网络环境限制,网络层往往不能保证消息的有效交付,因此需要在应用层通过可靠会话机制来实现端到端的可靠信息传输。对于可能传输来说,常见的问题包括重复消息和无序消息的问题。说到这,不得不提TCP协议,其就是用在解决IP层消息传输不可能和无连接问题的,其通过3此握手建立长连接,通过消息确认和超时重传机制来保证消息的可靠性。那么它与现在要提及的WCF中RM有什么区别呢?主要包含以下4点:WCF可靠消息是基于SOAP的,而TCP是基于报文段的;其与传输协议无关,并不限于TCP协议;并没有具体传输会话限制,可以跨越多个传输连接或会话;TCP在当前连接内提供端到端可靠传输,而WS-RM提供两个SOAP终结点见的可靠传输,不受传输连接限制。
在实质上,WS-RM可靠传输的原理与TCP的活动窗口机制相似,其首先也会创建连接(CreateSequence),服务端会返回去一个Identifier,之后开始数据传输,Sequence的头部包含Identifier和MessageNo,后者用于识别顺序,此外还包含AcksTo、Expires、Offer等参数,最后会TerminateSequence。主要注意的是,在请求-回复模式的通信中,为了减少通信量,消息将包含2部分,一部分是对上条消息的回复(SequenceAcknowledgement),一部分是新的消息,常见的可靠会话配置如下所示。
<system.serviceModel>
<bindings>
<customBinding>
<binding name="orderedDelivery">
<reliableSession ordered="true"/>
<binaryMessageEncoding>
<readerQuotas maxArrayLength=""/>
</binaryMessageEncoding>
<tcpTransport maxBufferSize="" maxReceivedMessageSize=""></tcpTransport>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
最后通过一个表格,简单的介绍一下可靠会话的最佳实践。
方式 | 诠释 |
设置MaxTransferWindowSize | 用于指示传输窗口可以保存多少信息,默认为8条 |
有效使用网络 | 如果网络延迟大,可以考虑增大传输窗口,已达到提升网络使用率的目的 |
满负荷运行服务 | 使用缓冲区可以提高服务的可用性,推荐发送方和接受方使用相同的MaxTransferWindowSize |
启动流控制 | 为了确保发送方和接收方步调一致,推荐将FlowControlEnabled设置为true |
设置MaxPendingChannels | 一旦可靠传输建立,PendingChannel就会加1,因此需要为MaxPendingChannels设置一个合适的值,太低服务利用率不高,太高会影响到工作集的状态,默认为4 |
可靠会话和宿主 | 可靠会话是有状态的,有AppDomain维护,在双工场景下,默认每个客户端需要两条HTTP连接,因此可能出现资源使用过量死锁的情况,这是需要如下设置来处理。 <system.net> <connectionManagement><add name = "*" maxconnection="XX"/> </connectionManagement > <system.net> |
这部分将介绍微软MSMQ,虽然很老了,但仍然需要做一个基础的了解,当然了,现在比较推荐RabbitMQ的开源队列框架,不管怎么说在互联网场景下,消息队列是解决峰谷平衡的目前最好解决方案。其类似于人类传统的书信通信,寄件人只需要收件人地址、邮编和姓名信息,仍然将信件放入邮筒即可,而收件人只要定时检查收信即可。为了使用消息队列,首先通过Windows功能安装MSMQ,包括AD服务集成、HTTP支持、触发器、多播支持和DCOM代理等组件。消息队列的信息将保存在%Windir%\System32\msmq\storage中,常见的,队列分为如下几种队列。
普通队列:具体应用创建,基于业务的队列,分为公有和私有,公有队列被注册在AD域中,其基于域账号的Windows认证机制。
管理队列:确认消息被存储在管理队列中,包括成功确认和失败确认。
回复队列:MSMQ完全采用单向的消息交换模式,消息发送后是没有回复消息返回给发送端的,但有些场景下,需要包括简单确认外的回复内容,这是就涉及服务队列
日志队列:当消息成功发送或接受后,MSMQ可以将消息的拷贝作为发送或接受日志存储起来,分为源日志和目标日志。
事务性队列:MSMQ和SQL Server一样,属于事务管理器(RM,ResourceManager),可以登记到一个分布式事务中。
死信队列:存放限定时间内无法投递信息
报表队列:是公有队列,存储路由跟踪的报表信息
子队列:是一种消息容器,针对消息队列的一个常见操作是将消息从一个队列转移到另一个,其典型应用包括:有序递交,可以将乱序的消息暂时放在子队列中,排序后有序提交;毒性队列,当频繁出错时,可以将其暂存在相应的子队列中以使其他消息得到及时处理。
基于MSMQ的API都集中在System.Messaging中,其常见的路径格式及其示例如下。
队列类型 |
模式 |
日志队列(公有) | {MachineName}\{QueueName}\Journal$ |
日志队列(私有) | {MachineName}\Private$\{QueueName}\Journal$ |
系统日志队列 | {MachineName}\ Journal$ |
系统死信队列 | {MachineName}\ DeadLetter$ |
系统事务死信队列 | {MachineName}\ XactDeadLetter$ |
公有队列 | DIRECT=HTTP://Xionger-PC/msmq/MyQueue |
示例 | String path = @".\Private$\MyQueue"; MessageQueue queue = new MessageQueue(path); |
其构造函数,除了path,还包括SharedModeDenyReceive表示当前应用独占目标队列,enableCache表示创建连接缓存,queueAccessModel表示对象由于何种操作(Peek, Receive, Send)。
整个构架包括:消息队列的创建和删除;消息队列的查询;创建一个MessageQueue对象;消息队列的格式名称;消息的发送;MSMQ消息;消息的接收与查看
其事务模型、事务批量操作、会话、错误处理等操作相对复杂,这部分暂时不进行介绍。
事务处理协议,包括OleTx和WS-AT两种:前者采用RPC作为通信手段,使用二进制编码,是最高效的分布式处理协议,但只能用于Windows平台;后者WS-AT是WS-*的一员,支持跨平台。
WS-Coordination通过一个协调器和若干协调协议定义了一个可扩展的框架去协调一个分布式活动的所有参与者,其核心是协调器,提供激活服务(Activation Service)、注册服务(Registration Service)和协议服务(Protocol Service)。两个不同的应用的事务模型的建立最终会归结为协议服务之间的终结点引用的交换,
接下来,进入实践意义很强的WCF事务编程部分,其主要包含如下3个概念:
通过服务契约决定事务流转(Transaction Flow)的策略,通过定义TransactionFlowAttribute来决定事务策略,NotAllowed表示客户端的事务不允许被流转到服务端,服务端也不会视图去接受流入的事务,Allowed则相反,Mandatory表示客户端必须在事务中进行服务调用。
通过绑定实施事务的流转,相关配置如下所示。
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name ="transactionalTcpBinding" transactionFlow="true" transactionProtocol="WSAtomicTransactionOctober2004"/>
</netTcpBinding>
<ws2007HttpBinding>
<binding name="transactionalHttpBinding" transactionFlow="true"></binding>
</ws2007HttpBinding>
</bindings>
</system.serviceModel>
通过服务/操作行为控制事务的相关行为,相关配置如下所示。
[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.ReadCommitted, TransactionTimeout = "00:05:00", TransactionAutoCompleteOnSessionClose = true)] |
接下来通过一个示例来了解如何创建一个事务型服务(一个银行转账操作,涉及一个银行的取和另一个一个银行的存)。
步骤1服务契约和服务的实现,在服务接口方法上添加特性[TransactionFlow(TransactionFlowOption.Allowed)],在服务实现方法上添加[OperationBehavior(TransactionScopeRequired=true)]。
步骤2部署服务。
步骤3调用BankingService。
步骤4设置DTC,在控制面板的管理工具中设置,如下图所示。
步骤5采用WS-AT协议,即在binding配置项中添加:<transactionFlow transactionProtocol="WSAtomicTransactiona11">
Tip:到目前为止,仍然觉得分布式事务这部分比较复杂,最好虚拟出多机的分布式环境进行实践再学习。
参考资料:
[1]蒋金楠. WCF全面解析[M]. 上海:电子工业出版社, 2012.
快速入门系列--WCF--06并发限流、可靠会话和队列服务的更多相关文章
- wcf利用IDispatchMessageInspector实现接口监控日志记录和并发限流
一般对于提供出来的接口,虽然知道在哪些业务场景下才会被调用,但是不知道什么时候被调用.调用的频率.接口性能,当出现问题的时候也不容易重现请求:为了追踪这些内容就需要把每次接口的调用信息给完整的记录下来 ...
- 快速入门系列--WebAPI--01基础
ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...
- 快速入门系列--MVC--01概述
虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的 ...
- [转]快速入门系列--WebAPI--01基础
本文转自:http://www.cnblogs.com/wanliwang01/p/aspnet_webapi_base01.html ASP.NET MVC和WebAPI已经是.NET Web部分的 ...
- webpack 快速入门 系列 —— 性能
其他章节请看: webpack 快速入门 系列 性能 本篇主要介绍 webpack 中的一些常用性能,包括热模块替换.source map.oneOf.缓存.tree shaking.代码分割.懒加载 ...
- 快速入门系列--WebAPI--03框架你值得拥有
接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...
- 快速入门系列--WebAPI--04在老版本MVC4下的调整
WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了.在之前的介绍中,基本上都基于.NET 4.5之后版本,其System.N ...
- 快速入门系列--MVC--07与HTML5移动开发的结合
现在移动互联网的盛行,跨平台并兼容不同设备的HTML5越来越盛行,很多公司都在将自己过去的非HTML5网站应用渐进式的转化为HTML5应用,使得一套代码可以兼容不同的物理终端设备和浏览器,极大的提高了 ...
- 快速入门系列--WCF--02消息、会话与服务寄宿
经过WCF基础的ABC学习,已经可以构建简单的WCF的服务,使用不同的服务地址和绑定类型,根据业务提供所需的服务契约.但不禁想问,服务所使用的消息报文是什么样的形式么?蕴含什么样内容呢?WCF服务是否 ...
随机推荐
- 「2014-2-26」Unicode vs. UTF-8 etc.
目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ...
- 【转】JavaScript下对去重算法的优化
本人较懒,直接将链接附上: JavaScript下去重算法优化:http://www.linuxde.net/2013/02/12062.html
- Web Workers
在 Web Workers 中使用 postMessage 和 onmessage 首先,需要在客户端页面的 JavaScript 代码中 new 一个 Worker 实例出来,参数是需要在另一个线程 ...
- 后台设置gridview不换行
GridView1.Style.Add("word-break", "keep-all"); GridView1.Style.Add(&q ...
- EventBus的简单使用与原理
一.概述 EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间 ...
- (原创) 巩固理解I2C协议(MCU,经验)
题外话:这几天天气突然转冷了.今天已是11月23日了,查查黄历,昨天(11月22日)刚好是小雪,一夜温度骤降,果然老祖先的经验有灵验!冬天来了,还是多加加衣服,注意保暖! 1.Abstract ...
- angularjs 时间格式化
本地化日期格式化: ({{ today | date:'medium' }})Nov 19, 2015 3:57:48 PM ({{ today | date:'short' }})11/19/15 ...
- c# 动态执行脚本,相关的几个脚本引擎.
Jint 嵌入式的javascript脚本支持引擎,一直都在更新,对各种方法支持也比较好,可以 C# 交互. https://github.com/sebastienros/jint Jurass ...
- 【Win10】UAP/UWP/通用 开发之 RelativePanel
[Some information relates to pre-released product which may be substantially modified before it's co ...
- RCP: MANIFEST.MF, plugin.xml, build.properties三种文件的区别
在Eclipse插件开发中, MANIFEST.MF, plugin.xml, build.properties是三种最常见的文件,由于它们共享同一个编辑器(Plug-in Manifest Edit ...