实现 WCF 服务行为






4.95/5 (44投票s)
在这里,
介绍
本文将解释如何通过各种 WCF 服务行为技术来实现吞吐量、可靠性和性能。大多数应用程序在可伸缩性和性能策略方面差异很大。WCF 服务行为提供了配置关键运行时行为的各种可能方式。我们将逐一介绍各种服务行为元素。
并发
默认情况下,WCF 服务一次只能处理一个请求,所有其他服务请求线程都将被排队并逐一处理。并发元素允许客户端同时发送多个请求,但服务实现应避免死锁等场景。
并发模式有三种。
- Single(默认):并发模式 Single 一次只允许一个服务实例。所有其他待处理请求将保持在队列中并逐一处理。每当新请求进来时,调度程序会在进入代码之前获取锁定。参见图 1。
- Multiple:这允许并行请求,并通过为每个请求生成单独的线程来同时处理。参见图 2。
- Re-entrant:每当客户端调用 WCF 服务时,都会为此客户端调用分配一个线程锁。让我们考虑一个场景,服务 1 调用外部服务 2。线程锁在整个服务调用完成之前不会被释放。因此,所有其他客户端请求都处于等待状态。Re-entrant 允许客户端在调用外部服务(服务 2)之前释放锁,这样其他客户端就可以使用服务 1 的功能,直到服务 2 处理完成。参见图 3。
ConcurrencyMode Single
定义如下:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
public class VisitorCount : IVisitorCount
{
}
以下是我们定义 ConcurrencyMode Multiple
的方式。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class VisitorCount : IVisitorCount
{
}
使用 ConcurrencyMode Reentrant
装饰服务类。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class VisitorCount : IVisitorCount
{
}
并发模式可以增加服务方法中的通过量,从而提高整体服务性能。
实例上下文模式
WCF 实例决定对象的创建方式,并指代服务对象的生命周期。每当客户端发起请求时,运行时都会创建服务对象来提供响应。通过实例,我们可以控制此服务实例要保留多长时间。为此,我们使用三种实例模式。
- Per Call:在此场景中,所有对服务的调用都是无状态的。对于每个线程请求,都会创建一个新的服务实例。这适用于所有服务绑定。参见图 4。
- Per Session:服务对象的生命周期独立于客户端通道的生命周期,因此每次建立新的通信会话时都会创建一个新的服务对象,并在之后将其释放。每个客户端通道都会获得一个专用的服务实例,并且同一会话中的后续调用将由同一个服务对象处理。这是 Instancing Context 的默认值。它适用于除 basicHttpBindings 之外的所有绑定。参见图 5。
- Single:这将帮助我们全局共享数据。我们只能创建一个实例,并且后续调用将重用同一个实例。与 Per Session 类似,它适用于除 basicHttpBinding 之外的所有绑定。单例实例在服务主机关闭之前不会被释放。参见图 6。
以下是我们定义 InstanceContext Mode Percall
的方式。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.PerCall)]
public class VisitorCount : IVisitorCount
{
}
以下是我们定义 InstanceContextMode PerSession
的方式。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,InstanceContextMode = InstanceContextMode.PerSession)]
public class VisitorCount : IVisitorCount
{
}
以下是我们定义 InstanceContext mode Single
的方式。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,InstanceContextMode = InstanceContextMode.Single)]
public class VisitorCount : IVisitorCount
{
}
服务节流
WCF 允许您限制特定服务类型的负载。
这包括
- 最大并发会话数
- 最大并发调用数
- 最大并发实例数
每当这些值超过时,调用者将被添加到队列中并按 FIFO 顺序处理。我们可以按如下方式在应用程序配置文件中配置节流行为。
<serviceBehaviors>
<behavior name="visitorCountServiceBehavior">
<serviceThrottling maxConcurrentCalls="5" maxConcurrentInstances="10" maxConcurrentSessions="10">
</serviceThrottling>
</behavior>
</serviceBehaviors>
使用代码
让我们创建一个示例应用程序来演示不同的服务行为。首先创建一个接口,并使用 ServiceContract 和 OperationalContract
属性来指定客户端应用程序可以使用此接口的这些操作。
[ServiceContract]
public interface IVisitorCount
{
[OperationContract]
int GetVisitorCount();
}
现在,我们需要创建一个服务类来实现上述接口方法。并且我们需要使用不同的服务行为来装饰服务类。以下代码解释了 Concurrency Mode Single 和 Instance context mode single。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,InstanceContextMode = InstanceContextMode.Single)]
public class VisitorCount : IVisitorCount
{
int _visitorCount = 0;
public VisitorCount()
{
Console.WriteLine("New Service Instance Created");
}
public int GetVisitorCount()
{
_visitorCount++;
return _visitorCount;
}
}
现在让我们看看如何使此服务可供客户端应用程序使用。App.Config 配置文件内容如下。
<configuration>
<system.web>
<compilation debug="true">
</compilation></system.web>
<system.servicemodel>
<services>
<service name="InstanceContextModeService.VisitorCount">
<endpoint binding="wsHttpBinding" contract="InstanceContextModeService.IVisitorCount">
<identity>
<dns value="localhost">
</dns></identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
<host>
<baseAddresses>
<add baseaddress="https://:8732/InstanceContextModeService/VisitorCount/">
</baseAddresses>
</add></host>
</endpoint></service>
</services>
<behaviors>
<servicebehaviors>
<behavior>
<servicemetadata httpgetenabled="True">
<servicedebug includeexceptiondetailinfaults="False">
<servicethrottling maxconcurrentcalls="5" maxconcurrentinstances="10" maxconcurrentsessions="10">
</servicethrottling></servicedebug></servicemetadata><</behavior>
</servicebehaviors>
</behaviors>
</system.servicemodel>
</configuration>
以下服务主机代码将 VisitorCounter
服务托管给客户端应用程序。
class Program
{
private static ServiceHost host = null;
static void Main(string[] args)
{
host = new ServiceHost(typeof(InstanceContextModeService.VisitorCount));
host.Opened += new EventHandler(host_Opened);
host.Closed += new EventHandler(host_Closed);
host.Open();
Console.ReadKey();
host.Close();
Console.ReadKey();
}
static void host_Closed(object sender, EventArgs e)
{
Console.WriteLine("Service Closed");
}
static void host_Opened(object sender, EventArgs e)
{
Console.WriteLine("Service Started");
}
}
我们的服务已托管并定义。以下代码解释了客户端如何利用服务和服务行为。
static class Program
{
static void Main(string[] args)
{
VisitorCountClient client = new VisitorCountClient();
Console.WriteLine("First Call-->" + client.GetVisitorCount());
Console.ReadKey();
Console.WriteLine("Second Call-->" + client.GetVisitorCount());
Console.ReadKey();
Console.WriteLine("Third Call-->" + client.GetVisitorCount());
Console.ReadKey();
Console.WriteLine("Forth Call-->" + client.GetVisitorCount());
Console.ReadKey();
}
}
下载上面附加的示例应用程序供您参考,并像我们之前讨论的那样,通过更改不同的行为属性来回顾不同的服务行为。
摘要
每当我们设计企业应用程序时,它都应该提供出色的性能、可伸缩性、吞吐量和可靠性。WCF 可以通过本文讨论的不同技术实现这些功能。