我有一个WCF服务,所有客户端都连接到该服务以获取通知\提醒(使用他们实现的CALLBACK接口)。目前,WCF服务是自托管的,但计划是将其托管在Windows服务中。
WCF服务具有“发布”,“订阅”和“取消订阅”操作。
我需要有一个后台工作线程某种类型的查询SQL服务器数据库表[每隔XXX分钟],并查找某些“提醒”行。一旦找到它们 - 它应该通知所有连接的客户端。
我想到了实现这个目标的两种方法。
方法A:
有一个单独的EXE项目(不要让它成为一个控制台,那应该是什么 - 一个Windows服务?),它将启动并运行一个后台线程。后台线程将作为其客户端之一连接到“Reminder”服务。后台线程将轮询数据库,一旦找到某些内容 - 它将向WCF服务发送'发布'消息,这将使WCF服务向所有订阅的客户端发送提醒。
方法B:
以某种方式使后台线程在 WCF服务项目中运行 ,当它在数据库中检测到新的提醒行时,以某种方式让它“发出信号”WCF服务使用该信息,然后WCF服务将此信息发送给所有订阅的客户端。
哪种方法更好?还有其他建议吗?
答案 0 :(得分:6)
如果这是一个长时间运行的过程,Windows服务是一个完美的解决方案。 您的主要Win Service线程将轮询数据库,将结果排入某种供应商/消费者线程安全集合。
您可以在win服务中托管WCF服务,然后可以使用(删除)队列中的任何结果并按照请求将它们传递回客户端(调用WCF将在他们自己的线程中进行)
这是一种非常常见的架构,并不难实现。
答案 1 :(得分:1)
方法A:
如果您要创建两个单独的主机(即一个用于WCF服务,一个用于“轮询”服务),那么您实际上只有一个选项可以使它完全正常工作。
Windows服务通信非常有限(没有服务端点的帮助,例如WCF)。因此,如果您要在Windows服务中托管“轮询”服务,则必须将其与WCF服务结合使用。
然后可以在一个Windows服务中同时托管这两个服务,并通过手动实例化WCF主机并将“轮询”服务传递给构造函数。
protected override void OnStart(string[] args)
{
//...
// This would be you "polling" service that would start a background thread to poll the db.
var notificationHost = new PollingService();
// This is your WCF service which you will be "self hosted".
var serviceHost = new WcfService(notificationHost);
new ServiceHost(serviceHost).Open();
//...
}
这远非理想,因为您需要通过两个服务之间的事件进行通信,而且您的WCF服务必须在单例模式下运行才能进行手动实例化...所以这会让您... ...
方法B:
如果您要在WCF服务中托管“轮询”服务,那么您将遇到许多问题。
方法C:
鉴于方法A和方法B的缺点,最好的解决方案是托管两个独立的WCF服务。
我们的想法是,您的常规服务在收到订阅者后将打开与您的轮询服务的新连接或使用现有服务(取决于您配置会话的方式)并等待回复。您的轮询服务是一个长期运行的WCF服务,它会轮询您的数据库并将通知发布给其订阅者(即其他WCF主机)。
<强>优点:
<强>缺点: