2013-04-21 98 views
1

我們在IIS上設計一個WCF Web服務,具有以下特點:選擇一個WCF實例管理

  • 對象的創建是比較重(大約需要500毫秒),因爲它需要編寫一個文件
  • 任何國家在創建對象後需要保留
  • 來自客戶端的每次呼叫平均需要150-200毫秒。這個調用包括髮送UDP請求到另一臺服務器並接收響應。
  • 我們預計約有30個同時進行的客戶。它可能增長到50個客戶。在最壞的情況下(50個客戶端),我們需要一個包含10個對象實例的池來處理這個負載。

您會推薦3個實例管理上下文(PerCall,PerSession,Single)中的哪一個?爲什麼?哪個實例使我們能夠管理可以完成這項工作的可用對象池?

回答

3

開箱即用,WCF不支持服務對象池。您需要自定義IInstanceProvider。在這種情況下,WCF上下文模式將定義WCF何時從IInstanceProvider請求新對象,並且IInstanceProvider行爲將管理該池。根據使用情況將服務設置爲PerInstance或PerSession可能有意義。

如果您在您的實現使用依賴注入容器,如Castle WindsorStructureMap,或MS企業庫的Unity那麼你可以使用容器的exsiting IInstanceProvider與彙集的生活方式。所有這些容器都是合理的(儘管我個人對管理對象池沒有多少經驗)。

我個人選擇的容器是溫莎城堡。在這種情況下,您可以使用Windsor的WCF Integration Facilitypooled lifestyle

這是一個使用Castle.Facilites.WcfIntegraion NuGet包的快速測試控制檯程序。

using Castle.Facilities.WcfIntegration; 
using Castle.MicroKernel.Registration; 
using Castle.Windsor; 
using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.Threading.Tasks; 

namespace WCFWindsorPooledService 
{ 
    [ServiceContract] 
    public interface ISimple 
    { 
     [OperationContract] 
     void Default(string s); 
    } 

    public class SimpleService : ISimple 
    { 
     private static int CurrentIndex = 0; 
     private int myIndex; 

     public SimpleService() 
     { 
      // output which instance handled the call. 
      myIndex = System.Threading.Interlocked.Increment(ref CurrentIndex); 
     } 

     public void Default(string s) 
     { 
      Console.WriteLine("Called #" + myIndex); 
      System.Threading.Thread.Sleep(5); 
     } 
    } 

    class PooledService 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("\n\n" + System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.Name); 

      // define mapping of interfaces to implementation types in Windsor container. 
      IWindsorContainer container = new WindsorContainer(); 
      container.AddFacility<WcfFacility>() 
        .Register(Component.For<SimpleService>().LifeStyle.PooledWithSize(2, 5)); 

      var host = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory() 
                  .CreateServiceHost(typeof(SimpleService).AssemblyQualifiedName, 
                       new Uri[] { new Uri("http://localhost/Simple") }); 
      host.Open(); 

      ChannelFactory<ISimple> factory = new ChannelFactory<ISimple>(host.Description.Endpoints[0]); 

      List<Task> tasks = new List<Task>(); 
      for (int i = 0; i < 20; i++) 
      { 
       tasks.Add(Task.Run(() => 
       { 
        ISimple proxy = factory.CreateChannel(); 
        proxy.Default("Hello"); 

        ((ICommunicationObject)proxy).Shutdown(); 
       })); 
      } 

      Task.WaitAll(tasks.ToArray()); 

      ((ICommunicationObject)host).Shutdown(); 
      container.Dispose(); 
     } 
    } 

    public static class Extensions 
    { 
     static public void Shutdown(this ICommunicationObject obj) 
     { 
      try 
      { 
       obj.Close(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Shutdown exception: {0}", ex.Message); 
       obj.Abort(); 
      } 
     } 
    } 
} 

我不會假裝理解城堡如何管理游泳池的所有規則,但游泳池顯然正在使用。輸出是:

PooledService 
Called #1 
Called #5 
Called #2 
Called #3 
Called #4 
Called #6 
Called #7 
Called #8 
Called #7 
Called #4 
Called #2 
Called #5 
Called #1 
Called #10 
Called #6 
Called #9 
Called #4 
Called #7 
Called #1 
Called #9 
+0

@ ErnieL:謝謝你的指導。就線程問題而言,看起來有效的是進入IIS管理器,選擇應用程序池高級設置,並增加過程模型最大工作者進程。我仍然有關於使用哪個實例管理的問題。 – 2013-04-30 11:32:36

+0

@ Mr.T。增加工作進程的數量只會創建更多的進程來處理請求。它不會爲您提供可重用的服務實例池。會話狀態也不在工作進程之間共享。從你的問題來看,你是否正在使用會話還不清楚。如果您需要會話,請使用PerSession。如果不是,請使用PerCall。 – ErnieL 2013-05-01 16:15:11