这篇文章给大家介绍的内容是关于浅谈node.js中高并发与分布式集群的内容,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
Node特性:高并发
在解释node为什么能够做到高并发之前,不妨先了解一下node的其他几个特性:
单线程
我们先来明确一个概念,即:node是单线程
的,这一点与JavaScript在浏览器中的特性相同,并且在node中JavaScript主线程与其他线程(例如I/O线程)是无法共享状态的。
单线程的好处就是:
无需像多线程那样去关注线程之间的状态同步问题
没有线程切换所带来的开销
没有死锁存在
当然单线程也有许多坏处:
无法充分利用多核CPU
大量计算占用CPU会导致应用阻塞(即不适用CPU密集型)
错误会引起整个应用的退出
不过在今天看来,这些坏处都已经不再是问题或者得到了适当的解决:
(1) 创建进程 or 细分实例
关于第一个问题,最直白解决方案就是使用child_process核心模块或者cluster:child_process 和 net 组合应用。我们可以通过在一台多核服务器上创建多个进程(通常使用fork操作)来充分利用每个核心,不过要处理好进程间通信问题。
另一个方案是,我们可以将物理机器划分为多台单核的虚拟机,并通过pm2等工具,管理多台虚拟机形成一个集群架构,高效运行所需服务,至于每台机器间的通信(状态同步)我这里先按下不表,在下文的Node分布式架构中再做详细说明。
(2) 时间片轮转
关于第二点,我跟小伙伴讨论过后认为可以通过时间片轮转方式,在单线程上模拟多线程,适当减少应用阻塞的感觉(虽然这种方法不会真的像多线程那样节约时间)
(3) 负载均衡、坏点监控/隔离
至于第三点,我跟小伙伴们也讨论过,认为主要的痛点就在于node不同于JAVA,它所实现的逻辑是以异步为主的。
这就导致了node无法像JAVA一样方便地使用 try/catch 来来捕获并绕过错误,因为无法确定异步任务会何时传回异常。而在单线程环境下,绕不过错误就意味着导致应用退出,重启恢复的间隙会导致服务中断,这是我们不愿意看到的。
当然,在服务器资源丰富的当下,我们可以通过 pm2 或 nginx 这些工具,动态的判断服务状态。在服务出错时隔离坏点服务器,将请求转发到正常服务器上,并重启坏点服务器以继续提供服务。这也是Node分布式架构的一部分。
异步I/O
你可能会问,既然node是单线程的,事件全部在一个线程上处理,那不是应该效率很低、与高并发相悖吗?
恰恰相反,node的性能很高。原因之一就是node具有异步I/O
特性,每当有I/O请求发生时,node会提供给该请求一个I/O线程。然后node就不管这个I/O的操作过程了,而是继续执行主线程上的事件,只需要在该请求返回回调时在处理即可。也就是node省去了许多等待请求的时间。
这也是node支持高并发的重要原因之一
实际上不光是I/O操作,node的绝大多数操作都是以这种异步的方式进行的。它就像是一个组织者,无需事必躬亲,只需要告诉成员们如何正确的进行操作并接受反馈、处理关键步骤,就能使得整个团队高效运行。
事务驱动
你可能又要问了,node怎么知道请求返回了回调,又应该何时去处理这些回调呢?
答案就是node的另一特性:事务驱动
,即主线程通过event loop事件循环触发的方式来运行程序
这是node支持高并发的另一重要原因
图解node环境下的Event loop:
┌───────────────────────┐ ┌─>│ timers │<————— 执行 setTimeout()、setInterval() 的回调 │ └──────────┬────────────┘ | |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调 │ ┌──────────┴────────────┐ │ │ I/O callbacks │<————— 执行几乎所有的回调,除了 close callbacks 以及 timers 调度的回调和 setImmediate() 调度的回调 │ └──────────┬────────────┘ | |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调 │ ┌──────────┴────────────┐ │ │ idle, prepare │<————— 内部调用,可忽略 │ └──────────┬────────────┘ | |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调 | | ┌───────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ - (retrieve new I/O events; node will block here when appropriate) │ │ poll │<─────┤ connections, │ │ └──────────┬────────────┘ │ data, etc. │ │ | | | | | └───────────────┘ | |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调 | ┌──────────┴────────────┐ │ │ check │<————— setImmediate() 的回调将会在这个阶段执行 │ └──────────┬────────────┘ | |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调 │ ┌──────────┴────────────┐ └──┤ close callbacks │<————— socket.on('close', ...) └───────────────────────┘
poll阶段:
当进入到poll阶段,并且没有timers被调用的时候,会发生下面的情况:
(1)如果poll队列不为空:
Event Loop 将同步的执行poll queue里的callback(新的I/O事件),直到queue为空或者执行的callback到达上线。
(2)如果poll队列为空:
如果脚本调用了setImmediate(), Event Loop将会结束poll阶段并且进入到check阶段执行setImmediate()的回调。
如果脚本没有被setImmediate()调用,Event Loop将会等待回调(新的I/O事件)被添加到队列中,然后立即执行它们。
当进入到poll阶段,并且调用了timers的话,会发生下面的情况:
一旦poll queue是空的话,Event Loop会检查是否timers, 如果有1个或多个timers时间已经到达,Event Loop将会回到timer阶段并执行那些timer的callback(即进入到下一次tick)。
优先级:
Next Tick Queue > MicroTask Queue
setTimeout、setInterval > setImmediate
由于timer需要从红黑树中取出定时器来判断时间是否到了,时间复杂度为O(lg(n)),故如果想立即异步执行一个事件,最好不要用 setTimeout(func, 0)。而是使用 process.nextTick() 来完成。
分布式Node架构
我了解到的Node集群架构主要分为以下几个模块:
Nginx(负载均衡、调度) -> Node集群 -> Redis(同步状态)
按我的理解整理了一副图:
当然,这应该是比较理想状态下的架构方式。因为虽然 Redis 的读/写相当快,但这是因为其将数据存储在内存池里,在内存上进行相关操作。
这对于服务器的内存负荷是相当高的,所以通常我们还是会在架构中加入 Mysql,如下图:
先解释一下这幅图:
当用户数据到来时,将数据先写入 Mysql,Node 需要数据时再去 Redis 读取,若没有找到再去 Mysql 里面查询想要的数据,并写入 Redis,下次使用时就可以直接去 Redis 里面查询了。
加入 Mysql 相较于只在 Redis 里读/写的好处有:
(1)避免了短期内无用的数据写入 Redis,占用内存,减轻 Redis 负担
(2)在后期需要对数据进行特定查询、分析的时候(比如分析运营活动用户涨幅),SQL关系查询能提供很大的帮助
当然在应对短时间大流量写入的时候,我们也可以直接将数据写入 Redis,以达到快速存储数据、增加服务器应对流量能力的目的,等流量下去了再单独将数据写入 Mysql。
简单介绍完了大体的架构组成,接下来我们来细看每个部分的细节:
流量接入层
流量接入层所做的就是对所有接受的流量进行处理,提供了以下服务:
流量缓冲
分流和转发
超时检测
与用户建立连接超时
读取用户body超时
连接后端超时
读后端响应头超时
写响应超时
与用户长连接超时
集群健康检查/隔离坏点服务器
隔离坏点服务器并尝试修复/重启,直到该服务器恢复正常
失败重试机制
在请求转发到某集群某机器上,返回失败后,将该请求转发到该集群的别的机器,或者跨集群的机器上进行重试
连接池/会话保持机制
对于延迟敏感用户使用连接池机制,减少建立连接的时间
安全防护
数据分析
当转发到各个产品线后就到了负载层工作的时候了:将请求根据情况转发到各地机房
当然,这个平台并不止转发这一个功能,你可以把它理解为一个大型的私有云系统,提供以下服务:
文件上传/服务线上部署
线上配置修改
设置定时任务
线上系统监控/日志打印服务
线上实例管理
镜像中心
等等...
Node集群层
这一层主要的工作是:
(1)编写可靠的 Node 代码,为需求提供后端服务
(2)编写高性能查询语句,与 Redis、Mysql 交互,提高查询效率
(3)通过 Redis 同步集群里各个 Node 服务的状态
(4)通过硬件管理平台,管理/监控物理机器的状态、管理IP地址等(其实这部分工作放在这一层感觉不妥,但是我也不知道应该放在哪一层。。。)
(当然这部分我只是粗浅地列列条目,还是需要时间来积累、深入理解)
数据库层
这一层主要的工作是:
(1)创建 Mysql 并设计相关页、表;建立必要的索引、外键,提升查询便利性
(2)部署 redis 并向 Node 层提供相应接口
相关推荐:
以上是浅谈node.js中高并发与分布式集群的内容的详细内容。更多信息请关注PHP中文网其他相关文章!

由于最近刚开始负责对象存储相关系统的建设与稳定性运维,作为一个“对象存储”的一个新手,需要加强这块的学习。由于公司目前采用MinIO来搭建公司的对象存储体系,后续我会逐步将自己关于MinIO的学习经验分享出来,欢迎大家持续关注。本文主要是介绍如何在测试环境中搭建MinIO,这也是构建MinIO学习环境最基本的步骤。1、准备实验环境使用OracleVMVirtualBox虚拟机,安装一个最小版本的Linux,然后添加4块虚拟盘,用于充当MinIO的虚拟盘。实验环境如下所示:接下来和大家简单介绍一下

Vercel是什么?本篇文章带大家了解一下Vercel,并介绍一下在Vercel中部署 Node 服务的方法,希望对大家有所帮助!

gm是基于node.js的图片处理插件,它封装了图片处理工具GraphicsMagick(GM)和ImageMagick(IM),可使用spawn的方式调用。gm插件不是node默认安装的,需执行“npm install gm -S”进行安装才可使用。

node怎么爬取数据?下面本篇文章给大家分享一个node爬虫实例,聊聊利用node抓取小说章节的方法,希望对大家有所帮助!

本篇文章给大家分享一个Node实战,介绍一下使用Node.js和adb怎么开发一个手机备份小工具,希望对大家有所帮助!

随着互联网的发展和应用,分布式系统也越来越受到人们的关注和重视。而在分布式系统中,如何实现快速部署和便捷管理则成为了一项必要的技术。本文将介绍如何使用Gin框架来实现分布式系统的部署和管理功能。一、分布式系统部署分布式系统的部署主要包括了代码部署、环境部署、配置管理和服务注册等几个方面。以下将逐一介绍这些方面。代码部署在分布式系统中,代码部署是一个重要的环节

node后台框架有:1、Koa,一个开源的Node web框架,用Generator来实现中间件的流程控制,用try/catch来增强异常处理;2、Nest,一个用于构建高效、可扩展的Node服务器端应用程序的框架;3、Socket,是用来在客户端和服务器端之间创建实时双向通信的框架;4、Sails,是一个非常稳固的Node框架,提供建立任何规模的Web应用所需要的所有功能。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。