我开发了一个聊天 Web 应用程序,它使用 SqlServer 数据库来交换消息。
所有客户端每 x 秒轮询一次以检查新消息。
很明显,这种方法会消耗很多资源,我想知道是否有一种“更便宜”的方式来做到这一点。
我对“存在”使用相同的方法:检查谁在场。
我开发了一个聊天 Web 应用程序,它使用 SqlServer 数据库来交换消息。
所有客户端每 x 秒轮询一次以检查新消息。
很明显,这种方法会消耗很多资源,我想知道是否有一种“更便宜”的方式来做到这一点。
我对“存在”使用相同的方法:检查谁在场。
不使用像 flash 或 java applet 这样的浏览器插件/扩展,浏览器本质上是一种单向通信工具。请求必须由浏览器发起才能获取数据。您不能将数据“推送”到浏览器。
许多 web 应用程序使用 Ajax 轮询方法来模拟服务器“推送”。诀窍是平衡频率/数据大小与带宽和服务器资源。
我只是对gmail做了一个简单的观察。它每 5 秒执行一次 HttpPost 轮询。如果没有“状态”变化,则响应数据大小只有几个字节(不包括 http 标头)。当然,谷歌拥有巨大的服务器资源和带宽,这就是我提到的原因:找到一个很好的平衡点。
那就是“改善用户体验与服务器资源”。您可能需要提出一种创造性的轮询策略方式,而不是每 x 秒进行一次简单的轮询。
例如,如果 A 方没有活动,则每 3 秒轮询一次。在甲方打字时,每 5 秒轮询一次。这只是一个插图,你可以玩弄数字,或者想出一个更有效的数字。
最后是数据交换。挑战在于找到一种方法来传递最小数据大小以传达相同的信息。
我的 2 美分 :)
如果您使用的是 SQL Server 2005,您可以查看 Notification Services。当然,这会将您锁定在 SQL 2005 中,因为在 SQL 2008 中删除了通知服务,它旨在允许 SQL Server 通知客户端应用程序对数据库的更改。
如果您想要一些更具可扩展性的东西,您可以在用户记录上放置几个位标志。当用户收到消息时,将新消息的位更改为 true。当您阅读消息时,将其更改为 0。人们登录和注销时也是如此。这样,您正在阅读一个非常小的字段,该字段很有可能已经在缓存中。
做工作流程就准备好了。如果为 1,则从消息表中获取消息。如果它是 0 什么都不做。
在 ASP.NET 4.0 中,您可以将观察者模式与 JavaScript 对象和数组一起使用,即:使用 jQuery 和/或 PageMethods 的 AJAX JSON 调用。
您将始终需要访问数据库来分析是否有任何数据要返回。诀窍在于使这些调用变小,并且只在需要时返回数据。
SQL Server 2005 内置了两个相关的解决方案,并且在 SQL Server 2008 中仍然可用:
1) Service Broker,它允许订阅者发布对队列的读取(带有 WAIT.. 的 RECEIVE 命令)。在您的情况下,您希望使用位于这些队列前面的 Service Broker 服务通过数据库发送消息,然后等待的客户端可以接收这些消息。没有轮询,等待的客户端只是在收到消息时被激活。
2)查询通知,它允许订阅者定义一个查询,并在执行该查询产生的数据集发生变化时接收通知。建立在 Service Broker 之上的查询通知更易于使用,但也可能效率较低。(并不是说查询通知及其同级,事件通知经常被误认为通知服务 (NS),这引起了人们的关注,因为 NS 在 2008 年被取消,但是,查询和事件通知仍然完全可用,甚至在 SQL Server 2008 中得到了增强)。
对于诸如实时聊天应用程序之类的东西,我建议使用带有 SQL 支持的分布式缓存。我碰巧喜欢使用 Enyim .NET 提供程序的 memcached,所以我会执行以下操作:
数据库支持允许您在缓存被清除或应用程序重新启动时预加载缓存,但功能位依赖于内存缓存,而不是轮询数据库。