2008-10-15 8 views
13

Estoy desarrollando una aplicación cliente/servidor en .Net 3.5 usando WCF. Básicamente, un servicio de cliente de larga ejecución (en varias máquinas) establece una conexión dúplex con el servidor a través de un netTcpBinding. Luego, el servidor usa el contrato de devolución de llamada del cliente para realizar ciertas oraciones a pedido, a las cuales el cliente responde de manera asíncrona (creo que es bastante estándar). Subclases la clase DuplexClientBase para manejar la mayor parte de la comunicación.¿Cómo restablezco automáticamente un canal dúplex si se produce una falla?

Desafortunadamente, cuando algo sale mal en cualquiera de los extremos (como una falla de la red, una excepción inesperada, etc.), el canal se bloquea/falla y fallan todas las operaciones subsiguientes. He superado esta limitación en canales no dúplex al crear una clase RecoveringClientBase que se activa automáticamente cuando el cliente ha fallado y vuelve a intentar la operación.

Entonces, mi pregunta es, ¿existe una forma establecida de determinar cuándo ha fallado un canal dúplex? ¿Dónde debo verificar esto, en el servidor o el cliente? En su defecto, ¿qué opciones tengo para garantizar que la conexión se restablezca?

Actualización: Estoy buscando algunos consejos específicos para los canales dúplex, donde el servidor puede intentar utilizar un canal de devolución de llamada que tuvo una falla. Por lo tanto, necesito algo que se vuelva a conectar/volver a suscribir inmediatamente cuando algo le pase al canal. En este momento, estoy escuchando el evento de cierre del canal y lo recreé si el estado no es Cerrado. De alguna manera funciona, pero se siente hacky ...

Respuesta

1

Nicolas Allen, del equipo de WCF tiene sugerencias para esto:

http://blogs.msdn.com/drnick/archive/2007/11/05/custom-transport-retry-logic.aspx

Su sugerencia es manejar esto a nivel de canal. El nivel de canal es un poco más agradable, ya que puedes conectarlo a la pila de cualquier enlace a través de comportamientos en lugar de requerir una clase base de cliente personalizada.

+3

¿Puede dar un ejemplo de esto? El artículo simplemente sugiere la idea, pero no da ninguna pista sobre la implementación. – Jacob

+0

+1 Jacob. ¿Alguien tiene información sobre cómo hacer que esto funcione? En la actualidad, tuve que recurrir al uso del proxy dinámico de Castle para implementar mi comportamiento de reconexión, pero prefiero agregar este comportamiento a través de Wcf. Estoy leyendo varios blogs Wcf, pero es impenetrable y no tengo ni idea de por dónde empezar, incluso las extensiones simples parecen requerir la creación de muchas clases y resmas de configuración, es desconcertante. –

+0

Agregue un controlador de eventos al evento Faulted a través de la interfaz explícita de ICommunicationObject en su servicio. En el controlador de eventos, cancela() el canal y crea un nuevo canal. – Jakub

0

He tenido algunos problemas similares, y para mí parece que estas llamadas de larga duración son más o menos incompatibles.

WCF parece estar diseñado para utilizarse en llamadas de corta duración. Los servicios, que se llaman, hacen algunas cosas pequeñas y terminan.

Refactoré mis aplicaciones en elementos más pequeños de trabajo. Entonces, en lugar de un artículo de larga ejecución, ahora tengo muchos artículos más pequeños. Por supuesto, a veces esto no es posible de lograr. Luego tuve que orar por conexiones de red estables (se pueden detectar excepciones, por lo que creo que las fallas no son realmente un problema).

3

He experimentado flakiness en sesiones largas (minutos-horas). No puedo estar seguro de que sea WCF, estoy bastante seguro de su nivel de red.

Estoy pensando en eliminar completamente el dúplex. Es una verdadera molestia intentar administrar el estado de la conexión.

Estoy pensando en alojar un punto final de servicio en el cliente para las operaciones que actualmente forman parte del contrato de devolución de llamada. El cliente se pondría en contacto con el servidor con los detalles del punto final, el servidor puede almacenarlos en algún lugar (persistente o donde sea). Cuando el servidor necesita contactar al cliente, abre una conexión con el cliente a través de los detalles del punto final oculto. Básicamente, convertir la conexión dúplex en 2 conexiones cliente-servidor.

No responde su pregunta, pero siento su dolor.

0

Creo que realmente debería escuchar sobre un evento con fallas. Puedes escucharlo en ambos extremos, creo que ya lo estás manejando, el final del servidor es OperationContext.Current.Channel.events.

No he encontrado una forma de reenviar un mensaje automáticamente porque su canal de devolución de llamada ya tiene una falla y aún no conoce el nuevo canal de devolución de llamada, pero necesita mantener estas llamadas en algún lugar hasta que el cliente se vuelva a conectar.

Los clientes recibirán una falla eventualmente y deben volver a realizar el protocolo de enlace con el servidor, que es el punto que el servidor debe enviar llamadas no enviadas.

Básicamente la única manera de recuperarse de un canal con falla/cerrado es reemplazarlo por uno nuevo, sin embargo, la parte más importante es que realmente debe detectar la desconexión a TIEMPO, he encontrado permitir una sesión confiable tiempo la mayor parte del caso. Alternativamente, puede enviar mensajes de latido en ambos extremos para "probar" el canal con fallas.

Cuestiones relacionadas