2012-02-17 12 views
5

¿Cómo puedo asegurarme de que un servicio WCF utiliza hilos de un ThreadPool para procesar los mensajes entrantes?¿WCF Service usa varios subprocesos para procesar las solicitudes entrantes?

En este momento invocación de método simple como 'return null;' tarda unos 45 segundos, mientras que otros están procesando solicitudes

Aquí es como he comentado mi clase de servicio:

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

Pero cuando estoy viendo el proceso en el administrador de tareas parece ser el uso de un número constante de los hilos. Incluso bajo carga.


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(); 
      } 
     } 

Aquí es mi comportamiento en servicio:

<?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> 

Aquí es cómo crear instancia de servicio:

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

InstanceContextMode = SIngle significa: tiene ** singleton ** - solo una única instancia de servicio. ¡No muy escalable! ConcurrencyMode = Múltiples medios, ese singleton puede dar servicio a múltiples solicitudes de servicio a la vez, pero también significa que su código de implementación del servicio ** debe ** ser 100% seguro para subprocesos, ¡no es una tarea fácil! Yo recomendaría usar 'InstanceContextMode.PerCall' y' ConcurrencyMode.Single' - de esa manera, cada solicitud de WCF entrante obtiene su propia instancia de una clase de servicio para manejar la solicitud. El tiempo de ejecución WCF puede manejar múltiples solicitudes concurrentes, su código es fácil de escribir. –

+0

posible duplicado: http: // stackoverflow.com/questions/1609703/wcf-concurrencymode-multiple-connection-best-practices-and-caching –

+1

Algunas veces InstanceContextMode = Single está bien; por ejemplo, cuando la API no tiene estado y solo reenvía la llamada. No es necesario tener más de una instancia del servicio alguna vez creada. Por ejemplo, llamadas a métodos que devuelven cosas como longitudes de cola o enviar datos a una cola de procesamiento ... Y escribir código 100% thread safe es el comportamiento estándar para algunos de nosotros, no todo el mundo es un script kiddie. – TomTom

Respuesta

5

InstanceContextMode y ConcurrencyMode son conceptos distintos pero que tienen un nivel de interacción - I blogged about this con cierta profundidad hace un tiempo

Las llamadas WCF se procesan en subprocesos de subprocesos de subprocesos IO. Suponiendo que no haya hecho algo como ConcurrencyMode.Single, InstanceContextMode.Single que serializará cada llamada al servicio, el administrador de subprocesos tratará de equilibrar la cantidad de subprocesos con la tasa de trabajo.

Si el número de solicitudes simultáneas puede ser atendido por 5 hilos, entonces esa es la cantidad que utilizará. Puede estar viendo que el grupo de subprocesos puede mantenerse al ritmo de la tasa de trabajo con la cantidad de subprocesos que puede ver. Puede utilizar con mucho más hilos que núcleos con efecto porque, siempre que los hilos no estén exclusivamente vinculados a la CPU, el sistema operativo puede obtener rendimiento al cambiar los hilos en la CPU cuando el hilo que se ejecuta previamente inicia IO. Si la CPU está completamente max'd a cabo a continuación, la heurística del gestor de subprocesos hará que sea reticente a añadir más hilos en el grupo de subprocesos

Sin embargo, hay un par de problemas potenciales:

  1. reunión basándose los enlaces pueden bloquearse en el lado del cliente mientras hay múltiples solicitudes de salida simultáneas a través del mismo proxy. No dice cómo está generando las múltiples solicitudes, por lo que puede ser un problema;
  2. También es posible que esté viendo la aceleración pateando ya que, antes de .NET 4, el número máximo predeterminado de solicitudes concurrentes era 16 y el número predeterminado de sesiones simultáneas era 10. Estos valores se han generado en .NET 4 pero usted no indique qué versión de .NET está usando
+0

Estoy en .NET4. En el sitio web de ASP .NET estoy creando un nuevo proxy cada vez que debo solicitar algo del servicio. Parece que estamos yendo en buen camino y esto puede ser un problema. – kseen

+0

Por favor, mira la actualización de mi publicación. – kseen

+0

¿está llamando cerca del proxy? –

Cuestiones relacionadas