Pregunta

Tengo una aplicación cliente/servidor WCF que se comunica a través de HTTP utilizando WSHttpBinding.

Configuración del servidor:autohospedaje, utilizando el WCF estándar ServiceHost.Mi clase de servicio real se atribuye como:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
 InstanceContextMode = InstanceContextMode.PerSession, 
 UseSynchronizationContext = false)]

Configuración del cliente:usando un proxy de cliente generado por Visual Studio usando sincrónico llamadas de servicio (proxy.call_server_method bloques hasta que el servidor haya respondido por completo.)

Guión:Tengo una llamada a un método en particular que tarda 20 segundos en ejecutarse en el servidor.El cliente llama a este método en un hilo separado, por lo que no se retrasa y el ConcurrencyMode.Multiple significa que WCF también debería ejecutarlo en un hilo separado en el servidor.

Esta teoría está respaldada por el hecho de que cuando configuro mi aplicación para usar NetTcpBinding, todo funciona bien.

Problema:
Si configuro la aplicación para usar WSHttpBinding, entonces esta larga llamada al método hace que las solicitudes http hagan una "copia de seguridad".He verificado este comportamiento inspeccionando mis registros y depurando las solicitudes HTTP usando Fiddler.

Ejemplo:

  • El cliente inicia una solicitud de 20 segundos de duración en un hilo en segundo plano
  • El cliente inicia las solicitudes B y C en el hilo de primer plano
  • Las solicitudes B y C se envían al servidor, que no las procesa hasta que finaliza con la solicitud de 20 segundos de duración.

Pero a veces:

  • Solicitudes B y C no te envíen (ni siquiera aparecen en Fiddler) hasta que regresa la solicitud de 20 segundos (esto es raro).
    • Nota:configuración <add address="*" maxconnection="100"/> en app.config del cliente hizo que esto (pareciera) dejar de suceder.
  • La solicitud B se envía y recibe una respuesta inmediatamente, mientras que la solicitud C se retiene hasta que se completa la de 20 segundos (esto es raro)

Aquí hay una línea de tiempo de Fiddler que demuestra el problema:(haga clic para ver una versión más grande)

Como puede ver, todas las solicitudes están respaldadas en el servidor.Una vez que se completa la solicitud de 20 segundos, todas las respuestas llegan en masa, pero tenga en cuenta que hay algunas solicitudes que no lo son siendo retenido...

Entonces, Preguntas:

  • ¿Qué diablos está pasando aquí?¿Por qué funciona bien usando NetTcpBinding y no funciona usando WSHttpBinding?
  • ¿Por qué el comportamiento inconsistente?
  • ¿Que puedo hacer para arreglarlo?

Notas:

  • No está bloqueando el servidor.Establecí puntos de interrupción y usé !syncblk e informa constantemente que no hay bloqueos retenidos.
  • No es mi subproceso (de lo contrario, NetTcpBinding no debería funcionar)
  • Tengo <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" /> configurado en la aplicación.config del servidor
  • La llamada de 20 segundos solo está esperando un temporizador, no está atacando la CPU, el disco o la red.
  • Preferiría una solución que no implicara rediseñar la aplicación para usar llamadas asincrónicas...Es una gran cantidad de código heredado y realmente no quiero meterme con cosas que no entiendo.
¿Fue útil?

Solución 3

[Respuesta propia para mostrar a otros usuarios cuál fue nuestra solución final]

Al final, nunca logré resolver esto.
Nuestra solución final fue cambiar nuestra aplicación de WSHttpBinding a NetTcpBinding en producción; habíamos planeado hacerlo eventualmente de todos modos por razones de rendimiento.

Esto es bastante desafortunado, ya que deja una marca negra en <=> que puede o no estar justificada. Si a alguien se le ocurre una solución que no implique deshacerse de <=>, me encantaría saberlo

Otros consejos

Hay algo de acelerador fuera de WCF (una cosa .Net o Windows) que por defecto solo permite un máximo de dos conexiones HTTP salientes simultáneas. Desafortunadamente, no puedo recordar de por vida el nombre de la cosa (y lo que pondría en app.config o su aplicación para anularlo). Dado que no está viendo que las solicitudes salen del cliente, y que es solo HTTP, creo que está presionando & Quot; esa cosa & Quot ;. Seguiré buscando su nombre.

Actualización: Lo encontré - intente esto en el cliente (pero cambie el '2' a un número mayor):

<configuration>
  <system.net>
    <connectionManagement>
      <add address = "*" maxconnection = "2" />
    </connectionManagement>
  </system.net>
</configuration>

Vimos exactamente los mismos síntomas con un servicio JSON alojado en IIS / ASP.NET.

La causa raíz terminó siendo ASP.NET sincronizando las solicitudes, no WCF. Tuvimos que deshabilitar el estado de la sesión (en el nivel de la aplicación) para obtener métodos concurrentes de WCF.

Web.config: <system.web> <sessionState mode="Off" /> </system.web>

Tenga en cuenta que nuestro servicio utiliza webHttpBinding, no wsHttpBinding. Por lo tanto, no estoy seguro de si esto también resuelve el problema de Orión.

Creo que ha alcanzado el límite de protocolo y para solucionarlo debe modificar la configuración estándar en la máquina cliente:

http://support.microsoft.com/kb/183110

http://support.microsoft.com/kb/282402

Supongo que WSHttpBinding utiliza la configuración de WinINET al emitir las solicitudes.

Si cambia a BasicHttpBinding, ¿funciona?

Es así, suena como este es tu problema , aceleración de sesión, algo que me mordió el culo.

Considere usar ConcurrencyMode.Multiple en servicios por llamada para permitir concurrentes llamadas.

Lo olvido, ¿podría estar ordenando? Creo que tal vez RM sobre http conserva el orden, pero tal vez las sesiones de Tcp no (a menos que lo solicite explícitamente). ¿Hay un atributo en el Contrato de servicio que describió las sesiones ordenadas / no ordenadas (lo olvido).

No estoy seguro, pero a veces el problema con las llamadas simultáneas desde la aplicación Silverlight está relacionado con la administración de la conexión del navegador. Para mí, la solución fue poner eso en nuestro App.xaml.cs, método Application_Startup como se describe aquí: http://weblogs.asp.net/olakarlsson/simuallyly-calling-multiple-methods-on-a-wcf-service-from-silverlight

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top