一、概述

传入的客户端调用消息会分发给Windows I/O线程池(线程默认为1000)上的服务实例。多个客户端可以发起多个并发的调用,并且服务可以在多个线程上处理这些请求。如果传入的调用分发给同一个服务实例,就必须对内存中的服务状态提供线程安全的访问方式,否则,可能存在错误的风险。客户端回调时的内存状态亦是如此,因为回调也是分发给I/O线程池上的线程。此外,为了同步访问实例的状态,还需要同步访问实例之间共享的资源,比如静态变量。

WCF提供了两种同步模式:自动同步与手动同步。虽然自动同步会指导WCF去同步访问服务实例,但是它只对服务和回调类可用。手工同步是让开发者来控制同步,需要应用程序具体的集成工作。开发者需要使用.NET同步锁。手工同步的优点是,对服务类和非服务类来说,它都可以用,而且它允许开发者去优化吞吐量和伸缩性。

二、实例管理和并发

服务实例线程安全性与服务实例化模式紧密相关。

根据定义,单调服务实例是安全的,因为每个调用都有自己的服务实例。实例只分配给自己的工作线程访问,不必考虑同步问题。但是,单调服务是状态可知的,可以将状态存储在内部资源里,比如静态字典里,可以被多个线程访问,因为服务可以使用并发调用,不论是来自相同的客户端还是不同的客户端。

会话服务需要并发管理和同步,因为客户端可能使用相同的代理或者通过多线程发送请求给服务。

对于并发访问单例服务才是最敏感,而且它必须要支持同步访问。单例服务有一些所有客户端共享的状态信息。

发生客户端多线程调用的最大可能是,会话和单例中有多个客户端在不同的执行上下文里运行,每个客户端都使用自己的线程去调用服务。

但所有的调用都会通过I/O线程池上的线程进入相同的服务实例中——本质上,这就需要同步机制。

三、服务并发模式

ServiceBehavior的ConcurrencyMode属性控制着服务实例的并发访问。

// 指定服务类是支持单线程还是多线程操作模式。
public enum ConcurrencyMode
{
// 默认,单线程模型
Single = 0,
// 单线程,可重入模型,通常用在CallBack调用模型中
Reentrant = 1,
// 多线程模型
Multiple = 2,
} [AttributeUsage(AttributeTargets.Class)]

public sealed class ServiceBehaviorAttribute : ...

{

public ConcurrencyMode ConcurrencyMode

{get;set;}

//More members

}

枚举值ConcurrencyMode控制着是否以及何时允许并发调用。ConcurrencyMode的名字是错误的,正确的名字应该是ConcurrencyContextMode,因为它同步访问的不是实例,而是包含实例的上下文(InstanceContextMode也控制这上下文的实例化,而不是实例)。

1、ConcurrencyMode.Single

当并发模式配置为ConcurrencyMode.Single时,WCF会自动对服务上下文提供同步机制,会使用同步锁来把上下文和服务实例关联起来以阻止并发调用。每次进入的调用必须获得同步锁。一旦操作返回,WCF就会释放同步锁,从而允许后来的调用者进入。

同一个服务实例不会同时处理多个请求。当服务在处理请求时会对当前服务加锁,如果再有其它请求需要该服务处理的时候,需要排队等候。

例如:我们去银行去办理业务,如果营业厅中只有一个窗口对外服务的话,那当前窗口每次只能处理一个用户请求,如果再有其它用户需要办理业务的话,只能排队等待。直到我办理完业务后,营业窗口才能为队列中下个用户提供服务。

2、ConcurrencyMode.Reentrant

可重入的单线程处理模式,它仍然是单线程处理。服务端一次仍然只能处理一个请求,如果有多个请求同时到达仍然需要排队。与单线程不同的是,请求在处理过程中可以去调用其它服务,等到其它服务处理完成后,再回到原服务等待队列尾排队。在调用其它服务的过程中,会暂时释放锁,其它等待线程会趁机进行服务的调用。这种模式常见于服务端回调客户端的场境中。

重入适用于以下情况:

  • 如果单例服务调用的服务回调服务实例,那么单例服务调出就会带来死锁问题。
  • 在同一个应用程序域中,如果客户端把代理存储咋全局变量中,那么服务调用校友的某些对象就需要使用代理引用,去回调最初的服务。
  • 在非单向操作上的调用必须允许重入服务调用
  • 如果服务调用执行的事件过长,设置不会重入服务实例,那么要想办法优化吞吐量。在调出期间,允许其它客户端进入服务实例。

例如:我们去银行办理业务,营业厅中还是只有一个窗口对外服务,一次只能处理一个用户请求。我向银行服务员请求办理开户业务,从此刻开始该服务被我锁定,其它人员只能排队等待。在服务员办理业务的过程中,会让我填写开户申请表,这个签字的过程就是服务端对客户端的回调过程。由于填写开户申请表的时间会很长,为了不耽搁后面排队顾客的时间,我暂时释放对服务员的锁定,到旁边填写申请表,让后面的人员办理业务。在我签完字后再回到队列中等待服务,当再轮到我的时候我再次锁定服务,把凭据交给服务员,让他继续处理我的业务,这相当于服务的“重入”过程。 等到业务办完后,我会离开银行柜台,释放对该服务的锁定,等待队列中的下个人员又开始锁定服务办理业务了。

3、ConcurrencyMode.Multiple

多线程模式,多线程模式可以很好地增加系统的吞吐量。当多个用户请求服务实例时,服务并不会加锁,而是同时为多个请求服务。这样一来对所有用户共享的资源就会产生影响,所以这种多线程的访问模式需要对共享资源做好保护,大部份的情况下需我们的手动编写代码来实现多线程之间的访问保护。
    例如:我们去吃烤肉串,烤肉串的师傅可以同时为多个顾客烤制,而不用一个一个地排队等待,这就是典型的多线程处理模式。但这种模式如果不对肉串很好保护得的话那可麻烦了,比仿,我要的是3串麻辣味的,你要的是3串香辣味的,他要的是3串原味的,烤肉的时傅在烤制的时候需要对这三份肉串做好保护,防止做出一些“五味俱全”的肉串来。

四、实例与并发访问

使用相同的代理,一个单独的客户端可以像服务端发起多个并发的调用请求。客户端可以多线程去激活调用,也可以在同一个线程上发起快速、连续的单向调用。同一客户端的请求是否被服务并发处理完全取决与服务的实例模式、服务配置的并发模式以及传输模式(传输会话)。

单调服务

对于单调服务,如果没有传输层会话,那么并发处理是允许的。调用请求在到达服务端后会分发给每个新的服务实例,然后并发执行。这是一种可以不管服务并发模式的情况。

如果单调服务使用传输层会话,那么是否并发处理客户端请求就取决于服务配置的并发模式。如果服务配置为ConcurrentcyMode.Single,就不允许使用并发处理,每次只会分发一个调用消息。原因是使用了ConcurrentcyMode.Single,WCF会维护传输层会话,这样消息会严格按照发送的顺序执行。应该避免使用过久的处理,因为可能会导致超时。

如果服务配置为ConcurrentcyMode.Multiple,那么是允许并发的。调用会在到达时立即分发给新的服务实例进行并发处理。它的好处就是吞吐量,使用ConcurrentcyMode.Multiple搭配单调服务是个好主意——实例本身是线程安全的,所以不需要额外使用并发机制。

如果服务配置了ConcurrencyMode.Reetrant且服务没有调出,则结果就与ConcurrentcyMode.Single一样。

会话与单例服务

在使用会话和单例服务时,并发模式会控制等待调用的并发执行工作。如果服务配置了ConcurrentcyMode.Single并发模式,那么每次会发送给服务实例一个调用消息,等待的调用会放进一个队列中。应该避免使用过久的处理,因为可能会导致超时。

如果服务并发模式配置为ConcurrencyMode.Multiple,那么允许同时处理来自同一客户端的并发调用。调用消息在到达服务端时就会立即处理(取决于限流设置)。当然,还要处理服务实例的同步访问问题,否则可能带来一些风险。

如果服务并发模式配置为ConcurrencyMode.Reetant,那么服务实例的行为就与ConcurrentcyMode.Single类似。但是,如果服务调出,下一个调用就可以继续执行。

[WCF编程]13.并发:服务并发模式的更多相关文章

  1. 基于TCP的socket套接字的网络编程(客户端/服务端模式)

    于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...

  2. .Net-WCF-图书:《WCF编程》

    ylbtech-.Net-WCF-图书:<WCF编程> <WCF编程>是2008年1月机械工业出版社出版的图书,作者是Juval Lowy.Clemens Vasters. 1 ...

  3. 并发编程 13—— 线程池的使用 之 配置ThreadPoolExecutor 和 饱和策略

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  4. [WCF编程]7.实例上下文模式

    一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...

  5. 【WCF--初入江湖】08 并发与实例模式

    08 并发与实例模式 1. 实例上下文模式   一个服务代理:servicePoxy ChannelFactory<IService1> factoryservicel = new Cha ...

  6. Python高级编程和异步IO并发编程

    第1章 课程简介介绍如何配置系统的开发环境以及如何加入github私人仓库获取最新源码. 1-1 导学 试看 1-2 开发环境配置 1-3 资源获取方式第2章 python中一切皆对象本章节首先对比静 ...

  7. Java并发编程系列-(5) Java并发容器

    5 并发容器 5.1 Hashtable.HashMap.TreeMap.HashSet.LinkedHashMap 在介绍并发容器之前,先分析下普通的容器,以及相应的实现,方便后续的对比. Hash ...

  8. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

  9. 使用WCF实现SOA面向服务编程—— 架构设计

    原文地址:http://www.cnblogs.com/leslies2/archive/2011/03/29/1997889.html SOA本身就是一种面向企业级服务的系统架构,简单来说,SOA就 ...

随机推荐

  1. 剑指Offer面试题:15.反转链表

    一.题目:反转链表 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点. 链表结点定义如下,这里使用的是C#描述: public class Node { public in ...

  2. 一个新人如何学习在大型系统中添加新功能和Debug

    文章背景: 今年七月份正式入职,公司主营ERP软件,楼主所在的组主要负责二次开发,使用的语言是Java. 什么叫二次开发呢?ERP软件的客户都是企业.而这些企业之间的情况都有所不同,一套标准版本的企业 ...

  3. 一次Mysql 死锁事故

    故障描述: 简单描述一下需求:我们写的一个计步器的客户端软件,用户通过手机客户端将用户的运动计步信息传到服务器. 服务器侧记录每个用户每次上传明细,同时每个用户有一个汇总值,参与全省排名. 1.加入明 ...

  4. [Hadoop大数据]——Hive连接JOIN用例详解

    SQL里面通常都会用Join来连接两个表,做复杂的关联查询.比如用户表和订单表,能通过join得到某个用户购买的产品:或者某个产品被购买的人群.... Hive也支持这样的操作,而且由于Hive底层运 ...

  5. Juint整合Log4j

    一般Log4j配置在web.xml中,在单元测试时,不需要启动Tomcat,所有Log4j找不到配置文件 在测试类中手动加载 配置文件 PropertyConfigurator.configure(& ...

  6. sublime text3同时编辑多行

    sublime text3同时编辑多行 下面的才是正确的姿势,之前一直是shift + 右键 拖啊. http://stackoverflow.com/questions/32127604/how-t ...

  7. LINQ系列:Linq to Object相等操作符

    相等操作符通过比较两个序列来检查它们相应的元素是否相同.如果两个序列有相同的元素,并且对应元素的值相同,则认为这两个序列是相等的. SequenceEqual操作符判定两个集合是否相等.判定是通过并行 ...

  8. es6学习笔记一数组(中)

    接着上一篇,给大家再分享一些数组的其他方法.大家也可以去点击这里学习数组更多的方法 concat方法: 概述:    concat() 方法将传入的数组或非数组值与原数组合并,组成一个新的数组并返回. ...

  9. 深入理解DOM事件类型系列第二篇——键盘事件

    × 目录 [1]类型 [2]顺序 [3]按键信息[4]应用 前面的话 鼠标和键盘是电脑端主要的输入设备,上篇介绍了鼠标事件,本文将详细介绍键盘事件 类型 键盘事件用来描述键盘行为,主要有keydown ...

  10. Windows下使用Dev-C++开发基于pthread.h的多线程程序

    一.下载Windows版本的pthread 目前最新版本是:pthreads-w32-2-9-1-release.zip. 二.解压pthread到指定目录      我选择的目录是:E:\DEV-C ...