保护我方输出nodejs(一)

node最近被唱衰,尤其是在后端领域,node确实有不适用的地方,但无脑黑的真不少,随即想再复盘整理下node相关的资料,也随手来个使命感(口号)“保护我方输出 nodejs”

nodejs概述

nodejs是什么

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时。它允许通过JavaScript和一系列模块来编写服务器端应用和网络相关的应用。核心模块包括文件系统I/O、网络(HTTP、TCP、UDP、DNS、TLS/SSL等)、二进制数据流、加密算法、数据流等等。

运行时包含了程序运行的基本环境,这里有动态内存—堆,有线程栈,有最基本的运行时函数库,例如文件读写API, 网络交互,等等。

任何语言都需要有自己的运行时,一直以来,javascript 都以浏览器为运行时,从事客户端的工作(网络、DOM、外部事件、HTML5视频、canvas和存储),node的出现突破了这一限制,为javascript在服务器端开疆拓土提供了环境。

nodejs 架构

Node.js主要分为四大部分,Node Standard Library,Node Bindings,V8,Libuv等,架构如下

node-framework

  • 标准库是node直接提供给开发者的接口
  • node bindings 提供js和c/c++交互的通道,封装了v8和libuv,向标准库提供基础接口
  • v8是谷歌开发的js引擎,提供js运行环境
  • libuv 是一个跨平台的异步I/O库
  • c-ares 是异步处理dns的库
  • http_parser等提供http解析,ssl,数据压缩等能力

nodejs的特性

事件驱动,非阻塞io

正如node架构展示的那样,node拥有libuv非阻塞io,事件驱动的能力,擅长io密集型任务;
事件驱动是说通过注册事件队列,轮询处理事件的机制,如图

node-evenloop

轮询执行的简化概述如下

event-detail

1. 定时器:处理已经被setTimeOut()和setInterval() 调度的回调函数
2. 待定回调:执行延迟到下一个循环迭代的I/O回调
3. idle,prepare:系统内部使用
4. 轮询:检索新的I/O事件,执行与I/O相关的回调
5. 检测:执行setImmediate()回调函
6. 关闭回调函数:一些关闭的回调函数

非阻塞io是说基于epoll 事件驱动的多路复用IO / IOPC异步IO 的IO处理模型

单线程

单线程是说,v8单线程解释执行js的特性, 因此node本身不擅长处理cpu密集型任务,但可以通过cluster模块的多进程模型来适当解决;

基于node特性的发散和延展

由node特性可以看到,一个node程序运行后,会产生两种线程:主线程即事件循环线程;线程池中的工作线程。这种特点决定了,主线程阻塞或者线程池的线程阻塞耗尽,都将成为node应用性能瓶颈,对于生产应用来说就是安全故障隐患,因此应该尽可能降低每个回调任务的复杂度,减少耗时操作(复杂正则,复杂json处理,密集计算)

常见耗时任务
  1. 复杂正则

    通过正则复杂度模块 检查确定是否是复杂正则 safe-regex

  2. node同步api

    node的异步IO是特色,但也提供了方便使用的同步IO api,但是这些同步api是高开销的,在服务端应谨慎使用。主要包含以下模块:

    • crypto
    • zlib
    • fs
    • child_process
  3. 复杂json解析

    JSON.stringify() 和 JSON.parse()包含了高耗时操作,对复杂的json解析,耗能严重,应考虑对交互json深度进行限制或者使用异步流api,如Big-Friendly JSON

耗时任务的处理方式

对于“大”问题,一般解决思路都是分治,一大化多小,拆分思路如下:

  1. 拆分任务

    在同一线程内进行任务拆分,比如遍历任意长数组的元素,可通过闭包的方式保存上下文,分段执行

  2. 分流处理

    通过cluster模块,子进程,外部负载均衡进行分流

    通过N-API 主动为node线程池分配任务

定时器
  • setTimeout / setInterval

    setTimeout / setInterval 返回Timeout对象, 可指定回调任务间隔多久后执行,调度的回调在事件轮询的timers阶段执行

  • clearTimeout / clearInterval / unref

    clearTimeout / clearInterval 取消Timeout对象调度回调函数的执行

    unref() 将定时器对象标进行active–,当active 为0时,定时器退出,定时器调度的回调函数则不会执行

  • setImmediate

    setImmediate调度回调函数 在当前时间轮询的任何I/O操作后,且在下一轮定时器执行前 执行

process.nextTick()

process.nextTick() 不属于事件轮询,它总是在当前操作完成后被处理,不管事件循环进行到哪个阶段

node市场定位和前景

从09年node发布第一个版本到现在,已经过去十年了,node从“威胁”java地位的高性能后端语言,逐步过渡到了前端工程化的工具语言,无论是开发者还是企业技术团队,通过用脚投票的方式基本摒弃了node在后端的使用价值,至少到现在,node的市场定位就落在了大前端方向

前端如今的繁荣离不开node的发展,在一段时间内,node将依然在前端工程化,前端业务逻辑复杂化,serverless等领域建功立业,对于前端的同学来说,node已经从加分项慢慢变成必备技能

参考资料

ref && unref

你知道的node可能都是错的

不要阻塞你的事件线程和线程池

node源码阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值