问题 良好的C#.NET解决方案来管理频繁的数据库轮询


我目前正在开发一个c#.NET桌面应用程序,它将通过WCF和WCF数据服务通过Internet与数据库进行通信。应用程序中有许多位置可能需要在某个时间间隔内刷新。最简单的解决方案是将这些区域放在计时器上并重新查询数据库。但是,由于成千上万的客户端连接到服务层并因此连接到数据库,因此这些操作对于服务器而言将非常昂贵。

我考虑的是创建一个由客户端轮询的RSS源,并让客户知道何时需要更新这些特定区域。 RSS源将由一个服务进行管理,该服务轮询数据库以进行更改,或者迭代通过客户端发出的WCF请求排队的项列表。

我还考虑过从客户端到服务器创建一些直接和连续的连接,但我不确定从客户端打开哪些出站防火墙端口。我可能只能依靠端口80/443。

所以我的问题是人们成功解决这个问题的解决方案是什么?有人做过RSS吗? Microsoft Sync Services?客户端和服务器之间通过WCF通过某个保存端口进行双向通信?

任何想法都非常感谢。


3997
2017-12-07 16:08


起源



答案:


我想你可能想要采用两种方法的组合。首先,你可以使用 长期民意调查 从客户端到服务器,以便服务器可以在客户端感兴趣的更改发生时立即通知客户端。

在ASP.NET中很好地处理上述建议的新技术是 SignalR。这可以处理长轮询的大部分细节(或者尽可能使用WebSockets),因此您不必担心它。

其次,基于此问题中的标记,您似乎正在使用SQL Server。您可以在感兴趣的表上使用数据库通知,以便在发生更改时让数据库通知您的服务。然后,这可以触发服务通过长轮询连接通知客户端有关更改的信息。你可以使用 的SqlDependency 类。

我确信还有其他方法,但这可能会很好地扩展,因为您只有一个服务获取通知,然后将它们分发给所有客户端。


8
2017-12-07 16:17



+1,但我担心成千上万的客户使用长轮询。开放连接可能需要一些环境优化。我从来没有用WCF做过这个,所以我无法评论困难/积极因素。 - marr75
+1您是否知道使用WCF在C#中进行任何良好的长轮询实现?我用谷歌搜索它并没有提出任何好的例子。 - BernicusMaximus
对不起,我没有。我知道在WCF中有一个用于Silverlight的双工通道,但是从我读过的它将定期轮询并且不进行长轮询(msdn.microsoft.com/en-us/library/cc645028(VS.95).aspx) - Jeremy Wiebe
是啊。看到同样的事情。再次感谢。 - BernicusMaximus


答案:


我想你可能想要采用两种方法的组合。首先,你可以使用 长期民意调查 从客户端到服务器,以便服务器可以在客户端感兴趣的更改发生时立即通知客户端。

在ASP.NET中很好地处理上述建议的新技术是 SignalR。这可以处理长轮询的大部分细节(或者尽可能使用WebSockets),因此您不必担心它。

其次,基于此问题中的标记,您似乎正在使用SQL Server。您可以在感兴趣的表上使用数据库通知,以便在发生更改时让数据库通知您的服务。然后,这可以触发服务通过长轮询连接通知客户端有关更改的信息。你可以使用 的SqlDependency 类。

我确信还有其他方法,但这可能会很好地扩展,因为您只有一个服务获取通知,然后将它们分发给所有客户端。


8
2017-12-07 16:17



+1,但我担心成千上万的客户使用长轮询。开放连接可能需要一些环境优化。我从来没有用WCF做过这个,所以我无法评论困难/积极因素。 - marr75
+1您是否知道使用WCF在C#中进行任何良好的长轮询实现?我用谷歌搜索它并没有提出任何好的例子。 - BernicusMaximus
对不起,我没有。我知道在WCF中有一个用于Silverlight的双工通道,但是从我读过的它将定期轮询并且不进行长轮询(msdn.microsoft.com/en-us/library/cc645028(VS.95).aspx) - Jeremy Wiebe
是啊。看到同样的事情。再次感谢。 - BernicusMaximus


你可以在WCF连接中定义一个回调接口,如下所示:

[ServiceContract(CallbackContract = typeof(IFooClient))]

当客户端启动连接时,应该通过防火墙工作。服务器可以注册更改的方法,您可以获得回调接口

IFooClient client = OperationContext.Current.GetCallbackChannel<IFooClient>();

并回调所有在数据更改时注册的客户端。


5
2017-12-07 16:19



我也喜欢这种方法。我会进一步调查。 - BernicusMaximus


如果昂贵的操作是汇集数据库的服务器,则应该实现某种缓存。它可以像ASP.NET缓存一样基本,也可以像使用memcached一样高级。

但是,如果昂贵的操作是集合服务器的客户端,则可以使用带有PubSubHubbub的Atom或RSS源来最小化对服务器的请求数。它会变得更便宜,因为有一些免费的PubSubHubbub发布者可以处理负载。


0
2017-12-07 16:15





你可以看一下 Service Broker,这样您就不必轮询更新


0
2017-12-07 16:17





我不知道为什么RSS比让您的Web服务从数据库缓存信息更简单。

为了比较这两个选项,假设你需要知道谁最后在报告中编辑了一个对象(或者最后一次更新对象等)。使用RSS提要,您必须请求提要,获取,解析并根据相关值执行操作。通过Web服务调用来记忆和缓存它的数据库调用,您只需调用服务并对结果执行操作。我唯一能看到RSS更好的是1)你支持多个客户端,你要么不控制,要么不是.Net客户端; 2)你正在基于很多轮询值同时采取行动。


0
2017-12-07 16:20