2012-02-17 7 views
5

Jak mogę się upewnić, że usługa WCF używa wątków z ThreadPool do przetwarzania przychodzących wiadomości?Czy usługa WCF korzysta z wielu wątków do przetwarzania przychodzących żądań?

W tej chwili proste wywołanie metody, takie jak "return null;" trwa około 45 sekund, podczas gdy kolejne wnioski są przetwarzanie

Oto jak ja adnotacją moją klasę usług:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] 
    public partial class MyService : IMyService { 
... 
} 

Ale kiedy patrzę na proces w Menedżerze zadań wydaje się być za pomocą stałej liczby wątków. Nawet pod obciążeniem.


public ActionResult SelectDatabase(string param) 
     { 
      if (!String.IsNullOrEmpty(param)) 
      { 
      try 
      { 
       MyServicece svc = new MyService(); 
       Database[] dbsArray = svc.GetDatabases(param); 
       if (depsArray != null) 
        ViewData["depsArray"] = depsArray; 

       return View(); 
      } 
      catch (Exception exc) 
      { 
       // log here     
       return ActionUnavailable(); 
      } 
     } 

Oto moje zachowanie usługa:

<?xml version="1.0"?> 
<configuration> 
    <runtime> 

    </runtime> 
    <system.net> 
    <connectionManagement> 
     <add address="*" maxconnection="100" /> 
    </connectionManagement> 
    </system.net> 
    <system.serviceModel> 
    <diagnostics performanceCounters="Default" /> 
    <bindings>  
     <netTcpBinding> 
     <binding sendTimeout="00:02:00" receiveTimeout="00:02:00" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"> 
      <security mode="None">   
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="CrossDomainServiceBehavior"> 
      <webHttp /> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="MyService.MyServiceBehavior"> 
      <serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" maxConcurrentSessions="100" /> 
      <dataContractSerializer maxItemsInObjectGraph="2147483646"/> 
      <serviceMetadata httpGetEnabled="false" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service behaviorConfiguration="MyService.MyServiceBehavior" name="MyService.MyService"> 
     <endpoint address="MyService" binding="netTcpBinding" contract="AService.IAServ" isSystemEndpoint="false" /> 
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> 
     </service> 
     <service behaviorConfiguration="MyService.MyServiceBehavior" name="MyService.MyServiceAdmin"> 
     <endpoint address="MyServiceAdmin" binding="netTcpBinding" contract="MyService.IMyServiceAdmin" isSystemEndpoint="false" /> 
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />   
     </service> 
    </services> 
    </system.serviceModel> 
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> 

Oto jak utworzyć wystąpienie usług:

ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(String.Format("net.tcp://{0}/", _bindAddress))); 
      myserviceHost.Open(); 
      Console.WriteLine(myserviceHost.BaseAddresses[0]); 
+3

InstanceContextMode = SIngle oznacza: masz ** singleton ** - tylko jedną instancję usługi. Niezbyt skalowalne! ConcurrencyMode = Wiele oznacza, że ​​singleton może obsługiwać wiele zgłoszeń serwisowych jednocześnie - ale oznacza to również, że twój kod implementacji usługi ** musi ** być w 100% bezpieczny dla wątków - nie jest to łatwe zadanie! Polecam używanie 'InstanceContextMode.PerCall' i' ConcurrencyMode.Single' - w ten sposób każde przychodzące żądanie WCF otrzymuje własną instancję klasy usług do obsługi żądania. Środowisko wykonawcze WCF może obsługiwać wiele jednoczesnych żądań, twój kod jest łatwy do napisania. –

+0

możliwy duplikat: http: // stackoverflow.com/questions/1609703/wcf-concurrencymode-multiple-connection-best-practice-and-caching –

+1

Czasami InstanceContextMode = Single jest ok - na przykład, gdy interfejs API jest bezstanowy i tylko przekazuje dalej połączenie. Nie ma potrzeby tworzenia więcej niż jednej instancji usługi kiedykolwiek utworzonej. Na przykład wywołania metod, które zwracają takie elementy, jak długości kolejki lub przesyłanie danych do kolejki przetwarzania ... A pisanie 100% wątku bezpiecznego kodu jest standardowym zachowaniem dla niektórych z nas - nie każdy jest skrypciarzem. – TomTom

Odpowiedz

5

InstanceContextMode i ConcurrencyMode są odrębne koncepcje, ale które mają poziom wzajemnego oddziaływania - I blogged about this w pewnej głębi jakiś czas wstecz

Połączenia WCF są przetwarzane na wątkach wątków IO. Zakładając, że nie wykonałeś czegoś takiego, jak ConcurrencyMode.Single, , które będzie serializować każde wezwanie do usługi, menedżer wątków spróbuje zrównoważyć liczbę wątków z szybkością pracy.

Jeśli liczba równoczesnych żądań może być obsługiwana przez 5 wątków, to tyle z nich będzie korzystać. Być może zauważysz, że wątek może nadążyć za tempem pracy z liczbą wątków, które możesz zobaczyć. Z powodzeniem można używać więcej wątków niż rdzeni z efektem, ponieważ tak długo, jak wątki nie są wyłącznie związane z procesorem, system operacyjny może uzyskać przepustowość poprzez przełączanie wątków na procesor, gdy poprzednio uruchomiony wątek rozpoczyna IO. Jeśli procesor jest całkowicie max'd się wówczas heurystyki zarządcy puli wątków uczyni to niechętnie dodać więcej wątków w puli wątków

Jednakże, istnieje jeszcze kilka potencjalnych problemów:

  1. sesji opartej powiązania mogą blokować po stronie klienta, podczas gdy istnieje wiele równoczesnych żądań wychodzących za pośrednictwem tego samego serwera proxy. Nie mówisz, jak generujesz wiele próśb, więc może to być problem;
  2. Możesz również zobaczyć, jak dławienie się wrzuca, ponieważ przed .NET 4 domyślna maksymalna liczba równoczesnych żądań wynosiła 16, a domyślna liczba równoczesnych sesji wynosiła 10. Te wartości zostały podniesione w .NET 4, ale nie masz powiedz, która wersja .NET używasz
+0

Jestem na .NET4. Na stronie ASP .NET tworzę nowy serwer proxy za każdym razem, gdy powinienem poprosić o coś z usługi. Wygląda na to, że idziemy właściwą drogą, a to może być problem. – kseen

+0

Proszę zobaczyć moją aktualizację postu. – kseen

+0

Czy dzwonisz w pobliżu proxy? –