我正在设计一个我所有客户将连接的2 WCF服务。其中一项服务将是通知服务。
我希望每个客户端连接到服务,订阅它然后使用双工Callback接口接收通知(该服务将在客户端中激活'Notify'操作。)
这是我的设计理念:
我的问题是:当每个客户端连接到我的服务时,我将根据我的数据库中的“用户”表进行验证(我将使用UserNamePasswordValidator并实现'验证'功能)。
要求:每个用户都需要根据数据库中定义的规则接收不同的通知,但它们都使用相同的合同。
例如:
数据库中的我的服务将有一个工作线程,用于检测数据库中的更改(新产品已插入数据库)。
然后应该遍历所有连接的客户端 - 并且每个客户端都会向他发送新产品的通知,只要它与客户的通知请求相匹配。
再次 - 所有客户端都会收到相同类型的更新(新产品),但每个客户端应根据数据库中的规则接收不同的产品。
我认为实现此方法的一种方法是使用 Singleton 服务,该服务包含以下列表:
这种方式 - 每次工作线程检测到新产品时,它都会遍历此列表并向有需要的人发送通知。 这种方法的问题在于,为了拥有一个全局客户列表 - 我需要将服务作为Singlton,对吗?
第二种方法是......嗯......我不知道如何从工作线程访问连接到服务的客户端列表......
我想我遇到的主要问题是每个客户都可能想要通知他不同类型的产品。含义 - pub \ sub方法在这里不太好,因为我的场景要求服务了解客户端。
关于如何解决这个令人头疼的问题的任何建议?
答案 0 :(得分:2)
以双工通信的方式,您需要维护从服务器到客户端打开的TCP通道才能发送通知。
客户端是发起与服务器连接的人,您需要保持此连接打开,如果此连接丢失,您不能(不应该)启动从服务器到客户端的连接,因为客户端可以在NAT后面,有防火墙等。
所以在任何方面都必须在服务器端有一些静态(单例)对象来保持客户端连接列表,认为这不一定是WCF服务。您可以依赖将此对象注入服务构造函数。
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);
}
}
答案 1 :(得分:0)
我想说的是以下内容。
创建一个wcf服务,每个客户端都会调用该服务来订阅过滤器一次。 wcf服务本身只是将数据添加到数据库,并在数据存储中包含客户端名称和过滤器信息等信息。然后你的工作线程将在一个窗口服务中,它将简单地轮询你的数据库以获取数据,当数据可用时,它将从订阅表中读取。然后它会将数据推送到每个客户端的队列,这些客户端可能是像rabbitmq这样的共享队列服务器。
在客户端假设它是一个基于窗口的应用程序,它将简单地通过在队列中查找具有自身名称(client1,e.t.c)的数据来轮询rabbitmq队列服务器以查找它。