2012-04-24 8 views
5

Estoy diseñando 2 servicios de WCF a los que se conectarán todos mis clientes. Uno de estos servicios será un servicio de notificaciones.WCF Duplex: ¿envía notificaciones diferentes a cada cliente?

Me gustaría que cada cliente se conecte al servicio, suscríbase y luego reciba notificaciones, utilizando una interfaz de devolución de llamada dúplex (el servicio activará la operación 'Notificar' en los clientes).

Esta es mi idea del diseño:

enter image description here

Mi pregunta es: Cuando cada cliente se conecta a mi servicio, voy a validarlo contra la mesa 'Usuarios' en mi base de datos (Me va a utilizar una UserNamePasswordValidator e implementar la función 'Validar').

Requisito: cada usuario necesita recibir notificaciones diferentes, basadas en reglas definidas en la base de datos, pero todas usan el mismo contrato.

Por ejemplo:

John Smith 's reglas en la base de datos podría ser: Enviar notificación a todos los nuevos productos que tienen un precio de más de 100 dólares.

Las normas de Jane Doe en la base de datos pueden ser: Notificarme en todos los productos nuevos que sus nombres comienzan por 'JA'.

Las reglas de Jim Jabra en la base de datos pueden ser: Notificarme sobre todos los productos nuevos que son del tipo 'Alimentos'.

Mi servicio tendrá un hilo de trabajo que detecta un cambio en la base de datos (se insertó un nuevo producto en la base de datos).

Debería recorrer todos los clientes conectados y para cada cliente enviarle una notificación del nuevo producto, solo si coincide con las solicitudes de notificación del cliente.

Nuevamente, todos los clientes reciben el mismo tipo de actualización (productos nuevos), pero cada cliente debe recibir diferentes productos según la regla en la base de datos.

Un enfoque pensé para poner en práctica este sería el uso de un servicio de Singleton, que contiene una lista de:

  • cliente Enpoint
  • objeto de usuario (a partir de la base de datos)

De esta forma, cada vez que el hilo de trabajo detecta un nuevo producto, pasa por encima de esta lista y envía notificaciones a quien lo necesite. El problema con este enfoque es que para tener una lista global de clientes, necesito tener el servicio como Singlton, ¿verdad?

El segundo enfoque sería ... bueno ... no tengo otra idea de cómo puedo acceder a una lista de clientes conectados al servicio de un subproceso de trabajo ...

supongo que la El principal problema que tengo es que cada cliente puede desear que se le notifiquen diferentes tipos de productos.Significado: el método pub \ sub no es tan bueno aquí, porque mi escenario requiere que el servicio sepa sobre los clientes.

¿Alguna sugerencia sobre cómo puedo resolver este dolor de cabeza?

+0

¿Has pensado en utilizar una cola? Donde cada uno de sus clientes se conecta a la cola y sondea para obtener datos según estén disponibles. Y simple, el servicio WCF debe ser un servicio para suscribirse a datos. Luego, en su cadena de trabajo, envíe datos a la cola del cliente cuando los datos pertenezcan a ellos. – rpgmaker

+0

¿cómo resolvería una cola mi problema exactamente? ¿Qué quieres decir con 'el servicio wcf será un servicio para suscribirse'? ¿tienes una muestra o ejemplo que pueda mirar? –

+0

Mi respuesta está por debajo de – rpgmaker

Respuesta

2

De cualquier manera con la comunicación dúplex, necesita mantener el canal TCP abierto desde el servidor al cliente para poder enviar notificaciones.

El cliente es el que inicia la conexión al servidor, y necesita mantener esta conexión abierta; si se pierde esta conexión, no puede (no debería) iniciar la conexión de servidor a cliente, porque el cliente puede estar detrás de NAT , tiene firewall, etc.

De modo que debe haber algún objeto estático (singleton) en el servidor que mantenga la lista de conexiones de los clientes, aunque este no es necesariamente el servicio WCF. Puede la dependencia de inyectar este objeto en el constructor del servicio.

public class ProductRepository 
{ 
    private EventAggregator eventAggregator; 

    public void Add(Product product) 
    { 
     //... 
     eventAggregator.Publish(new NewProductEvent(product)) 
    } 
} 
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] 
public class EventPublishingService 
{ 
    private IClientCallback client; 
    private EventAggregator eventAggregator; 
    private Func<Product, bool> predicate; 

    public EventPublishingService(...) 
    { 
     eventAggregator.Subscibe<NewProductEvent>(OnNewProduct); 
    } 
    private void OnNewProduct(NewProductEvent e) 
    { 
     if (predicate(e.Product)==true) client.Notify(e.Product); 
    } 

    public void Subscribe() 
    { 
     client = OperationContext.Current.GetCallbackChannel<IClientCallback>() 
     var user = ServiceSecurityContext.PrimaryIdentity; 
     predicate = GetFilterForUser(user); 
    } 
} 
+0

¿Quiere decir que necesito un servicio singleton e inyectar el hilo de trabajo en segundo plano al servicio en su constructor? ¿No debería hacer lo contrario? ¿Inyectar el servicio en el constructor del trabajador de fondo? –

+0

@JohnMiner, No estoy seguro de por qué necesita trabajadores de fondo. He escrito un pequeño ejemplo. –

+0

guau, gracias por el extenso ejemplo! Trataré de explicar por qué necesito un hilo de trabajo. Hay una tabla en la base de datos que contiene las reglas para cada usuario, qué productos quiere. USER1 tiene una regla que dice que quiere ser notificado de productos con "price> 50". USER2 tiene una regla que dice que quiere ser notificado de productos con "precio> 30 y precio <70". USER3 tiene una regla que dice que quiere productos con "FOOD" en su nombre. Continuar en el próximo comentario –

0

Lo que quise decir es lo siguiente.

Crea un servicio wcf que cada cliente llamará para suscribirse a filtros una vez. El servicio wcf simplemente agregará datos a la base de datos e incluirá información como el nombre del cliente y la información de filtros en el almacén de datos. Luego su hilo de trabajo que estará en un servicio de ventana que simplemente sondeará su base de datos y, cuando los datos estén disponibles, leerá de las tablas de suscripción. A continuación, enviará los datos a la cola de cada cliente, que podría ser un servidor de colas compartido como rabbitmq.

En el lado del cliente, suponiendo que es una aplicación basada en la ventana, simplemente sondeará el servidor de la cola rabbitmq para buscar los datos buscándolo en la cola con el nombre de sí mismo (client1, e.t.c).

Cuestiones relacionadas