¿Destruir o mantener los proxies de WCF?

 


Desde el punto de vista de la escalabilidad, en teoria, es mejor crear y destruir el proxy, si es que hay afinidad entre número de clientes y número de proxies. Tanto es así que de hecho los proxies son IDisposable. Pero desde el punto de vista del rendimiento, sin duda, crear y destruir el proxy tiene un coste bastante alto según mi experiencia y algunas pruebas no muy formales que he realizado.

En resumen, la idea es clara, si no sabes cuantos clientes vas a tener, cada proxy consume recursos del servidor, y por tanto esto afecta a la escalabilidad (el numero de clientes que puedes atender será menor). Pero también es cierto que si el número de proxys es finito no interesa abrir y cerrar los proxies, por el coste que tiene. La idea subyacente es la misma que con las conexiones de bases de datos, de hecho, un pool de proxies es algo que he leído que van a añadir a WCF en próximas versiones.

Este problema además se enmaraña un poco más si tenemos en cuenta la seguridad. Si creamos el proxy en cada ocasión también incurrimos en el coste de negociar un token de seguridad cada vez.

Si nos decantamos por utilizar un único proxy para todas las invocaciones, manteniéndolo abierto durante toda la vida del cliente, el problema de que surge es que, en algún momento puede haber contención, pero con las redes actuales es difícil que esto ocurra. Un solo socket es capaz de atender miles de peticiones WCF sobre todo si los mensajes que intercambiamos son óptimos.

Quien decide si mantener o no los proxies es el cliente, pero también hemos de tener en cuenta que las opciones de Throtlling limitan el número de sesiones concurrentes a un máximo de 10 por defecto. Si nos decidimos por mantener los proxies abiertos y estamos usando sesiones este valor va a limitar el número de conexiones, y por tanto hemos de cambiar el valor por defecto de la propiedad MaxConcurrentSessions.

También conviene recordar que si usamos un binding basado en TCP, por defecto vamos a tener una sesión implícitamente creada por cliente. De hecho usando como binding el netTcpBinding, no vamos a poder especificar que no queremos sesión, porque si en nuestro ServiceContract establecemos SesionMode a None, obtendremos el error ‘No se puede iniciar el servicio. System.InvalidOperationException: Contract does not allow Session, but Binding ‘NetTcpBinding’ does not support Datagram or is not configured properly to support it.’ al intentar arrancar el host del servicio.

Existe la alternativa de crearse un ‘custom binding’ que use TCP y que no requiera sesión tal y como está descrito aquí, pero creo que no tiene mucho sentido, que se trata de una optimización prematura. Las sesiones en sí consumen muy pocos recursos, según las pruebas que hice sobre este tema en su momento. Esto tiene toda la lógica, lo que consume recursos es lo que tu mantienes dentro de la sesión, y el hecho de poner y sacar cosas en la sesión, no la sesión en si, que es poco más que un simple diccionario. Tener sesiones vacias es algo que no va a afectar demasiado a la escalabilidad o el rendimiento de nuestro servicio.

Espero que esto que comento os ayude a tomar una decisión.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *