用实例浅谈WCF实例与并发
2011-04-22 07:57
218 查看
并发是对同时执行的任务数量的度量,单位为任务(如请求、作业、事务等)。执行时间是对完成任务所用时间的度量,单位为时间(如毫秒、秒等)。吞吐量是在固定的时间内完成的任务数量的度量,单位为任务/时间(如请求/秒、事务/秒等)。可以通过减少执行时间或提高并发来提高吞吐量。在WCF中可以通过InstanceContextMode和ConcurrencyMode来控制并发行为。
InstanceContextMode用于控制服务类实例化,可以有以下几种取值:
Single:一个服务类实例处理所有客户端的所有请求。
PerCall:为每一个客户端的每一个请求创建一个服务类实例。
PerSession:为每一个客户端会话创建一个服务类实例(也就是每一个客户端会话的所有请求共用一个服务类实例)。
ConcurrencyMode用来控制服务类实例内的线程并发。有以下取值:
Single:在同一时刻只有一个线程可以访问服务类实例。
Reentrant:在同一时刻只有一个线程访问服务类实例,但是线程能暂时离开服务类实例,稍后回来并继续访问。
Mutiple:多线程能并发访问服务类实例。
下面用简单的代码来展示InstanceContextMode和ConcurrencyMode不同的设置组合对服务类实例化和并发的影响。这次用NetTcpBinding绑定,它支持会话。
服务契约:
服务类:
服务端寄存:
运行此控制台程序,用如下命令生成代理和配置文件
“/a”是为了生存异步调用方法。而后把生存的两个文件添加到客户端项目内。
客户端调用代码:
首先设置ConcurrencyMode.Single和InstanceContextMode.PerCall 这种组合设置会为每次调用生成一个服务类实例。
运行结果:
下面用ConcurrencyMode.Single和InstanceContextMode.PerSession测试下,结果应该是每个客户会话一个服务类实例,这次启动两个客户端,应该只有两个服务类实例。
执行结果,服务端:
客户端:
下面我们用ConcurrencyMode.Multiple和InstanceContextMode.PerSession进行测试,因为同一会话中允许多个线程并发访问,所以需要手工控制访问的安全性。
修改服务类代码如下:
程序的执行结果(还是运行两个客户端)服务端:
客户端:
假如把InstanceContextMode设置为PerCall那将都会是1。还有几种组合就不一一测试。
InstanceContextMode用于控制服务类实例化,可以有以下几种取值:
Single:一个服务类实例处理所有客户端的所有请求。
PerCall:为每一个客户端的每一个请求创建一个服务类实例。
PerSession:为每一个客户端会话创建一个服务类实例(也就是每一个客户端会话的所有请求共用一个服务类实例)。
ConcurrencyMode用来控制服务类实例内的线程并发。有以下取值:
Single:在同一时刻只有一个线程可以访问服务类实例。
Reentrant:在同一时刻只有一个线程访问服务类实例,但是线程能暂时离开服务类实例,稍后回来并继续访问。
Mutiple:多线程能并发访问服务类实例。
下面用简单的代码来展示InstanceContextMode和ConcurrencyMode不同的设置组合对服务类实例化和并发的影响。这次用NetTcpBinding绑定,它支持会话。
服务契约:
using System; using System.ServiceModel; namespace IFruitSvc { [ServiceContract(Namespace="http://www.cnblogs.com/qiuwuyu")] public interface IFruitService { [OperationContract] string GetFruitName(); } }
服务类:
using System; using System.ServiceModel; using IFruitSvc; using System.Threading; using System.ServiceModel.Description; namespace FruitSvc { public class FruitService:IFruitService { FruitService() { Console.WriteLine("{0} : Created new instance of FruitService on thread", DateTime.Now.Ticks); } public string GetFruitName() { Console.WriteLine("{0} : GetFruitName called on thread {1} ", DateTime.Now.Ticks, Thread.CurrentThread.ManagedThreadId); return "banana"; } } }
服务端寄存:
using System; using System.ServiceModel; using System.ServiceModel.Description; using IFruitSvc; using FruitSvc; namespace WcfInstanceHost { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(FruitService), new Uri("net.tcp://localhost:8000"))) { ServiceEndpoint sed= host.AddServiceEndpoint(typeof(IFruitService), new NetTcpBinding(), "FruitService"); //设置IFruitService的ServiceContract特性的SessionMode sed.Contract.SessionMode = SessionMode.Allowed; ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); host.Description.Behaviors.Add(behavior); ServiceBehaviorAttribute behaviorAttr = host.Description.Behaviors.Find<ServiceBehaviorAttribute>(); if (behaviorAttr == null) { behaviorAttr = new ServiceBehaviorAttribute(); } //设置服务类FruitService的ServiceBehavior特性的ConcurrencyMode和InstanceContextMode behaviorAttr.ConcurrencyMode = ConcurrencyMode.Single; behaviorAttr.InstanceContextMode = InstanceContextMode.PerCall; host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); host.Open(); Console.WriteLine("Fruit Service Is Running..."); Console.ReadLine(); } } } }
运行此控制台程序,用如下命令生成代理和配置文件
“/a”是为了生存异步调用方法。而后把生存的两个文件添加到客户端项目内。
客户端调用代码:
using System; using System.Threading; namespace WcfInstanceClient { class Program { static void Main(string[] args) { FruitServiceClient proxy = new FruitServiceClient(); for (int i = 0; i < 4; i++) { Console.WriteLine("{0}: Begin Calling GetFruitName", DateTime.Now.Ticks); proxy.BeginGetFruitName(GetFruitNameCallBack, proxy); } Console.ReadLine(); } static void GetFruitNameCallBack(IAsyncResult ar) { string name = ((FruitServiceClient)ar.AsyncState).EndGetFruitName(ar); Console.WriteLine("{0}: End FruitName:{1} ", DateTime.Now.Ticks, name); } } }
首先设置ConcurrencyMode.Single和InstanceContextMode.PerCall 这种组合设置会为每次调用生成一个服务类实例。
运行结果:
下面用ConcurrencyMode.Single和InstanceContextMode.PerSession测试下,结果应该是每个客户会话一个服务类实例,这次启动两个客户端,应该只有两个服务类实例。
执行结果,服务端:
客户端:
下面我们用ConcurrencyMode.Multiple和InstanceContextMode.PerSession进行测试,因为同一会话中允许多个线程并发访问,所以需要手工控制访问的安全性。
修改服务类代码如下:
public class FruitService:IFruitService { //添加一对象,对此对象访问加锁 object lockObj = new object(); private int n = 0; FruitService() { Console.WriteLine("{0} : Created new instance of FruitService on thread", DateTime.Now.Ticks); } public string GetFruitName() { string name = "banana"; Console.WriteLine("{0} : GetFruitName called on thread {1} ", DateTime.Now.Ticks, Thread.CurrentThread.ManagedThreadId); lock (lockObj) { name=name + "_" + (++n).ToString(); } return name; } }
程序的执行结果(还是运行两个客户端)服务端:
客户端:
假如把InstanceContextMode设置为PerCall那将都会是1。还有几种组合就不一一测试。
相关文章推荐
- WCF实例与并发
- WCF实例与并发
- WCF ServiceHost的实例方式及ServiceHost实例的并发方式
- 并发与实例上下文模式: WCF服务在不同实例上下文模式下具有怎样的并发表现
- WCF 第五章 并发和实例(服务行为)
- WCF实例上下文模式与并发模式对性能的影响 转载自:http://log.medcl.net/item/2010/03/wcf-instance-context-mode-and-the-performance-impact-of-conc
- WCF4.0 –- RESTful WCF Services (实例) (并发同步服务 SyncService)
- WCF 第五章 不支持会话的绑定的默认并发和实例
- WCF并发(Concurrency)的本质:同一个服务实例上下文(InstanceContext)同时处理多个服务调用请求
- WCF基础之会话、实例和并发
- WCF实例与并发的一些测试
- 【WCF--初入江湖】08 并发与实例模式
- WCF 第五章 不支持会话的绑定的默认并发和实例
- WCF4.0 –- RESTful WCF Services (实例) (并发同步服务 SyncService)
- WCF简单教程(7) 并发模型与实例模型 推荐
- WCF 第五章 控制并发实例的数量
- WCF实例与并发
- 用实例浅谈WCF消息队列
- WCF并发控制与实例模式
- WCF 第五章 控制并发实例的数量