【WCF】服务并发中的“可重入模式”
2017-02-23 18:13
274 查看
WCF服务实例的并发模式是在服务实现类上,使用 ServiceBehaviorAttribute 的 ConcurrencyMode 属性来指定。其值由 ConcurrencyMode 枚举来界定,这个枚举只有三个值:
Single——服务实例只在单个线程上运行,如果服务是单个实例,那么同一时间只有一个传入的调用被接收,其他调用请拿票排队。
Multiple——这个好理解,服务实例支持多个线程同时调用,所以状态数据可能会不同步(单个服务实例),如果某些变量担心被其他线程意外修改,可以适合地 lock 一下。
Reentrant——这家伙是今天的主角,因为它不太好理解。老周就不抄MSDN了,就按我自己的理解说一下。“可重入模式”大致是这个意思:首先,服务实例是单线程,但是,如果在服务中调用另外的服务,那么此时其他正在排队的传入消息就可以进来。等其他另一个服务调用完成后,又重新进入当前服务操作继续向下执行。有点像你去营业厅排队办业务,服务窗口中的工作人员就是服务实例,而窗口外面排队的客户就是等待调用的客户端。假如我要申请一个业务,通常要填个XXX表格。要是等你填完,估计后面排队的人会跑掉一半。所以,常规的做法是:你站到一边去填表(相当于在服务实例中调用另外一个服务),然后让后面排队的人继续办业务。等你填完表了,再回来找工作人员处理(相当于另外一个服务调用完成,重新进入当前服务实例)。
没看懂?还是实例好用吧。来,下面咱们来动动手吧。
首先我们弄个“另一个”服务。
这个服务协定有一个方法,作用很简单,产生一个GUID,然后返回,能看懂吧。
好,现在来弄“主”服务。
待会儿我们实现这个协定时,在服务操作方法中去调用前面的“另一个”服务。
还没完呢,我们设置一下这个服务类,让它使用“可重入”并发模式。
启动ServiceHost并接收请求。
模拟客户端调用,咱们开N个 Task 来模拟同时有 N 个客户端调用服务的情形。
最后的 Task.WaitAll 用以等待所有 Task 完成执行,此处可以不要这句。
好,见证的时刻即将来了。运行!
在当前服务去调用另外一个服务的时候,其他正在等待的调用就会进来,在上图中,上面的是“另一个”服务被调用时生成的 GUID,下面是“另一个”服务调用完成后返回到当前服务后得到的 GUID。
从图中,大家会发现,“另一个”服务产生ID输出的顺序,与调用返回后输出的顺序不同,看来,调用完成后,重新进入到当前服务实例的消息还得排队,故调用后返回的消息顺序与“另一个”服务生成ID的顺序并不一致。
不知道用这个示例来装逼之后,各位是否能理解“可重入”并发的含义。
示例源代码下载地址
Single——服务实例只在单个线程上运行,如果服务是单个实例,那么同一时间只有一个传入的调用被接收,其他调用请拿票排队。
Multiple——这个好理解,服务实例支持多个线程同时调用,所以状态数据可能会不同步(单个服务实例),如果某些变量担心被其他线程意外修改,可以适合地 lock 一下。
Reentrant——这家伙是今天的主角,因为它不太好理解。老周就不抄MSDN了,就按我自己的理解说一下。“可重入模式”大致是这个意思:首先,服务实例是单线程,但是,如果在服务中调用另外的服务,那么此时其他正在排队的传入消息就可以进来。等其他另一个服务调用完成后,又重新进入当前服务操作继续向下执行。有点像你去营业厅排队办业务,服务窗口中的工作人员就是服务实例,而窗口外面排队的客户就是等待调用的客户端。假如我要申请一个业务,通常要填个XXX表格。要是等你填完,估计后面排队的人会跑掉一半。所以,常规的做法是:你站到一边去填表(相当于在服务实例中调用另外一个服务),然后让后面排队的人继续办业务。等你填完表了,再回来找工作人员处理(相当于另外一个服务调用完成,重新进入当前服务实例)。
没看懂?还是实例好用吧。来,下面咱们来动动手吧。
首先我们弄个“另一个”服务。
[ServiceContract] public interface ISome { [OperationContract] Guid GetUID(); } class SomeService : ISome { public Guid GetUID() { Guid id = Guid.NewGuid(); Console.WriteLine($"第二个服务被调用,产生的ID为:{id}"); return id; } }
这个服务协定有一个方法,作用很简单,产生一个GUID,然后返回,能看懂吧。
好,现在来弄“主”服务。
[ServiceContract] public interface ITestService { [OperationContract] void TestCall(); }
待会儿我们实现这个协定时,在服务操作方法中去调用前面的“另一个”服务。
internal class TestService : ITestService { public void TestCall() { Console.WriteLine("即将调用另一个服务。"); // 调用其他服务 ISome cnl = ChannelFactory<ISome>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345")); // 调用完成后,再次回来 Guid id = cnl.GetUID(); ((IClientChannel)cnl).Close(); Console.WriteLine($"回到当前服务。得到的ID为:{id}"); } }
还没完呢,我们设置一下这个服务类,让它使用“可重入”并发模式。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)] internal class TestService : ITestService { …… }
启动ServiceHost并接收请求。
using (ServiceHost host = new ServiceHost(typeof(TestService))) { host.AddServiceEndpoint(typeof(ITestService), new WSHttpBinding(), "http://localhost:9000"); host.Open(); //运行服务 Console.WriteLine("主服务已启动。"); …… Console.ReadKey(); }
模拟客户端调用,咱们开N个 Task 来模拟同时有 N 个客户端调用服务的情形。
Action actdlg = () => { ITestService cn = ChannelFactory<ITestService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:9000")); cn.TestCall(); // 关闭通道 ((IClientChannel)cn).Close(); }; // 开启5个任务 Task[] tasks = new Task[5]; // 初始化每个任务 for (int n = 0; n < tasks.Length; n++) { tasks = new Task(actdlg); } // 开始执行任务 foreach (Task t in tasks) { t.Start(); } // 等待所有任务完成 Task.WaitAll(tasks);
最后的 Task.WaitAll 用以等待所有 Task 完成执行,此处可以不要这句。
好,见证的时刻即将来了。运行!
在当前服务去调用另外一个服务的时候,其他正在等待的调用就会进来,在上图中,上面的是“另一个”服务被调用时生成的 GUID,下面是“另一个”服务调用完成后返回到当前服务后得到的 GUID。
从图中,大家会发现,“另一个”服务产生ID输出的顺序,与调用返回后输出的顺序不同,看来,调用完成后,重新进入到当前服务实例的消息还得排队,故调用后返回的消息顺序与“另一个”服务生成ID的顺序并不一致。
不知道用这个示例来装逼之后,各位是否能理解“可重入”并发的含义。
示例源代码下载地址
相关文章推荐
- ConcurrencyMode.Multiple模式下的WCF服务就一定是并发执行的吗:探讨同步上下文对并发的影响[上篇]
- ConcurrencyMode.Multiple 模式下的WCF服务就一定是并发执行的吗:探讨同步上下文对并发的影响[下篇]
- WCF服务实例模式与并发、限流
- 并发与实例上下文模式: WCF服务在不同实例上下文模式下具有怎样的并发表现
- WCF 第八章 安全 因特网上的安全服务(下) 其他认证模式
- WCF面向服务应用程序系列之十七:消息交换模式(MEP)-单向操作
- WCF - 服务实例管理模式
- WCF单例服务,如何实现并发
- WCF学习之:实例上下文模式和并发模式的性能影响
- WCF把书读薄(2)——消息交换、服务实例、会话与并发
- [导入]构建WCF面向服务的应用程序系列课程(9):并发, 吞吐量与限流.zip(21.43 MB)
- WCF4.0 –- RESTful WCF Services (实例) (并发同步服务 SyncService)
- 提高WCF服务并发能力的简单处理办法
- WCF4.0 –- RESTful WCF Services (实例) (并发同步服务 SyncService)
- 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(3)--- 服务访问和配置模式
- WCF 第五章 并发和实例(服务行为)
- WCF技术剖析之五:利用ASP.NET兼容模式创建支持会话(Session)的WCF服务
- [导入]构建WCF面向服务的应用程序系列课程(7):消息模式.zip(15.48 MB)
- WCF 第五章 导出并发布元数据(服务行为)
- WCF实例上下文模式与并发模式对性能的影响 转载自:http://log.medcl.net/item/2010/03/wcf-instance-context-mode-and-the-performance-impact-of-conc