网站首页 > 基础教程 正文
文末有福利
NodeJS
V8 内存管理模型
node 程序运行中,此进程占用的所有内存称为 常驻内存 :
- 代码区:存放即将执行的代码片段
- 栈:存放局部变量
- 堆:存放对象、闭包上下文
- 堆外内存:由 c++分配,不受 V8 管理,也不会被 V8 回收。(Buffer 数据)
V8 垃圾回收 :recycle:
- 新生代:将内存平均分为两块,使用空间叫 FROM,闲置空间叫 TO。将存活对象分配到 TO 空间,然后清除 FROM 空间调换 FROM 和 TO 空间,继续内存分配新生代晋升老生代多次存活的对象会晋升至老生代To 空间内存使用率超过 25%
- 老生代:标记清除 Mark-Sweep (会产生碎片)标记整理 Mark-Compact (整理连续内存)
事件循环
高并发: 单线程 非阻塞 异步 IO(主线程事件循环机制以及底层线程池的实现)
Event Loop
事件循环原理
- node 初始化初始化 node 环境执行输入代码执行 process.nextTick 回调执行 microtasks
- 进入 Event Looptimers 阶段检查 timer 队列是否有到期的 timer(setTimeout/setInterval)回调,有的话将到期的回调按 timerId 升序执行。IO callback 阶段检查是否有等待(pending)的 IO 回调,有的话执行idle,prepare 阶段nodejs 内部调用poll 阶段检查是否存在尚未完成的回调,如果存在,分两种情况如果队列不为空(包含到期的定时器和 IO 事件),执行可用回调。如果队列为空,检查是否有 setImmediate 回调,如果有,退出 poll 阶段,进入 check 阶段。如果没有,超时之前 node 阻塞在这里,等待新的事件通知。如果不存在尚未完成的回调,直接退出 poll 阶段check 阶段如果有 setImmediate 回调,执行回调closing callback如果套接字或处理函数突然关闭(例如 socket.destroy()),则'close' 事件将在这个阶段发出。在事件循环的每一个子阶段退出之前,都会执行:检查是否有 process.nextTick,有的话执行执行 microtasks退出当前阶段
- 检查是否有活跃的 handlers(定时器,IO 事件句柄)如果有,继续下一轮循环没有,就退出事件循环,退出程序
process.nextTick :vs: setImmediate
process.nextTick 是 Nodejs 的一个定时器,他是在本轮循环执行的,而且是所有异步任务中最快执行的。Node 执行完所有同步任务,就会去执行 process.nextTick 任务队列。
process.nextTick 并不属于 Event Loop 中的某一阶段,而在 Event loop 的每一个阶段结束之前,直接执行 nextTickQueue 中插入的 tick,并且直到整个 Queue 处理完。
setImmediate 是在当前任务队列的尾部添加事件,也就是说,它指定的事件总在下一次 Eventloop 执行。
递归调用的 process.nextTick 会导致 IO 饥饿,推荐 setImmediate。
示例:
进程 Process
- 查看进程ps -ef
- 当前进程的启动目录process.cwd()
- 改变工作目录process.chdir()
- 标准流process.stdin process.stdout process.stderr
- child_process.fork 与 POSIX 的 fork 有什么区别? Nodejs 的 child_process.fork()在 UNIX 上的实现最终调用了 POSIX 的 fork,但是 POSIX 需要手动管理子进程的资源释放,child_process.fork 不用担心这个问题,nodejs 自动释放,并且可以在 option 中选择父进程死后是否允许子进程存活spawn exec fork
- child.kill 与 child.send一个是基于信号系统, 一个是基于 IPC.
- 父进程或子进程的死亡是否会影响对方? 什么是孤儿进程?子进程死亡不会影响父进程, 不过子进程死亡时(线程组的最后一个线程,通常是“领头”线程死亡时),会向它的父进程发送死亡信号.反之父进程死亡, 一般情况下子进程也会随之死亡,但如果此时子进程处于可运行态、僵死状态等等的话, 子进程将被进程 1(init 进程)收养,从而成为孤儿进程.另外, 子进程死亡的时候(处于“终止状态”),父进程没有及时调用 wait() 或 waitpid() 来返回死亡进程的相关信息,此时子进程还有一个 PCB 残留在进程表中,被称作僵尸进程.
Cluster
Cluster 是 nodejs 常见的利用多核的办法,它是利用 child_process.fork 实现的,所以 cluster 产生的进程之间是通过 IPC 来通信的,并且它也没有拷贝父进程的空间,而是通过加入 cluster.isMaster 来区分父、子进程。
const cluster = require('cluster')
const http = require('http')
const numCPUs = require('os').cpus().length
if (cluster.isMaster) {
// 仅父进程执行
// fork workers
for(i = 0; i<numCPUs;i++) {
cluster.fork()
}
cluster.on('exit', (worker) => {
console.log(`worker ${worker.process.pid} died`)
})
} else {
// 仅子进程执行
// workers can share any TCP connection
http.createServer((req, res) => {
res.writeHead(200)
res.end('hello world')
}).listen(3000)
}
复制代码
Koa
compose:
function compose(middlewares){
return ctx => {
const dispatch = i => {
const middleware = middlewares[i]
if(!middleware) return
return middleware(ctx, () => dispatch(i+1))
}
return dispatch(0)
}
}
复制代码
Context: ctx
class Context{
constructor(req, res) {
this.req=req
this.res=res
}
}
复制代码
Koa-mini
class Application() {
constructor() {
this.middlewares = []
}
listen(...args) {
const server = http.createServer(async (req,res) => {
const ctx = new Context(req,res)
const fn = compose(this.middlewares)
await fn(ctx)
ctx.res.end(ctx.body)
})
server.listen(...args)
}
use(middleware){
this.middlewares.push(middleware)
}
}
复制代码
如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以加入到我的Q群中:前114中6649后671,里面有许多前端学习资料以及2020大厂面试真题 点赞、评论、转发 即可免费获取,希望能够对你们有所帮助。
- 上一篇: Node.JS实战24:分离子进程
- 下一篇: Node.js如何调用Python脚本?
猜你喜欢
- 2024-11-25 Deno 1.30 正式发布
- 2024-11-25 用 WasmEdge 和 Rust 在边缘云上构建高性能且安全的微服务
- 2024-11-25 通过浏览器工作台启动本地项目
- 2024-11-25 r2frida:基于Frida的远程进程安全检测和通信工具
- 2024-11-25 NPM 使用介绍
- 2024-11-25 使用Hexo在github上搭建静态博客
- 2024-11-25 Android动态调试(1)-Radare2和lldb
- 2024-11-25 Metasploit渗透测试之MSFvenom
- 2024-11-25 浅析CTF中的Node.js原型链污染
- 2024-11-25 首个SSRF漏洞开篇学习
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)