65.9K
CodeProject 正在变化。 阅读更多。
Home

实现 WCF 服务行为

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (44投票s)

2012年8月21日

CPOL

4分钟阅读

viewsIcon

159857

downloadIcon

2530

在这里, 我们将尝试实现不同的服务行为以提高服务性能

介绍 

本文将解释如何通过各种 WCF 服务行为技术来实现吞吐量、可靠性和性能。大多数应用程序在可伸缩性和性能策略方面差异很大。WCF 服务行为提供了配置关键运行时行为的各种可能方式。我们将逐一介绍各种服务行为元素。

并发

默认情况下,WCF 服务一次只能处理一个请求,所有其他服务请求线程都将被排队并逐一处理。并发元素允许客户端同时发送多个请求,但服务实现应避免死锁等场景。

并发模式有三种。

  1. Single(默认):并发模式 Single 一次只允许一个服务实例。所有其他待处理请求将保持在队列中并逐一处理。每当新请求进来时,调度程序会在进入代码之前获取锁定。参见图 1。
  2. 图 1。

    ConcurrencyMode Single 定义如下:

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
    public class VisitorCount : IVisitorCount
    {
    } 
  3. Multiple:这允许并行请求,并通过为每个请求生成单独的线程来同时处理。参见图 2。
  4. 图 2

    以下是我们定义 ConcurrencyMode Multiple 的方式。

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class VisitorCount : IVisitorCount
    {
    }
  5. Re-entrant:每当客户端调用 WCF 服务时,都会为此客户端调用分配一个线程锁。让我们考虑一个场景,服务 1 调用外部服务 2。线程锁在整个服务调用完成之前不会被释放。因此,所有其他客户端请求都处于等待状态。Re-entrant 允许客户端在调用外部服务(服务 2)之前释放锁,这样其他客户端就可以使用服务 1 的功能,直到服务 2 处理完成。参见图 3。
  6. 图 3

    使用 ConcurrencyMode Reentrant 装饰服务类。

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class VisitorCount : IVisitorCount
    {
    }

并发模式可以增加服务方法中的通过量,从而提高整体服务性能。

实例上下文模式

WCF 实例决定对象的创建方式,并指代服务对象的生命周期。每当客户端发起请求时,运行时都会创建服务对象来提供响应。通过实例,我们可以控制此服务实例要保留多长时间。为此,我们使用三种实例模式。

  1. Per Call:在此场景中,所有对服务的调用都是无状态的。对于每个线程请求,都会创建一个新的服务实例。这适用于所有服务绑定。参见图 4。
  2. 图4。

    以下是我们定义 InstanceContext Mode Percall 的方式。

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,
           InstanceContextMode = InstanceContextMode.PerCall)]
    public class VisitorCount : IVisitorCount
    {
    }
  3. Per Session:服务对象的生命周期独立于客户端通道的生命周期,因此每次建立新的通信会话时都会创建一个新的服务对象,并在之后将其释放。每个客户端通道都会获得一个专用的服务实例,并且同一会话中的后续调用将由同一个服务对象处理。这是 Instancing Context 的默认值。它适用于除 basicHttpBindings 之外的所有绑定。参见图 5。
  4. 图5。

    以下是我们定义 InstanceContextMode PerSession 的方式。

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,InstanceContextMode = InstanceContextMode.PerSession)]
    public class VisitorCount : IVisitorCount
    {
    }
  5. Single:这将帮助我们全局共享数据。我们只能创建一个实例,并且后续调用将重用同一个实例。与 Per Session 类似,它适用于除 basicHttpBinding 之外的所有绑定。单例实例在服务主机关闭之前不会被释放。参见图 6。
  6. 图 6

    以下是我们定义 InstanceContext mode Single 的方式。

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,InstanceContextMode = InstanceContextMode.Single)]
    public class VisitorCount : IVisitorCount
    {
    } 

服务节流

WCF 允许您限制特定服务类型的负载。

这包括

  1. 最大并发会话数
  2. 最大并发调用数
  3. 最大并发实例数

每当这些值超过时,调用者将被添加到队列中并按 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 可以通过本文讨论的不同技术实现这些功能。

© . All rights reserved.