Cuando se están escribiendo servicios web escalables, se necesita ser consciente de ciertas propiedades que aplican a nivel de la clase del servicio y que pueden afectar el desempeño WCF para despachar las solicitudes de un servicio.
InstanceContextMode y ConcurrencyMode
Estas propiedades son InstanceContextMode y ConcurrencyMode. En pocas palabras, InstanceContextMode controla cuando una nueva instancia de un servicio es creada y ConcurrencyMode controla la forma como las solicitudes pueden ser atendidas simultáneamente.
- InstanceContextMode = InstanceContextMode.PerSession (valor por defecto)
PerCall una instancia del servicio por cada llamado del método que haga el cliente, PerSession solo una instancia del servicio existe por cada sesión que posea el cliente WCF; Single, una única instancia del servicio es creada para todos los clientes.
- ConcurrencyMode = ConcurrencyMode.Single (valor por defecto)
La siguiente tabla muestra cuando una operación puede ser invocada mientras hay otra en progreso, dependiendo del ConcurrencyMode.
ConcurrencyMode |
Puede una nueva operación ser invocada? |
Single |
Nunca |
Reentrant |
Solamente cuando invoca otro servicio o un callback |
Multiple |
Siempre |
Formas de elegir,
InstanceContextMode.Percall
Considere este modo instancia en estas circunstancias:
- Si su servicio es sin estado.
- Si su servicio tiene código de inicialización de peso ligero (o ninguna). No aplica si por ejemplo, consulta una base de datos o crear gráficos de grandes objetos en memoria)
- Si su servicio es de un solo hilo de ejecución.
InstanceContextMode.PerSession (Por defecto)
Considere este modo de instancia en estas circunstancias:
- Si su servicio debe mantener algún estado entre las llamadas del mismo cliente.
- Si su servicio tiene código de inicialización de peso ligero (o ninguna).
Nota: De forma predeterminada, WCF utilizará PerSession siempre y cuando el cliente y el servicio se estén comunicando a través de un binding que admita estado de sesión. De lo contrario, el servicio se comportará como un servicio PerCall.
El desarrollador puede para eso, colocar una restricción utilizando la propiedad ServiceContractAttribute.SessionMode que se puede aplicar a su contrato de servicio. Con eso, si cualquier endpoint configurado para su servicio no soporta sesiones el servicio fallara al iniciar.
<ServiceContract(Name:="SampleDuplexHello", Namespace:="http://microsoft.wcf", CallbackContract:=GetType(IHelloCallbackContract), SessionMode:=SessionMode.Required)>
Public Interface IDuplexHello
<OperationContract(IsOneWay:=True)> _
Sub Hello(ByVal greeting As String)
End Interface
InstanceContextMode.Single
Considere este modo instancia en estas circunstancias:
- Si su servicio debe mantener algún Estado entre clientes.
- El servicio tiene código de inicialización caro. Es decir, al inicializar por cada cliente (PerSession) o por cada llamada (PerCall) sería demasiado costoso.
- No hay necesidad de escalar horizontalmente el servicio.
Tener en cuenta las consideraciones para balanceo de cargas en WCF en una granja de servidores.
Posibles escenarios
Para resumir unos ejemplos de posibles escenarios básicos, que suceden cuando 100 clientes simultáneamente invocan un método de un servicio.
- Escenario 1: InstanceContextMode.Single+ConcurrencyMode.Single
Resultado: 100 invocaciones secuenciales del método en un hilo.
- Escenario 2: InstanceContextMode.Single+ConcurrencyMode.Multiple
Resultado: N invocaciones concurrentes del método en N hilos, donde N es determinado por el service throttle MaxConcurrentCalls.
- Escenario 3:InstanceContextMode.PerCall+Any ConcurrencyMode
Resultado: N invocaciones concurrentes del método en N instancias del servicio, donde N es determinado por el service throttle MaxConcurrentInstances.
Link relacionado, http://kennyw.com/indigo/178