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 是一个很棒的数据库。我相信您不需要jointransactions 进行实时通知。

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 是如何真正异步的?的主要内容,如果未能解决你的问题,请参考以下文章

每五分钟安排一次 Node.js 作业

无法获取 socket.io.js

Ubuntu 12.04 中的 Socket.io 错误

一个包含 node.js 和 mongodb 的整个网站?

未找到 Socket.io.js(node.js + express + socket.io)

带有 socket.io 和后端 php 的 Angular