Nodejs 架构
Natives modules
当前层内容由 JS 实现。
提供应用程序可直接调用库,例如 fs、path、http等。
JS 语言无法直接操作底层硬件设置。需要通过桥梁:Builtin modules "胶水层" (由C++编写)。
底层
V8:执行 JS 代码,提供桥梁接口。
Libuv: 事件循环、事件队列、异步IO
第三方模块:zlib、http、c-ares等。
Reactor模式
单线程完成多线程工作
实现异步IO、事件驱动
可以实现高并发处理
Nodejs 更适用于 IO 密集型高并发请求
Nodejs异步IO
nodejs异步 IO 是 异步非阻塞 IO
立即返回的并不是业务层期望得到的数据,而仅仅是当前调用的状态,操作系统为了获取数据,就会让程序重复调用IO操作,判断 IO 是否结束,这种技术称为轮询。
常见轮询技术:read、select、poll、kqueue、event ports
期望实现无需主动判断的非阻塞 IO
1
异步 IO 总结
IO 是异步程序的瓶颈所在
异步 IO 提高性能无须采用原地等待结果返回
IO 操作属于操作系统级别,平台都有对应实现
Nodejs 单线程配合事件驱动架构及libuv实现了异步 IO
Nodejs 事件驱动架构
事件驱动架构是软件开发中的通用模式
事件驱动、发布订阅、观察者
主体发布消息,其他实例接收消息
const EventEmitter = require('events')
const myEvent = new EventEmitter()
myEvent.on('事件1', () => {
console.log('事件1执行了')
})
myEvent.on('事件1', () => {
console.log('事件1-2执行了')
})
myEvent.emit('事件1')
输出:
Nodejs单线程
使用 JS 实现高效可伸缩的高性能 Web 服务
单线程如何实现高并发?
异步非阻塞 IO 配合事件回调通知
Nodejs 主线程是单线程
libuv 库会维护一个线程池
1
const http = require('http')
function sleepTime (time) {
const sleep = Date.now() + time * 1000
while(Date.now() < sleep) {}
return
}
sleepTime(4)
const server = http.createServer((req, res) => {
res.end('server starting......')
})
server.listen(8080, () => {
console.log('服务启动了')
})
4秒后服务启动
Nodejs应用场景
IO 密集型高并发请求
Nodejs作为中间层
操作数据库提供 API 服务
实时聊天应用程序
Nodejs 更加适合 IO 密集型任务
Nodejs实现API服务
// 需求:希望有一个服务,可以依据请求的接口内容返回相应的数据
import express from 'express'
import { DataStore } from './data'
const app = express()
app.get('/', (req, res) => {
// res.end('1122')
res.json(DataStore.list)
})
app.listen(8081, () => {
console.log('服务已经开启了')
})
Nodejs全局对象
与浏览器平台的 window 不完全相同
Nodejs 全局对象上挂载许多属性
全局对象是 JavaScript 中的特殊对象
Node.js 中全局对象是 global
Global 的根本作用就是作为宿主
全局对象可以看做是全局变量的宿主
默认情况 this 是空对象,和 global 并不是一样的
Nodejs 常见全局变量
__filename:返回正在执行脚本文件的绝对路径
__dirname:返回正在执行脚本所在目录
timer类函数:执行顺序与事件循环间的关系
process:提供与当前进程互动的接口
require:实现模块的加载
module、exports:处理模块的导出
Nodejs 常见全局变量-process
获取进程信息
执行进程操作
// 1 资源: cpu 内存
console.log(process.memoryUsage()) // 内存信息
/*
{
rss: 24449024, // 常驻内存
heapTotal: 4481024, // 脚本执行申请的内存总大小
heapUsed: 2822984, // 脚本执行过程中实际使用的内存大小
external: 938610, // 底层c++模块所占用的内存大小
arrayBuffers: 9898 // Buffer 独立占用的缓冲区内存大小
}
*/
console.log(process.cpuUsage()) // cpu 信息
/*
{
user: 31000, // 用户执行过程中所占用的cpu时间片段
system: 46000 // 操作系统所占用的cpu时间片段
}
*/
// 2 运行环境:运行目录、node环境、cpu架构、用户环境、系统平台
console.log(process.cwd()) // 当前工作目录
// D:\s\lagou\5\1\5-1-课程资料\Code\01Base
console.log(process.version) // 当前node版本
//v14.18.1
console.log(process.versions) // node 其他相关版本信息
/*
{
node: '14.18.1',
v8: '8.4.371.23-node.84',
uv: '1.42.0',
zlib: '1.2.11',
brotli: '1.0.9',
ares: '1.17.2',
modules: '83',
nghttp2: '1.42.0',
napi: '8',
llhttp: '2.1.4',
openssl: '1.1.1l',
cldr: '39.0',
icu: '69.1',
tz: '2021a',
unicode: '13.0'
}
*/
console.log(process.arch) // 本机操作系统信息
// x64
console.log(process.env.NODE_ENV) // 获取当前环境,例如:dev、prod
console.log(process.env.PATH) // 获取本机所配置的系统环境变量
/*
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\nodejs\;D:\微信web开
发者工具\dll;C:\Users\zxy\AppData\Local\Microsoft\WindowsApps;C:\Users\zxy\AppData\Roaming\npm;C:\Users\zxy\AppData\Local\Programs\Microsoft VS Code\bin
*/
console.log(process.env.USERPROFILE) // 获取本机的管理员目录 mac系统使用 process.env.HOME
// C:\Users\zxy
console.log(process.platform) // 获取本机操作系统
// win32
// 3 运行状态: 启动参数、PID、运行时间
console.log(process.argv) // 获取启动参数
/*
PS D:\s\lagou\5\1\5-1-课程资料\Code\01Base> node .\05-process.js 1 2
[
'C:\\Program Files\\nodejs\\node.exe', // 当前Node启动程序的完整路径
'D:\\s\\lagou\\5\\1\\5-1-课程资料\\Code\\01Base\\05-process.js', // 当前进程文件的路径
'1',
'2'
]
*/
console.log(process.argv0) // 获取启动参数 第一个参数,只提供了 argv0
// C:\\Program Files\\nodejs\\node.exe
console.log(process.pid) // 获取当前进程的 pid
// 30024
setTimeout(() => {
console.log(process.uptime()) // 记录从运行开始到运行结束所消耗的时间
// 3.0328957
}, 3000)
process 事件
// 事件
process.on('exit', code => { // code: 退出的状态码
console.log('exit', code)
setTimeout(() => {
console.log(123) // 未打印,只支持同步代码
}, 1000)
})
process.on('beforeExit', code => { // code: 退出的状态码
console.log('beforeExit', code)
})
console.log('代码执行完了')
/*
代码执行完了
beforeExit 0
exit 0
*/
process.exit() // 直接退出,不会调用 beforeExit
process 标准输出,输入,错误
// 标准输出,输入,错误
console.log = function(data) {
process.stdout.write('---' + data + '\n')
}
console.log(11)
console.log(22)
/*
---11
---22
*/
读取文件经过管道输出
const fs = require('fs')
fs.createReadStream('text.txt')
.pipe(process.stdout)
// 控制台输出文件里的内容
控制台里输入内容 stdin
process.stdin.pipe(process.stdout)
获取控制台输入内容事件 stdin
process.stdin.setEncoding('utf-8')
process.stdin.on('readable', () => {
let chunk = process.stdin.read()
console.log(chunk)
})