2010-02-17 9 views
6

Me he responsabilizado de continuar con el desarrollo de un sistema que originalmente no diseñé y no puedo preguntar a los diseñadores originales por qué se tomaron ciertas decisiones de diseño, ya que ya no están aquí. Soy un desarrollador junior en cuestiones de diseño, por lo que realmente no sabía qué preguntar cuando comencé el proyecto, que fue mi primer proyecto SOA/WCF.Preguntas de diseño de SOA y WCF: ¿Es este un diseño de sistema inusual?

El sistema tiene 7 servicios WCF, crecerá a 9, cada uno alojado en una consola independiente/servicio de Windows. Todos ellos son de instancia única y de un solo subproceso. Todos los servicios tienen el mismo OperationContract: exponen un método Register() y Send(). Cuando los servicios del cliente desean conectarse a otro servicio, primero llaman a Register(), luego si tienen éxito hacen todos el resto de su comunicación con Send(). Tenemos un DataContract que tiene un MessageType enum y una propiedad de contenido que puede contener otras "cargas útiles" de DataContract. Lo que hace el servicio con el mensaje está determinado por la enumeración MessageType ... todo viene a través del método Send() y luego se enruta a una instrucción switch ... Sospecho que esto es inusual

Register() and Send () son en realidad OneWay y Async ... TODOS los resultados de los servicios son devueltos a los servicios del cliente por un WCF CallbackContract. Creo que la resonancia para usar CallbackContracts es facilitar el modelo Publish-Subscribe que estamos usando. El problema no es que toda nuestra comunicación se adapte publicar-suscribir y utilizar CallbackContracts significa que tenemos que incluir los datos de origen en los mensajes de resultado devueltos para que los clientes puedan determinar para qué fueron originalmente los resultados devueltos ... otra vez los clientes tienen una instrucción switch para resolver qué hacer con los mensajes que llegan de los servicios basados ​​en el MessageType (y otros detalles integrados).

En términos de topología: los servicios forman "nodos" en un gráfico. Cada servicio ha codificado una lista de otros servicios a los que debe conectarse cuando se inicia, y no permitirá que los servicios del cliente se "registren" hasta que haya realizado todas las conexiones que necesita. Como ejemplo, tenemos un LoggingService y un DataAccessService. DataAccessSevice es un cliente de LoggingService y, por lo tanto, el servicio de DataAccess intentará registrarse con LoggingService cuando se inicie. Hasta que pueda registrar correctamente el servicio DataAccess, no permitirá que ningún cliente se registre en él. El resultado es que cuando el sistema se enciende como un todo, los servicios se inician en cascada. No veo esto como un problema, pero ¿es esto inusual?

Para hacer las cosas más complejas, uno de los requisitos del sistema es que los servicios o "nodos" no necesitan registrarse directamente entre ellos para enviarse mensajes entre sí, sino que pueden comunicarse a través de enlaces indirectos. Por ejemplo, supongamos que tenemos 3 servicios A, B y C conectados en una cadena, A puede enviar un mensaje a C a través de B ... utilizando 2 saltos.

En realidad, me encargaron esto y escribí el sistema de enrutamiento, fue divertido, pero me faltaba la pista antes de poder preguntar por qué era realmente necesario. Por lo que puedo ver, no hay ninguna razón por la cual los servicios no puedan conectarse directamente a los otros servicios que necesitan. Lo que es más, tuve que escribir un sistema de confiabilidad además de todo, ya que el requisito era tener mensajes confiables en los nodos en el sistema, mientras que con enlaces sencillos punto a punto WCF hace el trabajo de manera confiable.

Antes de este proyecto solo había trabajado en las aplicaciones de escritorio de winforms durante 3 años, no sabía nada mejor. Mis sospechas son que las cosas se complican demasiado con este proyecto: supongo que para resumir, mis preguntas son:

1) ¿Es inusual la idea de una topología de gráfico con mensajes saltando sobre enlaces indirectos? ¿Por qué no simplemente conectar servicios directamente a los servicios a los que necesitan acceder (que en realidad es lo que hacemos de todos modos ... No creo que tengamos ningún mensaje saltando)?

2) ¿Es inusual exponer solo 2 métodos en OperationContract y utilizar la enumeración MessageType para determinar qué mensaje es/qué hacer con él? ¿No debería un servicio WCF exponer muchos métodos con fines específicos en su lugar y el cliente elige qué métodos desea llamar?

3) Devuelve todas las comunicaciones a un cliente a través de CallbackContracts inusual. Sin duda, la solicitud de respuesta de sincronización o asyc es más simple.

4) ¿La idea de un servicio no permite que los servicios del cliente se conecten a ella (Registrarse) hasta que se haya conectado a todos sus servicios (para los cuales es cliente) un diseño de sonido? Creo que este es el único aspecto de diseño con el que estoy de acuerdo, me refiero a que DataAccessService no debe aceptar clientes hasta que tenga una conexión con el servicio de registro.

Tengo tantas preguntas WCF, más vendrán en los hilos posteriores. Gracias por adelantado.

Respuesta

6

Bueno, todo parece un poco extraño, de acuerdo.

Todos ellos son de instancia única y de rosca simple.

Eso definitivamente va a volver y provocar dolores de cabeza de rendimiento masivo - garantizados. No entiendo por qué alguien querría escribir un servicio WCF de Singleton para empezar (excepto en algunos casos extremos, donde tiene sentido), y si tiene un servicio WCF de singleton, para obtener un rendimiento decente, debe ser de subprocesos múltiples (lo cual es una programación complicada, y es por eso que casi siempre desaconsejo).

Todos los servicios tienen el mismo OperationContract: exponen una Registro() y método send().

Eso es bastante extraño, también. Entonces, ¿quién llama tendrá primero .Register(), y luego llamará a .Send() con diferentes parámetros varias veces? Diseño divertido, en serio ... La suposición de SOA es que diseñes tus servicios para que sean el modelo de un conjunto de funcionalidades que deseas exponer al mundo exterior, p. su CustomerService puede tener métodos como GetCustomerByID, GetAllCustomersByCountry, etc., dependiendo de lo que necesite.

Tener un solo método Send() con parámetros que definen lo que se está haciendo parece un poco ... inusual y poco intuitivo/claro.

¿Es esta idea de una topología de grafo con mensajes saltando sobre vínculos indirectos inusual?

No necesariamente. Puede tener sentido exponer una sola interfaz al mundo exterior, y luego utilizar algunos servicios internos de back-end para hacer el trabajo real. .NET 4 realmente introducirá un RoutingService in WCF que facilita este tipo de escenarios. No creo que este sea un gran no-no.

Está haciendo todas las comunicaciones a un cliente a través de CallbackContracts unusual.

Sí, inusual, frágil, desordenado - si alguna vez puede prescindir de él - vaya por ello.Si tiene llamadas en su mayoría sencillas, como GetCustomerByID - haga de ellas una llamada de Solicitud/Respuesta estándar - el cliente solicita algo (proporcionando una ID de cliente) y obtiene un objeto Customer como valor de retorno. ¡Mucho más simple!

Si tiene llamadas de larga duración, puede llevar minutos o más completarlas, entonces podría considerar las llamadas One-Way que simplemente depositan una solicitud en una cola, y esa solicitud se maneja más adelante. En general, aquí puede depositar la respuesta en una cola de respuesta que el cliente verifica o puede tener dos métodos de servicio adicionales que le dan el estado de una solicitud (¿ya está hecho?) Y un segundo método para recuperar el resultado (s) de esa solicitud.

Espero que eso te ayude a empezar.

+0

El método Send() toma un DataContract de ActionMessage, que tiene un campo de destino de cadena utilizado para enrutar a un destino y una referencia a otro tipo de DataContract como carga útil. Todos los DataContracts de carga útil heredan de un tipo base que tiene un campo enum MessageContentType, y esto es lo que utilizan los servicios para determinar si están interesados ​​en el procesamiento de datos que pasa por ellos antes de enrutar el mensaje. La cadena Destino puede especificar qué tipos de nodo de servicio desea que pase el mensaje. Gracias por la información. Marcaré como respuesta después de algunas otras respuestas. – MrLane

+0

Debo agregar que tenemos un SessionManagerService que es la "puerta de enlace" en el sistema para nuestros clientes de Silverlight. Originalmente enviaron mensajes a servicios de back-end a través de esta única puerta de enlace (utilizando su método Send) que enrutaba los mensajes al servicio de back-end correcto y enrutaba los mensajes a la instancia de cliente de navegador correcta desde esos servicios. Ahora, sin embargo, este no es el caso, se utilizan mensajes separados entre los Clientes <> SessionManager <> BackEndServices, por lo que todo es un solo salto. El SessionManager en realidad conserva el estado de UI y lo "empuja" a los clientes de Silverlight. – MrLane

5

Todos los servicios tienen el mismo OperationContract: exponen un método Register() y Send().

Su diseño parece inusual en algunas partes, exponiendo especialmente solo dos operaciones. No he trabajado con WCF, usamos Java. Pero, en mi opinión, el objetivo general de los servicios web es exponer las operaciones que sus socios pueden utilizar.
Tener solo dos operaciones me parece un diseño extraño. Generalmente expone su API usando WSDL. En este caso, el WSDL no agregaría nada de valor a los socios, a menos que tenga mucha documentación. En general, el nombre de la operación debe ser autoexplicativo. En este momento, su sistema no puede ser utilizado por socios sin tener conocimiento interno.

Está haciendo todas las comunicaciones a un cliente a través de CallbackContracts inusual. Sin duda, la solicitud de respuesta de sincronización o asyc es más simple.

De acuerdo con usted. Async solo debe usarse para procesos de larga ejecución. Async agrega la sobrecarga de la correlación.

Cuestiones relacionadas