Node.js+Socket.io+MongoDB webapps 是如何真正异步的?
Posted
技术标签:
【中文标题】Node.js+Socket.io+MongoDB webapps 是如何真正异步的?【英文标题】:How are Node.js+Socket.io+MongoDB webapps truly asynchronous? 【发布时间】:2012-10-10 07:11:05 【问题描述】:我有一个很好的老式 LAMP webapp。一周前,我需要为其添加推送通知机制。 因此,我所做的是在服务器上添加 node.js+socket.io 并使用 node.js 每 10 秒轮询一次 mysql 数据库以检查是否有新项目:如果有,我会将它们发送到客户端( s) 使用 socket.io。 我对结果非常满意,即使这不是一个适当的实时通知(因为最多有 10 秒的延迟)。
现在,我要构建一个新的 web 应用程序,它也需要推送通知。我想知道是采用与第一种方法相同的方法(我认为它更稳定和成熟)还是完全采用 Node.js,不使用 php 和 Apache。至于数据库,我已经决定去MongoDB了。
最后,我的问题是:如果我选择 Node.js+Socket.io+MongoDB,我会得到一个真正 near-real-time webapp吗?我的意思是,一旦将新记录插入 MongoDB,是否会触发某种事件,我可以通过 node.js 捕获,对其进行检查,如果相关,将通知发送给客户端?还是会像我的第一个 LAMP webapp 那样在 db 服务器端和延迟上进行某种轮询?
一个相关问题:您能否像我在第一个应用程序中所做的那样在 MySQL 上构建一个实时 web 应用程序而不进行任何轮询。还是需要 MongoDB(或 Redis)?
我希望这个问题不是太傻 - 抱歉,我只是从 Node.js 和 co 开始。
谢谢。
【问题讨论】:
您可能要考虑不使用术语和标签“实时”。尽管大多数人都知道您的意思,但您的追求不是迂腐real-time,而是非阻塞。考虑使用术语异步、非阻塞或近实时。 @dan 如果您觉得我的回答有用,请您接受吗? 实时与您用于实施服务的技术无关。它与您的客户端和服务实现有关。 【参考方案1】:使用 JS 你可以打开一个到你的服务器的套接字(不是旧的浏览器),服务器将有一个 ah-hoc 程序(在一个 ad-hoc 端口上,所以你需要打开门并在你的服务器上运行程序的权限) 将(几乎)实时地与客户端发送数据,并且没有 HTTP 的协议开销。旧浏览器将回退到轮询机制。
我看不到其他方法可以做到这一点(可能已经有“coocked”框架可以做到这一点)
【讨论】:
【参考方案2】:我了解您的问题,因为我也从 php/apache/mysql 切换到 node.js。
一般node.js是稳定的,模块和你的脚本是出错的主要原因
实时与数据库无关,都是客户端和服务器,你可以在请求中查询任意多的数据并将其推送到其他客户端。
选择 node.js 是非常明智的,但实施起来比较困难。
当您向数据库插入新记录时,事件就是请求本身,您将与数据库查询一起进行推送事件,如下所示:
// Please note this is not real code, just an example of the idea
app.get('/query', function(request, response)
// Query your database
db.query('SELECT * FROM users', function(rows)
// Push notification to dan
socket.emit('database_query_executed', 'to_dan', rows);
// End request
response.end('success');
)
)
当然可以使用 MySQL!你想要的任何数据库,正如我所说的,实时与数据库无关,因为数据库处于进程的中间,它是完全可选的。
如果你想将 node.js 用于 推送通知 和 php/apache 用于 mysql 那么你将需要为每个服务器创建 2 个请求,例如:
// this is javascript
ajax('http://node.yoursite.com/push', node_options)
ajax('http://php.yoursite.com/mysql_query', php_options)
或者如果你只想要一个请求,或者你想使用一个表单,你可以调用你的 php 并且在 php 中你可以创建一个 http 或对 node.js 的网络请求 来自 php,类似于:
// this is php
new HttpRequest('http://node.youtsite.com/push', HttpRequest::METH_GET);
【讨论】:
+1 iff 对数据库的更改都发生在同一个 Node.js 应用程序中(并且由客户端发起)。 @Deer - 这是一个很好的观点。如果我将主应用程序保留在 PHP+Apache+MySQL 中并仅使用 Node.js 进行推送通知会怎样? @dan 有两种可能:1)您必须在客户端发起两个请求,1 个用于 node.js,1 个用于 apache/php,2)一个用于 apache/php在内部创建对 node.js 的请求,或者您可以从调用 php 的 node.js 开始,因此您需要同时调用两者,php 用于 mysql,node.js 用于推送通知 @Adam, dan - nay :-) iff Adam:就像你的第二个想法(通过内部请求将 websockets 通信卸载到 node.js)更好。 iff 表示当且仅当。【参考方案3】:回复:MongoDB 中的触发器 - 请参阅此答案:https://***.com/a/12405093/1651408
MySQL 中有更方便的触发器,但要从中调用 Node.js 需要对 MySQL UDF (user-defined functions) 进行一些处理,例如通过 Unix 套接字推送数据。请注意,仅当其他应用程序(除了您的 Node.js 进程)正在更新数据库时才需要这样做,并且在这种情况下确保选择 InnoDB 作为存储(行级与表级锁定)。
可以看出您选择sockets.io
的技术没有什么大问题,即使client-side web sockets aren't supported,您也会(我希望优雅地)退回到投票。
最后,你的问题一点也不傻,因为推送技术绝对优于大量的轮询请求——它的扩展性更好。编辑:但是,不会将这两种技术描述为实时。
另一个编辑:对于此类非常知名且成功的设置,请阅读以下内容:http://blog.fogcreek.com/the-trello-tech-stack/
【讨论】:
【参考方案4】:实际使用Socket.IO这样的推送技术帮助你使用
有效地利用服务器的资源,还可以帮助您将旧浏览器利用到现代浏览器来建立 websocket 或类似 websocket 的连接。
10 秒轮询是一个 HTTP 请求,它昂贵,尤其是当有很多用户在场时。
与轮询技术不同,推送技术相对便宜。用户的客户端打开一个专用的socket(即websocket)来监听服务器的推送通知。
通常您的客户端 JavaScript 在收到推送通知时会执行一些操作。
使用您的 LAMP 堆栈和具有不同端口(80 除外)的 Socket.IO 就足够了来实现您所需要的。
但是使用 Node.js + MongoDB + Socket.IO 实际上可以帮助您更有效地管理服务器资源。
因为这三个具有非阻塞性质。
如果您正确理解非阻塞概念并正确实施您的应用,
您的相同应用,具有相同功能但具有不同语言和不同数据库的应用,将能够处理比一般 LAMP 堆栈更多的请求。
上图是比较Non-blocking vs Thread方式处理并发的著名图表
Apache(线程)与 Nginx(非阻塞)
MySQL 是一个很棒的数据库。我相信您不需要join
和transactions
进行实时通知。
MongoDB 没有这两个功能,除非您自己实现类似的功能。
由于不具备这两个特性以及它自己的一些特性,MongoDB 可以比传统 SQL 数据库更快地存储和获取数据。
从 MySQL 切换到 MongoDB 将减少插入和获取数据的时间。
【讨论】:
【参考方案5】:使用:
作为 Store 的常规 MongoDB 集合, A MongoDB Capped Collection with Tailable Cursors 作为队列, 一个使用 Socket.IO 的 Node Worker 作为 Worker 观察队列, 一个节点服务器,用于通过 Socket.IO 客户端为页面提供服务,并作为 服务器 接收 POST 数据(或者其他数据被添加)它是这样的:
-
新数据被发送到服务器,
Server 将数据放入 Store,
服务器将数据的 ObjectID 添加到队列中,
Queue 会将新到达的 ObjectID 发送到 Worker 上打开的 Tailable Cursor,
Worker 去从 Store 中获取 ObjectID 中的实际数据,
Worker 通过套接字发出数据,
客户端从套接字接收数据。
这是从最初添加数据一直到客户端接收的“推送” - 没有轮询,因此您可以获得实时的每一步处理时间。
【讨论】:
【参考方案6】:你发现Chole了吗?它与您的 Web 服务器分开工作,并通过使用 HTTP POST 与其交互。这样你就可以按照你想要的任何方式编写你的网络应用程序。
【讨论】:
以上是关于Node.js+Socket.io+MongoDB webapps 是如何真正异步的?的主要内容,如果未能解决你的问题,请参考以下文章