在过去,我只在我的本地机器上玩Node.js,所以我只有单进程Node.js应用程序的经验.现在我想创建一个我可以在网上发布的Web应用程序.
这个Web应用程序会像一个多人游戏-使用Socket.IO客户端-服务器通信,快速处理HTTP请求,咕噜任务管理,等等-我想用其他NPM包,以及用于各种任务.
我想设计这个应用程序的架构
启用水平可伸缩性(后来,当我有很多访问者时,我不必重写整个应用程序)
最小化不同执行环境的依赖性(最大化可移植性)
如何使用Node实现此目的?
我想高级架构将包括:
不同的服务器进程(每个进程都将运行Express实例并处理传入的HTTP请求).
某处应该有负载均衡器.
可选:可以定期运行并处理"共享数据"的后台进程
由于我的应用程序是一个多人应用程序,每个用户都可以与其他在线用户交互,我应该存储一些可以在这些进程之间共享的公共状态("共享数据").
为了简单起见,首先我不必保留这个共享数据,所以我想我应该使用像Redis这样的内存数据存储.
大局看起来像这样:
这个设计提出了一些问题:
我应该使用Node child_process
或cluster
模块并手动启动工作进程吗?顺便说一句,是否可以手动启动它们,例如,如果我将我的应用程序部署到Heroku或Nodejitsu?
要么: is there a better way to store these information in a config file?
我的意思是,如果我可以通过编辑代码而不是配置条目来配置我想要的服务器实例数量会更好.
如果我手动生成进程,那么(我猜)所有进程都将在同一个(虚拟)服务器上运行.
如果这个服务器有4个CPU内核,那么你最多可以产生4个Node实例,因为如果你产生更多,你的CPU将进行上下文切换,这会破坏整体性能.
如果我需要更多流程实例,我该怎么办?假设我需要100个服务器实例.我是否必须将我的应用程序部署到25台服务器并在每台服务器上生成4个进程?
在我看来,像Nodejitsu这样的托管服务会以某种方式隐藏你的系统边界层,但我不知道它在实践中是如何工作的.
特别是有这个"共享数据"提供程序组件.我想这个提供程序(如Redis服务器)必须在不同的服务器上运行,因此它可供所有进程使用.但在这种情况下,它很容易成为瓶颈,不是吗?
如果我使用某些托管服务,我是否必须自己设置负载均衡器层?
编辑:
回答几个实际问题:在第一步,我想要无缝地处理4-500个并发用户(Socket.IO连接).这是我可以实际实现的一定数量的访问者.
但我很好奇,设计一个可以轻松扩展的应用程序架构是可能的(如果是的话,如何?).假设我的网站将从一天到下一天变得流行,而不是与几百个并发用户打交道,第二天我必须服务几千人.
据我所知,像Heroku和Nodejitsu这样的云托管服务可以很容易地适应这些场景 - 你只需要增加worker/dynos /的数量 - 但它只有在你拥有合适的应用程序架构时才有效.
关于共享数据:我不想坚持下去.我只想把它留在内存中.由于Socket.IO,一方面需要一些共享数据提供者 - 一个用户能够向另一个"节点"中的用户发送消息.为此,我将使用Redis作为共享数据提供程序.Redis需要处理的事务数量等于Socket.IO发送/接收的消息量,~1000-1500消息/秒.
另一方面,需要一些共享数据提供者,因为我想根据几个标准连接用户.之后,后台进程会定期重新计算/细化这些连接的概率("权重").我已经知道如何实现高效的数据结构来处理对这个内存表的快速插入/删除.因此,"共享数据提供程序"组件将包含一些可以存储这些连接的服务器端代码(可能是Node.js).
我知道它是TL; DR但是我希望它能回答你关于这个问题的所有技术问题.:)
好的,这要经历很多事情.首先,你需要分离关注点,你需要一种方法来进行通信,这可以通过Redis实例,或其他pub/sub或req/res系统(无论是redis,kue,zmq等).注意:如果您显着增长,您可能仍需要对数据/消息的使用进行分片,至少应尽可能多.如果使用更复杂的消息队列系统(Rabbit或其他AMQP),则可以缓解此问题.
您的主要关注点似乎是流程管理.通常,如果您使用Heroku,您应该能够扩展每个节点的单个进程,但是您仍然需要外部的协调节点.如果你是自托管(不是通过heroku或类似的)那么你应该看看pm2或永远 ...你可以提出多个实例...
在大多数情况下,您的物流/基础设施问题将根据您的需求而有所不同.更不用说涉及CI/CD,docker等的新策略.或者您的数据库使用.