繁体   English   中英

是一个node.js应用程序,它既可以提供rest-api,也可以处理Web套接字是一个好主意?

[英]Is a node.js app that both servs a rest-api and handles web sockets a good idea?

免责声明:我是node.js的新手,所以如果这是一个奇怪的问题我很抱歉:)

我有一个node.js使用express.js来提供REST-API。 REST-API提供的数据由node.js应用程序从nosql数据库中提取。 所有客户端仅使用HTTP-GET。 但有一个例外:数据是来自master数据库的PUT和DELETEd(另一个服务器上的关系数据库)。 这种设置的想法当然是让'node.js / nosql数据库'服务器成为公共前端,从而保护主数据库免受繁重的流量。

可能许多不同的客户端应用程序将使用REST-API,但主要是它将由具有较长生命周期(通常为0.5到2小时)的客户端应用程序使用。 我没有让这个应用程序不断地轮询REST-API以获取可能的新数据,而是希望使用websockets,以便在有任何新数据时只将数据发送到客户端。 我将使用node.js应用程序,并且可能使用socket.io,以便在客户端不支持websockets时它可以回退到api-polling。 每次nosql数据库中的主数据库PUT或DELETE对象时,都应将新数据发送到客户端。

问题是我是否应该为API和websockets使用一个node.js,或者为API使用一个node.js,为websockets使用一个。

需要考虑的事项: - 性能:应用程序将托管在服务器集群上,前面有负载均衡器和HTTP加速器。 处理一切的应用程序是否会比具有不同任务的两个应用程序执 - 应用程序之间的流量:如果我选择一个两个应用程序解决方案,从主数据库接收PUT和DELETE的api应用程序每次收到新数据时都必须注意websocket应用程序(或主数据库必须注意两个应用程序)。 双倍流量是否会成为性能问题? - 代码清理:我相信两个应用程序将产生更清晰和更好的代码,但是再一次肯定会有两个应用程序的共同代码,这将导致它有两个副本。

至于负载有多重,很难说,但可能的峰值可能涉及:50000个客户端,每个监听多达5个不同的通道,从主站发送新数据,每5秒钟新数据应发送到大约25%客户端(对于某些数据,它应该发送到所有客户端,其他数据可能低于1%的客户端)

更新:谢谢你们的答案。 这里有更多的思想食物。 我决定有两个node.js应用程序,一个用于REST-API,另一个用于Web套接字。 原因是我相信它会更容易扩展它们。 首先,整个系统将托管在三个物理服务器和一个node.js应用程序上,每个服务器上的REST-API应该足够,但对于websocket应用程序,可能需要在每个物理服务器上有几个实例。

这个问题问得好。

如果您正在查看旧系统,并且已经定义了REST接口,则添加WebSocket没有太多优势。 可能指向WebSockets的事情将是:*需要服务器到客户端或客户端到客户端的实时数据*需要使用经典的双向协议与服务器组件集成(例如,您想要用javascript写一个FTP或sendmail客户端。

如果你要开始一个新项目,我会尝试在项目之间进行一次硬分裂:

  • 使用HTTP(这是它的设计)和静态内容(图像,js,css)的服务

  • 使用WebSockets提供动态内容(实时数据)(基于负载平衡,订阅/消息传递,启用自动重新连接以处理网络blip)。

那么,我们为什么要尝试分离? 让我们考虑一下基于HTTP的REST协议的优点。

将HTTP协议用于REST语义是一项具有某些优点的发明*无状态交互:客户端的上下文都不会存储在请求之间的服务器端。 *可缓存:客户端可以缓存响应。 *分层系统:中介不可检测*易测试:使用curl测试基于HTTP的协议很容易

另一方面...

在WebSockets之上使用消息传递协议(例如AMQP,JMS / STOMP)并不排除任何这些优点。

  • WebSockets可以透明地进行负载平衡,可以缓存消息和状态,可以定义有效的有状态或无状态交互。

  • 基本的反应分析样式可以定义哪些事件触发客户端和服务器之间的消息。

其他主要优点包括:* WebSocket旨在成为长期持久连接,可通过单个连接用于多种不同的消息传递目的

  • WebSocket连接允许完全双向通信,允许数据在任何方向上发送,同时具有网络特性。

  • 可以使用连接卸载来使用中介共享对常见主题的订阅。 这意味着与核心消息代理的连接非常少,您可以大规模有效地为数百万连接用户提供服务。

  • 监控和测试可以通过管理界面实现发送/接收消息(随所有消息代理提供)。

  • 所有这些的成本是当WebSocket被丢弃后需要重新连接时,需要处理重建状态。 许多协议设计者构建了“同步”消息的概念,以提供从服务器到客户端的上下文。

无论哪种方式,无论您使用REST还是WebSockets,您的模型对象可以是相同的,但这可能意味着您仍然在请求 - 响应而不是发布/订阅方面考虑太多。

您必须考虑的第一件事是,您将如何扩展服务器并管理其状态。 使用REST API,这在很大程度上是直截了当的,因为它们大部分是无状态的,并且每个负载均衡器都知道如何代理http请求。 因此,可以水平扩展REST API,将几个状态位留给持久层(数据库)来处理。 对于websockets,往往是另一回事。 您需要研究您将要使用的负载均衡器(如果是云部署,通常取决于云提供商)。 然后找出负载均衡器需要什么类型的websocket支持或配置。 然后,根据您的应用程序,您需要弄清楚如何管理整个群集中的websocket连接的状态。 考虑不同的用例,例如,如果一个服务器上的websocket事件改变了数据的状态,您是否需要将此更改传播给另一个连接上的其他用户? 如果答案是肯定的,那么你可能需要像Redis这样的东西来管理你的ws连接并在服务器之间传递变化。

至于性能,在一天结束时它仍然只是HTTP连接,所以我怀疑在分离服务器功能方面会有很大的不同。 但是,我认为两个服务器在提高代码清洁度方面会有很大的作用,只要你有另一个“核心”模块来隔离两个服务器共有的代码。

我个人会一起做这些,这是因为你可以在REST和WS之间共享模型和大部分代码。

在一天结束时,Yuri在他的回答中说的是正确的,但是没有那么多工作来平衡WS平衡,现在每个人都这样做。 我采用的方法是为所有内容提供REST,然后为订阅实时数据服务器 - 客户端创建一些WS“端点”。

因此,根据我的理解,您的客户端只会从服务器获得通知和更新,所以我肯定会使用WS。 您订阅了一些活动,然后在有活动时获得新结果。 继续询问HTTP调用并不是最好的方法。

我们有这个需求,基本上围绕这个想法构建了一个小框架http://devalien.github.io/Axolot/

基本上你可以理解我们在控制器中的方法(这只是一个例子,在我们的真实应用程序中,我们有订阅,所以我们可以在有新数据或完成程序时通知)。 在操作中有其余端点,在套接字中有websockets端点。

module.exports = {
    model: 'user', // We are attaching the user to the model, so CRUD operations are there (good for dev purposes)
    path: '/user', // Tthis is the end point

    actions: {
        'get /': [
            function (req, res) {
                var query = {};

                Model.user.find(query).then(function(user) { // Find from the User Model declared above
                    res.send(user);
                }).catch(function (err){
                    res.send(400, err);
                });
            }],
    },
    sockets: {
        getSingle: function(userId, cb) { // This one is callable from socket.io using "user:getSingle
            Model.user.findOne(userId).then(function(user) {
                cb(user)
            }).catch(function (err){
                cb({error: err})
            });
        }
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM