Para poder realizar un buen diseño de un servicio WCF me parece crítico conocer en profudidad las propiedades InstanceContextMode y ConcurrencyMode, y establecer los valores adecuados en el ServiceBehavior en una fase temprana si no queremos llevarnos sorpresas posteriormente.
Elegir uno u otro valor puede afectar a factores como la escabilidad o incluir necesidades de sincronización en el acceso a la información.
InstanceContextMode permite delimitar el número de instancias que se crean en el servidor y cómo se comportan éstas, mientras que ConcurrencyMode permite controlar los hilos que pueden levantarse.
InstanceMode.PerSession
Se crea una instancia nueva cuando una aplicación cliente invoca por primera vez a una operación del servidor y permanece activa hasta que el cliente cierra la conexión, permaneciendo activa hasta entonces para atender otras peticiones del mismo cliente. Al período desde que se crea hasta que se destruye la instancia es a lo que se llama sesión. ( diferentes sesiones no pueden compartir información entre ellas)
Por defecto sólo procesará una petición a la vez, por lo que si hay una petición en curso y llega otra, la segunda tendrá que esperar a que termine la primera. ( o dar un time-out ).
Este funcionamiento se puede cambiar usando la propiedad ConcurrencyMode, pasando de ConcurrencyMode.Single a Multiple, permitiendo de esta manera que pueda haber múltiples hilos atendiendo peticiones.
En este caso de tener múltiples hilos usando la misma sesión será responsabilidad del desarrollador encargarse de que el código sea thread-safe.
[ServiceBehavior(InstanceContextMode = InstanceMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class Service : IService
{
......
InstanceMode.PerCall
Crea una instancia del servicio cada vez que el cliente invoca una operación. La instancia se destruye cuando se completa la operación.
De cara a la escalabilidad este modo ofrece mejor rendimiento que el anterior, ya que libera recursos entre llamada y llamada. Por ejemplo, si suponemos 100 clientes usando PerSession, el servidor tendrá que tener 100 instancias. Si sólo uno está activo y los otros 999 están tomándose un café, el servidor seguirá teniendo 100 instancias aunque sólo una se esté usando. Si se estuviese usando PerCall, el servidor sólo tendría una instancia.
Lógicamente, la desventaja de usar PerCall es que si necesitamos guardar estado entre sesión y sesión la cosa se complica y toca buscar alternativas más costosas de implementar.
InstanceMode.Single
Crea una instancia la primera vez que el cliente invoca una operación del servidor y permanece viva para atender todas las peticiones del mismo cliente y lo que es más importante, también todas las peticiones de otros clientes que se conecten al mismo servicio. La instancia se destruye cuando la aplicación que hace de host se detiene.
La principal ventaja, a parte de un menor consumo de recursos, es que todos los usuarios pueden compartir de una forma muy sencilla información ya que usan la misma instancia. Esta también se puede considerar su principal problema o desventaja...
Si utilizas este modo es importante establece ConcurrencyMode.Multiple, porque sino todas las peticiones de todos los clientes se estarán haciendo una detrás de otras y podrá haber muchas peticiones que den time-out.
Adicionalmente a estas propiedades es importante no olvidarse de configurar los parámetros de service throttling que ya comentaba anteriormente Oskar Alvarez.