Node.js基础与常用模块
目录
相关资料
Node.js介绍与安装
什么是Node.js?
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,使JavaScript能够在服务器端运行。它采用事件驱动、非阻塞I/O模型,使其轻量且高效。
Node.js的特点
graph TD
A[Node.js特点] --> B[事件驱动架构]
A --> C[非阻塞I/O]
A --> D[单线程模型]
A --> E[跨平台支持]
A --> F[丰富的包生态]
B --> B1[基于事件循环]
B --> B2[高并发处理]
C --> C1[异步操作]
C --> C2[高效资源利用]
D --> D1[避免线程切换开销]
D --> D2[简化并发编程]
E --> E1[Windows/macOS/Linux]
E --> E2[容器化支持]
F --> F1[npm生态系统]
F --> F2[模块化开发]
核心优势:
- 高性能:基于V8引擎的快速执行
- 高并发:事件循环机制处理大量并发连接
- 统一语言栈:前后端使用同一种语言
- 实时应用:非常适合构建实时应用(如聊天室、游戏服务器)
安装Node.js
为什么选择Volta?
Volta是一个快速、可靠的JavaScript工具链管理器,具有以下优势:
- 跨平台兼容:Windows、macOS、Linux全平台支持
- 项目级版本管理:每个项目可以使用不同的Node.js版本
- 无缝切换:自动检测并切换到项目所需的版本
- 速度快:用Rust编写,启动速度极快
- 团队协作:确保团队使用统一的工具版本
还有其他选择
| 工具 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| Volta | 快速、自动切换、团队友好 | 相对较新 | 现代开发团队 |
| nvm | 成熟稳定、功能丰富 | Windows支持不佳 | Unix系统 |
| fnm | 速度快、跨平台 | 功能相对简单 | 个人开发 |
| n | 简单易用 | 仅支持Unix | 简单场景 |
使用Volta安装Node.js
在Windows上安装Volta
javascript
// 使用PowerShell安装
// 下载并运行安装脚本
curl https://get.volta.sh | bash
// 或者从官网下载安装包
// https://github.com/volta-cli/volta/releases
在macOS/Linux上安装Volta
bash
# 使用curl安装
curl https://get.volta.sh | bash
# 重新加载shell配置
source ~/.bashrc
# 或者
source ~/.zshrc
# 验证安装
volta --version
安装Node.js和npm
bash
# 安装最新LTS版本的Node.js
volta install node
# 安装特定版本
volta install node@18.17.0
# 安装npm特定版本
volta install npm@9.8.0
# 查看已安装的工具
volta list
创建并管理项目
使用npm初始化项目
bash
# 创建项目目录
mkdir my-node-app
cd my-node-app
# 初始化package.json
npm init -y
# 或者交互式初始化
npm init
package.json示例:
javascript
{
"name": "my-node-app",
"version": "1.0.0",
"description": "Node.js应用示例",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"lint": "eslint .",
"build": "webpack --mode production"
},
"keywords": ["node", "javascript", "api"],
"author": "Your Name",
"license": "MIT",
"volta": {
"node": "18.17.0",
"npm": "9.8.0"
},
"dependencies": {
"express": "^4.18.2",
"dotenv": "^16.3.1"
},
"devDependencies": {
"nodemon": "^3.0.1",
"eslint": "^8.47.0",
"jest": "^29.6.2"
}
}
安装依赖
bash
# 安装生产依赖
npm install express
npm install --save express # 等价写法
# 安装开发依赖
npm install --save-dev nodemon
npm install -D eslint # 简写形式
# 安装全局依赖
npm install -g pm2
# 安装所有依赖
npm install
# 安装指定版本
npm install express@4.18.2
编写与调试Node.js程序
创建一个简单的服务器
javascript
// index.js - 基础HTTP服务器
const http = require('node:http');
const url = require('node:url');
// 创建服务器
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
const method = req.method;
// 设置响应头
res.setHeader('Content-Type', 'application/json');
res.setHeader('Access-Control-Allow-Origin', '*');
// 路由处理
if (path === '/' && method === 'GET') {
res.statusCode = 200;
res.end(JSON.stringify({
message: '欢迎使用Node.js服务器',
timestamp: new Date().toISOString(),
pid: process.pid
}));
} else if (path === '/health' && method === 'GET') {
res.statusCode = 200;
res.end(JSON.stringify({
status: 'healthy',
uptime: process.uptime(),
memory: process.memoryUsage()
}));
} else {
res.statusCode = 404;
res.end(JSON.stringify({
error: '页面未找到',
path
}));
}
});
// 错误处理
server.on('error', (error) => {
console.error('服务器错误:', error);
});
// 启动服务器
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}`);
});
javascript
// express-server.js - 使用Express框架
const express = require('express');
const path = require('node:path');
const app = express();
// 中间件配置
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
// 日志中间件
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next();
});
// 路由定义
app.get('/', (req, res) => {
res.json({
message: 'Express服务器运行中',
version: require('./package.json').version,
environment: process.env.NODE_ENV || 'development'
});
});
app.get('/api/users', (req, res) => {
// 模拟用户数据
const users = [
{ id: 1, name: '张三', email: 'zhangsan@example.com' },
{ id: 2, name: '李四', email: 'lisi@example.com' }
];
res.json(users);
});
app.post('/api/users', (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({
error: '姓名和邮箱不能为空'
});
}
const newUser = {
id: Date.now(),
name,
email,
createdAt: new Date().toISOString()
};
res.status(201).json(newUser);
});
// 错误处理中间件
app.use((error, req, res, next) => {
console.error('错误:', error);
res.status(500).json({
error: '服务器内部错误'
});
});
// 404处理
app.use((req, res) => {
res.status(404).json({
error: '接口不存在'
});
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Express服务器运行在端口 ${PORT}`);
});
运行项目
bash
# 直接运行
node index.js
# 使用npm scripts
npm start
npm run dev
# 使用PM2(生产环境)
pm2 start index.js --name "my-app"
pm2 status
pm2 logs my-app
使用npm脚本调试
javascript
// package.json中的scripts配置
{
"scripts": {
"start": "node index.js",
"dev": "nodemon --inspect index.js",
"dev:watch": "nodemon --watch src --ext js,json index.js",
"debug": "node --inspect-brk index.js",
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"build": "webpack --mode production"
}
}
调试配置:
bash
# 启动调试模式
npm run debug
# 使用Chrome DevTools调试
# 打开 chrome://inspect
# 点击 "inspect" 链接
# VS Code调试配置 (.vscode/launch.json)
json
{
"version": "0.2.0",
"configurations": [
{
"name": "启动程序",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/index.js",
"env": {
"NODE_ENV": "development"
},
"console": "integratedTerminal"
},
{
"name": "调试测试",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal"
}
]
}
Node.js核心模块详解
模块系统概述
Node.js采用CommonJS模块系统,同时支持ES模块。以下是核心模块的分类:
graph TD
A[Node.js核心模块] --> B[文件系统]
A --> C[网络通信]
A --> D[进程管理]
A --> E[数据处理]
A --> F[实用工具]
B --> B1[fs - 文件系统]
B --> B2[path - 路径处理]
C --> C1[http/https - HTTP服务]
C --> C2[net - TCP网络]
C --> C3[dgram - UDP协议]
D --> D1[process - 进程对象]
D --> D2[child_process - 子进程]
D --> D3[cluster - 集群]
E --> E1[buffer - 二进制数据]
E --> E2[stream - 数据流]
E --> E3[crypto - 加密]
F --> F1[util - 实用函数]
F --> F2[os - 操作系统]
F --> F3[events - 事件发射器]
常见问题解析
1. 为什么有时使用node:fs,而有时使用fs?
历史背景与最佳实践:
javascript
// 传统方式(向后兼容)
const fs = require('fs');
const path = require('path');
const http = require('http');
// 现代方式(Node.js 14+)
const fs = require('node:fs');
const path = require('node:path');
const http = require('node:http');
使用场景对比:
| 方式 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
fs |
向后兼容、简洁 | 可能的命名冲突 | 兼容老版本Node.js |
node:fs |
明确标识核心模块、避免冲突 | 需要Node.js 14+ | 现代项目、团队开发 |
实际应用示例:
javascript
// 可能的问题:第三方模块命名冲突
// 如果安装了名为'fs'的第三方包
const fs = require('fs'); // 可能引用第三方模块
// 解决方案:使用node:前缀
const fs = require('node:fs'); // 确保使用核心模块
// ES模块中的使用
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
2. 什么是Buffer和Streams?两者有什么区别?
Buffer:二进制数据处理
javascript
// Buffer基础用法
const buffer1 = Buffer.alloc(10); // 创建10字节的buffer
const buffer2 = Buffer.from('Hello World', 'utf8'); // 从字符串创建
const buffer3 = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // 从数组创建
// Buffer操作示例
class BufferExample {
static basicOperations() {
const buf = Buffer.from('Node.js Buffer示例');
console.log('Buffer长度:', buf.length);
console.log('Buffer内容:', buf.toString('utf8'));
console.log('Buffer十六进制:', buf.toString('hex'));
console.log('Buffer Base64:', buf.toString('base64'));
// 写入数据
const writeBuf = Buffer.alloc(20);
writeBuf.write('Hello', 0, 'utf8');
writeBuf.write(' World', 5, 'utf8');
console.log('写入结果:', writeBuf.toString());
return buf;
}
static bufferConversion() {
// JSON数据的Buffer处理
const jsonData = { name: '张三', age: 25 };
const jsonString = JSON.stringify(jsonData);
const jsonBuffer = Buffer.from(jsonString, 'utf8');
console.log('原始数据:', jsonData);
console.log('Buffer大小:', jsonBuffer.length);
// 解析回JSON
const parsedData = JSON.parse(jsonBuffer.toString('utf8'));
console.log('解析结果:', parsedData);
}
}
BufferExample.basicOperations();
BufferExample.bufferConversion();
Streams:流式数据处理
javascript
const fs = require('node:fs');
const { Transform, pipeline } = require('node:stream');
const { promisify } = require('node:util');
// 可读流示例
class CustomReadableStream extends require('node:stream').Readable {
constructor(options) {
super(options);
this.current = 0;
this.max = 5;
}
_read() {
if (this.current < this.max) {
this.push(`数据块 ${this.current++}\n`);
} else {
this.push(null); // 结束流
}
}
}
// 可写流示例
class CustomWritableStream extends require('node:stream').Writable {
constructor(options) {
super(options);
this.chunks = [];
}
_write(chunk, encoding, callback) {
console.log(`接收到数据: ${chunk.toString()}`);
this.chunks.push(chunk);
callback();
}
_final(callback) {
console.log('所有数据处理完成');
console.log('总数据量:', Buffer.concat(this.chunks).length);
callback();
}
}
// 转换流示例
class UpperCaseTransform extends Transform {
_transform(chunk, encoding, callback) {
const upperChunk = chunk.toString().toUpperCase();
callback(null, upperChunk);
}
}
// 流的实际应用
async function streamExamples() {
// 文件流处理
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
const transform = new UpperCaseTransform();
// 使用pipeline处理流(推荐方式)
const pipelineAsync = promisify(pipeline);
try {
await pipelineAsync(readStream, transform, writeStream);
console.log('文件处理完成');
} catch (error) {
console.error('流处理错误:', error);
}
// 自定义流使用
const customRead = new CustomReadableStream();
const customWrite = new CustomWritableStream();
customRead.pipe(customWrite);
}
// 大文件处理示例
class LargeFileProcessor {
static async processLargeFile(inputPath, outputPath) {
const readStream = fs.createReadStream(inputPath, {
highWaterMark: 64 * 1024 // 64KB chunks
});
const writeStream = fs.createWriteStream(outputPath);
let totalBytes = 0;
let chunkCount = 0;
// 监听流事件
readStream.on('data', (chunk) => {
totalBytes += chunk.length;
chunkCount++;
console.log(`处理第 ${chunkCount} 个数据块, 大小: ${chunk.length} 字节`);
});
readStream.on('end', () => {
console.log(`文件处理完成, 总大小: ${totalBytes} 字节`);
});
readStream.on('error', (error) => {
console.error('读取错误:', error);
});
writeStream.on('error', (error) => {
console.error('写入错误:', error);
});
// 使用管道传输
readStream.pipe(writeStream);
}
}
streamExamples().catch(console.error);
Buffer vs Streams对比:
| 特性 | Buffer | Streams |
|---|---|---|
| 内存使用 | 一次性加载到内存 | 分块处理,内存效率高 |
| 适用场景 | 小文件、完整数据处理 | 大文件、实时数据 |
| 处理方式 | 同步/异步操作 | 异步流式处理 |
| 性能 | 快速随机访问 | 高吞吐量处理 |
| 复杂度 | 简单直接 | 需要理解流概念 |
文件系统操作
fs模块深度应用
javascript
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
const path = require('node:path');
class FileSystemManager {
constructor(basePath = './') {
this.basePath = basePath;
}
// 文件基础操作
async fileOperations() {
try {
// 读取文件(多种方式)
const data1 = await fsPromises.readFile('config.json', 'utf8');
console.log('异步读取:', JSON.parse(data1));
// 同步读取(谨慎使用)
const data2 = fs.readFileSync('config.json', 'utf8');
console.log('同步读取:', JSON.parse(data2));
// 写入文件
const newData = {
updated: new Date().toISOString(),
version: '1.0.1'
};
await fsPromises.writeFile('config.json', JSON.stringify(newData, null, 2));
console.log('文件写入成功');
// 追加内容
await fsPromises.appendFile('log.txt', `日志时间: ${new Date()}\n`);
} catch (error) {
console.error('文件操作错误:', error);
}
}
// 目录操作
async directoryOperations() {
const dirPath = path.join(this.basePath, 'testDir');
try {
// 创建目录
await fsPromises.mkdir(dirPath, { recursive: true });
console.log('目录创建成功');
// 读取目录内容
const files = await fsPromises.readdir(dirPath, { withFileTypes: true });
for (const file of files) {
const filePath = path.join(dirPath, file.name);
const stats = await fsPromises.stat(filePath);
console.log({
name: file.name,
isDirectory: file.isDirectory(),
isFile: file.isFile(),
size: stats.size,
created: stats.birthtime,
modified: stats.mtime
});
}
} catch (error) {
console.error('目录操作错误:', error);
}
}
// 文件监听
watchFiles(watchPath) {
const watcher = fs.watch(watchPath, { recursive: true }, (eventType, filename) => {
console.log(`文件变化: ${eventType} - ${filename}`);
if (eventType === 'change') {
this.handleFileChange(path.join(watchPath, filename));
}
});
// 优雅关闭监听
process.on('SIGINT', () => {
watcher.close();
console.log('文件监听已关闭');
process.exit(0);
});
return watcher;
}
async handleFileChange(filePath) {
try {
const stats = await fsPromises.stat(filePath);
console.log(`文件 ${filePath} 已修改,大小: ${stats.size} 字节`);
} catch (error) {
console.error('获取文件信息失败:', error);
}
}
// 文件复制和移动
async copyAndMove() {
try {
// 复制文件
await fsPromises.copyFile('source.txt', 'backup.txt');
console.log('文件复制成功');
// 重命名/移动文件
await fsPromises.rename('backup.txt', 'moved-backup.txt');
console.log('文件移动成功');
// 删除文件
await fsPromises.unlink('moved-backup.txt');
console.log('文件删除成功');
} catch (error) {
console.error('文件操作失败:', error);
}
}
}
// 高级文件处理类
class AdvancedFileProcessor {
// 批量文件处理
static async processFilesInBatch(directory, processor) {
const files = await fsPromises.readdir(directory);
const results = [];
// 并发处理(控制并发数)
const concurrency = 5;
for (let i = 0; i < files.length; i += concurrency) {
const batch = files.slice(i, i + concurrency);
const batchPromises = batch.map(file =>
processor(path.join(directory, file))
);
const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults);
}
return results;
}
// 文件压缩示例
static async compressFile(inputPath, outputPath) {
const zlib = require('node:zlib');
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
const gzipStream = zlib.createGzip();
return new Promise((resolve, reject) => {
readStream
.pipe(gzipStream)
.pipe(writeStream)
.on('finish', resolve)
.on('error', reject);
});
}
// 文件完整性检查
static async calculateChecksum(filePath, algorithm = 'sha256') {
const crypto = require('node:crypto');
const hash = crypto.createHash(algorithm);
const stream = fs.createReadStream(filePath);
for await (const chunk of stream) {
hash.update(chunk);
}
return hash.digest('hex');
}
}
// 使用示例
const fileManager = new FileSystemManager();
fileManager.fileOperations();
fileManager.directoryOperations();
path模块实用工具
javascript
const path = require('node:path');
class PathUtils {
static demonstratePathOperations() {
const filePath = '/Users/username/projects/node-app/src/index.js';
console.log('路径操作示例:');
console.log('原始路径:', filePath);
console.log('目录名:', path.dirname(filePath));
console.log('文件名:', path.basename(filePath));
console.log('扩展名:', path.extname(filePath));
console.log('解析结果:', path.parse(filePath));
// 路径拼接
const newPath = path.join('/Users', 'username', 'projects', 'new-file.txt');
console.log('拼接路径:', newPath);
// 相对路径转换
const relativePath = path.relative('/Users/username', filePath);
console.log('相对路径:', relativePath);
// 绝对路径解析
const absolutePath = path.resolve('./src', '../config.json');
console.log('绝对路径:', absolutePath);
}
// 跨平台路径处理
static crossPlatformPaths() {
// Windows: C:\Users\username\file.txt
// Unix: /home/username/file.txt
const configPath = path.join(process.cwd(), 'config', 'app.json');
const logPath = path.join(process.cwd(), 'logs', 'app.log');
console.log('配置文件路径:', configPath);
console.log('日志文件路径:', logPath);
console.log('平台分隔符:', path.sep);
console.log('路径分隔符:', path.delimiter);
}
}
PathUtils.demonstratePathOperations();
PathUtils.crossPlatformPaths();
进程管理模块
process对象详解
javascript
class ProcessManager {
constructor() {
this.setupProcessHandlers();
}
// 进程信息获取
getProcessInfo() {
const info = {
// 基础信息
pid: process.pid,
ppid: process.ppid,
platform: process.platform,
arch: process.arch,
version: process.version,
versions: process.versions,
// 运行时信息
uptime: process.uptime(),
cwd: process.cwd(),
execPath: process.execPath,
argv: process.argv,
// 内存使用情况
memoryUsage: process.memoryUsage(),
// CPU使用情况
cpuUsage: process.cpuUsage(),
// 环境变量
env: {
NODE_ENV: process.env.NODE_ENV,
PORT: process.env.PORT,
// 只显示部分环境变量
PATH: process.env.PATH ? '...(隐藏)' : undefined
}
};
return info;
}
// 命令行参数处理
parseCommandLineArgs() {
const args = process.argv.slice(2); // 去掉node和脚本路径
const parsedArgs = {};
const flags = [];
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg.startsWith('--')) {
// 长选项 --key=value 或 --key value
const [key, value] = arg.slice(2).split('=');
if (value !== undefined) {
parsedArgs[key] = value;
} else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
parsedArgs[key] = args[++i];
} else {
parsedArgs[key] = true;
}
} else if (arg.startsWith('-')) {
// 短选项 -p 3000
const key = arg.slice(1);
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
parsedArgs[key] = args[++i];
} else {
flags.push(key);
}
} else {
// 位置参数
if (!parsedArgs._) parsedArgs._ = [];
parsedArgs._.push(arg);
}
}
return { args: parsedArgs, flags };
}
// 进程信号处理
setupProcessHandlers() {
// 优雅关闭
process.on('SIGTERM', this.handleShutdown.bind(this));
process.on('SIGINT', this.handleShutdown.bind(this));
// 未捕获异常
process.on('uncaughtException', (error) => {
console.error('未捕获异常:', error);
// 记录错误后退出
this.logError(error);
process.exit(1);
});
// 未处理的Promise拒绝
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason);
console.error('在Promise:', promise);
// 可以选择退出或继续运行
this.logError(reason);
});
// 警告事件
process.on('warning', (warning) => {
console.warn('Node.js警告:', warning.name);
console.warn('消息:', warning.message);
console.warn('堆栈:', warning.stack);
});
}
async handleShutdown(signal) {
console.log(`接收到${signal}信号,开始优雅关闭...`);
try {
// 清理资源
await this.cleanup();
console.log('应用已优雅关闭');
process.exit(0);
} catch (error) {
console.error('关闭过程中出错:', error);
process.exit(1);
}
}
async cleanup() {
// 关闭数据库连接
// 停止定时器
// 完成当前请求
// 等等清理工作
console.log('执行清理工作...');
await new Promise(resolve => setTimeout(resolve, 1000));
}
logError(error) {
const errorLog = {
timestamp: new Date().toISOString(),
error: error.message,
stack: error.stack,
pid: process.pid,
memory: process.memoryUsage()
};
// 这里可以写入文件或发送到日志服务
console.error('错误详情:', JSON.stringify(errorLog, null, 2));
}
// 进程性能监控
startPerformanceMonitoring(interval = 10000) {
const monitor = setInterval(() => {
const usage = process.memoryUsage();
const cpu = process.cpuUsage();
console.log('性能指标:', {
timestamp: new Date().toISOString(),
memory: {
rss: Math.round(usage.rss / 1024 / 1024) + 'MB',
heapUsed: Math.round(usage.heapUsed / 1024 / 1024) + 'MB',
heapTotal: Math.round(usage.heapTotal / 1024 / 1024) + 'MB',
external: Math.round(usage.external / 1024 / 1024) + 'MB'
},
cpu: {
user: cpu.user,
system: cpu.system
},
uptime: Math.round(process.uptime()) + 's'
});
}, interval);
return monitor;
}
}
// 使用示例
const processManager = new ProcessManager();
console.log('进程信息:');
console.log(JSON.stringify(processManager.getProcessInfo(), null, 2));
console.log('\n命令行参数:');
console.log(processManager.parseCommandLineArgs());
// 启动性能监控
const monitor = processManager.startPerformanceMonitoring(5000);
// 5分钟后停止监控
setTimeout(() => {
clearInterval(monitor);
console.log('性能监控已停止');
}, 300000);
child_process和cluster区别详解
javascript
// child_process示例
const { spawn, exec, fork } = require('node:child_process');
const path = require('node:path');
class ChildProcessManager {
// exec使用示例 - 执行shell命令
static async executeCommand(command) {
return new Promise((resolve, reject) => {
exec(command, { timeout: 10000 }, (error, stdout, stderr) => {
if (error) {
reject({ error, stderr });
} else {
resolve(stdout);
}
});
});
}
// spawn使用示例 - 长时间运行的进程
static runLongProcess() {
const child = spawn('node', ['-e', `
setInterval(() => {
console.log('子进程运行中...', new Date().toISOString());
}, 2000);
`]);
child.stdout.on('data', (data) => {
console.log(`子进程输出: ${data}`);
});
child.stderr.on('data', (data) => {
console.error(`子进程错误: ${data}`);
});
child.on('close', (code) => {
console.log(`子进程退出,代码: ${code}`);
});
return child;
}
// fork使用示例 - Node.js子进程通信
static createWorker() {
const workerScript = `
// worker.js
process.on('message', (msg) => {
console.log('Worker收到消息:', msg);
if (msg.type === 'compute') {
const result = msg.data.reduce((sum, num) => sum + num, 0);
process.send({
type: 'result',
data: result,
workerId: process.pid
});
}
});
process.send({ type: 'ready', workerId: process.pid });
`;
// 创建临时worker文件
const fs = require('node:fs');
const workerPath = path.join(__dirname, 'temp-worker.js');
fs.writeFileSync(workerPath, workerScript);
const worker = fork(workerPath);
worker.on('message', (msg) => {
console.log('主进程收到消息:', msg);
if (msg.type === 'ready') {
// 发送计算任务
worker.send({
type: 'compute',
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
});
} else if (msg.type === 'result') {
console.log('计算结果:', msg.data);
worker.kill();
// 清理临时文件
fs.unlinkSync(workerPath);
}
});
return worker;
}
}
// cluster使用示例
const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').cpus().length;
class ClusterManager {
static setupCluster() {
if (cluster.isMaster) {
this.setupMaster();
} else {
this.setupWorker();
}
}
static setupMaster() {
console.log(`主进程 ${process.pid} 正在运行`);
// 创建工作进程
for (let i = 0; i < Math.min(4, numCPUs); i++) {
cluster.fork();
}
// 监听工作进程事件
cluster.on('online', (worker) => {
console.log(`工作进程 ${worker.process.pid} 已上线`);
});
cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
// 自动重启工作进程
if (!worker.exitedAfterDisconnect) {
console.log('重启工作进程...');
cluster.fork();
}
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('主进程收到SIGTERM信号');
for (const id in cluster.workers) {
cluster.workers[id].kill();
}
});
// 工作进程负载监控
setInterval(() => {
const workers = Object.keys(cluster.workers).length;
console.log(`当前活跃工作进程数: ${workers}`);
}, 10000);
}
static setupWorker() {
// 创建HTTP服务器
const server = http.createServer((req, res) => {
const startTime = Date.now();
// 模拟一些处理时间
setTimeout(() => {
const processTime = Date.now() - startTime;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
pid: process.pid,
timestamp: new Date().toISOString(),
processTime: processTime,
url: req.url,
method: req.method
}));
}, Math.random() * 100); // 0-100ms的随机延迟
});
server.listen(3000, () => {
console.log(`工作进程 ${process.pid} 监听端口 3000`);
});
// 优雅关闭处理
process.on('SIGTERM', () => {
console.log(`工作进程 ${process.pid} 收到SIGTERM信号`);
server.close(() => {
process.exit(0);
});
});
}
}
// 使用示例
async function demonstrateChildProcess() {
try {
// 执行系统命令
const result = await ChildProcessManager.executeCommand('ls -la');
console.log('命令执行结果:', result);
// 创建长时间运行的子进程
const longProcess = ChildProcessManager.runLongProcess();
// 5秒后终止
setTimeout(() => {
longProcess.kill();
}, 5000);
// 创建worker进程
ChildProcessManager.createWorker();
} catch (error) {
console.error('子进程操作失败:', error);
}
}
// 启动集群(需要在单独文件中运行)
// ClusterManager.setupCluster();
demonstrateChildProcess();
child_process vs cluster 对比总结:
| 特性 | child_process | cluster |
|---|---|---|
| 目的 | 通用子进程创建和管理 | 专门用于HTTP服务器集群 |
| 灵活性 | 可执行任何程序 | 仅限Node.js应用 |
| 负载均衡 | 需要手动实现 | 自动负载均衡 |
| 进程通信 | 多种方式(IPC、流、管道) | 内置IPC通信 |
| 适用场景 | 外部命令、CPU密集任务 | Web服务器、API服务 |
| 复杂度 | 需要更多手动管理 | 更高级的抽象 |
网络通信模块
HTTP服务器高级应用
javascript
const http = require('node:http');
const https = require('node:https');
const fs = require('node:fs');
const url = require('node:url');
const querystring = require('node:querystring');
class HTTPServerManager {
constructor() {
this.server = null;
this.connections = new Set();
}
// 创建基础HTTP服务器
createBasicServer(port = 3000) {
this.server = http.createServer((req, res) => {
this.handleRequest(req, res);
});
// 连接管理
this.server.on('connection', (socket) => {
this.connections.add(socket);
socket.on('close', () => {
this.connections.delete(socket);
});
});
this.server.listen(port, () => {
console.log(`HTTP服务器运行在端口 ${port}`);
});
return this.server;
}
async handleRequest(req, res) {
const startTime = Date.now();
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
const method = req.method;
// 设置通用响应头
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.setHeader('X-Powered-By', 'Node.js');
res.setHeader('Access-Control-Allow-Origin', '*');
try {
// 路由处理
if (pathname === '/' && method === 'GET') {
this.handleHome(req, res);
} else if (pathname === '/api/users' && method === 'GET') {
await this.handleGetUsers(req, res);
} else if (pathname === '/api/users' && method === 'POST') {
await this.handleCreateUser(req, res);
} else if (pathname.startsWith('/api/users/') && method === 'GET') {
const userId = pathname.split('/')[3];
await this.handleGetUser(req, res, userId);
} else if (pathname === '/upload' && method === 'POST') {
await this.handleFileUpload(req, res);
} else {
this.handleNotFound(req, res);
}
} catch (error) {
this.handleError(req, res, error);
}
// 记录请求日志
const duration = Date.now() - startTime;
console.log(`${method} ${pathname} - ${res.statusCode} - ${duration}ms`);
}
handleHome(req, res) {
const serverInfo = {
message: '欢迎使用Node.js HTTP服务器',
timestamp: new Date().toISOString(),
server: {
platform: process.platform,
nodeVersion: process.version,
pid: process.pid,
uptime: process.uptime()
},
memory: process.memoryUsage(),
endpoints: [
'GET /',
'GET /api/users',
'POST /api/users',
'GET /api/users/:id',
'POST /upload'
]
};
res.statusCode = 200;
res.end(JSON.stringify(serverInfo, null, 2));
}
async handleGetUsers(req, res) {
// 模拟从数据库获取用户
const users = [
{ id: 1, name: '张三', email: 'zhangsan@example.com', createdAt: new Date().toISOString() },
{ id: 2, name: '李四', email: 'lisi@example.com', createdAt: new Date().toISOString() }
];
// 模拟异步操作
await new Promise(resolve => setTimeout(resolve, 100));
res.statusCode = 200;
res.end(JSON.stringify({
data: users,
total: users.length,
timestamp: new Date().toISOString()
}));
}
async handleCreateUser(req, res) {
const body = await this.parseRequestBody(req);
try {
const userData = JSON.parse(body);
// 验证数据
if (!userData.name || !userData.email) {
res.statusCode = 400;
res.end(JSON.stringify({
error: '姓名和邮箱不能为空',
code: 'VALIDATION_ERROR'
}));
return;
}
// 创建新用户(模拟)
const newUser = {
id: Date.now(),
name: userData.name,
email: userData.email,
createdAt: new Date().toISOString()
};
res.statusCode = 201;
res.end(JSON.stringify({
message: '用户创建成功',
data: newUser
}));
} catch (error) {
res.statusCode = 400;
res.end(JSON.stringify({
error: '无效的JSON格式',
code: 'INVALID_JSON'
}));
}
}
async handleGetUser(req, res, userId) {
// 模拟数据库查询
await new Promise(resolve => setTimeout(resolve, 50));
if (!userId || isNaN(userId)) {
res.statusCode = 400;
res.end(JSON.stringify({
error: '无效的用户ID',
code: 'INVALID_USER_ID'
}));
return;
}
// 模拟用户数据
const user = {
id: parseInt(userId),
name: `用户${userId}`,
email: `user${userId}@example.com`,
profile: {
age: 25 + parseInt(userId),
city: '北京',
hobbies: ['阅读', '编程', '旅游']
},
createdAt: new Date().toISOString()
};
res.statusCode = 200;
res.end(JSON.stringify({
data: user,
timestamp: new Date().toISOString()
}));
}
async handleFileUpload(req, res) {
try {
const contentType = req.headers['content-type'];
if (!contentType || !contentType.includes('multipart/form-data')) {
res.statusCode = 400;
res.end(JSON.stringify({
error: '请使用multipart/form-data格式上传文件',
code: 'INVALID_CONTENT_TYPE'
}));
return;
}
const body = await this.parseRequestBody(req);
const uploadInfo = {
size: body.length,
timestamp: new Date().toISOString(),
contentType: contentType
};
// 这里应该处理实际的文件上传逻辑
// 保存文件、生成文件名等
res.statusCode = 200;
res.end(JSON.stringify({
message: '文件上传成功',
uploadInfo
}));
} catch (error) {
res.statusCode = 500;
res.end(JSON.stringify({
error: '文件上传失败',
code: 'UPLOAD_ERROR'
}));
}
}
handleNotFound(req, res) {
res.statusCode = 404;
res.end(JSON.stringify({
error: '页面未找到',
code: 'NOT_FOUND',
path: req.url,
method: req.method,
timestamp: new Date().toISOString()
}));
}
handleError(req, res, error) {
console.error('服务器错误:', error);
res.statusCode = 500;
res.end(JSON.stringify({
error: '服务器内部错误',
code: 'INTERNAL_ERROR',
timestamp: new Date().toISOString(),
// 开发环境下可以返回错误详情
...(process.env.NODE_ENV === 'development' && {
details: error.message,
stack: error.stack
})
}));
}
// 解析请求体
parseRequestBody(req) {
return new Promise((resolve, reject) => {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
resolve(body);
});
req.on('error', reject);
});
}
// 优雅关闭服务器
async gracefulShutdown() {
return new Promise((resolve) => {
console.log('开始关闭HTTP服务器...');
// 停止接受新连接
this.server.close(() => {
console.log('HTTP服务器已关闭');
resolve();
});
// 关闭现有连接
for (const connection of this.connections) {
connection.end();
}
// 5秒后强制关闭
setTimeout(() => {
for (const connection of this.connections) {
connection.destroy();
}
resolve();
}, 5000);
});
}
}
// HTTPS服务器
class HTTPSServerManager extends HTTPServerManager {
createHTTPSServer(port = 443, certOptions) {
const options = certOptions || {
key: fs.readFileSync('path/to/private-key.pem'),
cert: fs.readFileSync('path/to/certificate.pem')
};
this.server = https.createServer(options, (req, res) => {
this.handleRequest(req, res);
});
this.server.listen(port, () => {
console.log(`HTTPS服务器运行在端口 ${port}`);
});
return this.server;
}
}
// 使用示例
const httpManager = new HTTPServerManager();
httpManager.createBasicServer(3000);
// 优雅关闭处理
process.on('SIGTERM', async () => {
await httpManager.gracefulShutdown();
process.exit(0);
});
process.on('SIGINT', async () => {
await httpManager.gracefulShutdown();
process.exit(0);
});
WebSocket通信示例
javascript
// 注意:这是一个WebSocket的简化实现示例
const http = require('node:http');
const crypto = require('node:crypto');
class SimpleWebSocketServer {
constructor(port = 8080) {
this.port = port;
this.clients = new Set();
this.server = this.createServer();
}
createServer() {
const server = http.createServer();
server.on('upgrade', (request, socket, head) => {
this.handleUpgrade(request, socket, head);
});
return server;
}
handleUpgrade(request, socket, head) {
const key = request.headers['sec-websocket-key'];
const acceptKey = this.generateAcceptKey(key);
const responseHeaders = [
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
`Sec-WebSocket-Accept: ${acceptKey}`,
'',
''
].join('\r\n');
socket.write(responseHeaders);
// 创建WebSocket连接
const client = {
socket,
id: crypto.randomUUID(),
connected: true
};
this.clients.add(client);
console.log(`客户端连接: ${client.id}`);
socket.on('data', (data) => {
this.handleMessage(client, data);
});
socket.on('close', () => {
this.clients.delete(client);
console.log(`客户端断开: ${client.id}`);
});
// 发送欢迎消息
this.sendMessage(client, {
type: 'welcome',
message: '欢迎连接WebSocket服务器',
clientId: client.id
});
}
generateAcceptKey(key) {
const magicString = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const hash = crypto.createHash('sha1');
hash.update(key + magicString);
return hash.digest('base64');
}
handleMessage(client, data) {
try {
// 简化的消息解析(实际WebSocket协议更复杂)
const message = JSON.parse(data.toString());
console.log(`收到消息 from ${client.id}:`, message);
// 广播消息给所有客户端
this.broadcast({
type: 'message',
from: client.id,
data: message,
timestamp: new Date().toISOString()
}, client);
} catch (error) {
console.error('消息解析错误:', error);
}
}
sendMessage(client, message) {
if (client.connected && !client.socket.destroyed) {
const data = JSON.stringify(message);
client.socket.write(data);
}
}
broadcast(message, excludeClient = null) {
for (const client of this.clients) {
if (client !== excludeClient) {
this.sendMessage(client, message);
}
}
}
start() {
this.server.listen(this.port, () => {
console.log(`WebSocket服务器运行在端口 ${this.port}`);
});
}
}
// 使用第三方WebSocket库的示例(推荐)
// npm install ws
/*
const WebSocket = require('ws');
class WebSocketServerManager {
constructor(port = 8080) {
this.port = port;
this.wss = new WebSocket.Server({ port });
this.clients = new Map();
this.setupServer();
}
setupServer() {
this.wss.on('connection', (ws, req) => {
const clientId = crypto.randomUUID();
this.clients.set(clientId, { ws, id: clientId, ip: req.socket.remoteAddress });
console.log(`客户端连接: ${clientId} from ${req.socket.remoteAddress}`);
// 发送欢迎消息
ws.send(JSON.stringify({
type: 'welcome',
clientId,
message: '连接成功'
}));
// 处理消息
ws.on('message', (data) => {
this.handleMessage(clientId, data);
});
// 处理断开
ws.on('close', () => {
this.clients.delete(clientId);
console.log(`客户端断开: ${clientId}`);
});
// 心跳检测
const heartbeat = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
} else {
clearInterval(heartbeat);
}
}, 30000);
ws.on('pong', () => {
console.log(`收到心跳响应: ${clientId}`);
});
});
}
handleMessage(clientId, data) {
try {
const message = JSON.parse(data.toString());
console.log(`消息来自 ${clientId}:`, message);
// 根据消息类型处理
switch (message.type) {
case 'chat':
this.handleChatMessage(clientId, message);
break;
case 'broadcast':
this.handleBroadcastMessage(clientId, message);
break;
default:
console.log('未知消息类型:', message.type);
}
} catch (error) {
console.error('消息处理错误:', error);
}
}
handleChatMessage(senderId, message) {
const response = {
type: 'chat',
from: senderId,
message: message.content,
timestamp: new Date().toISOString()
};
// 发送给所有客户端
this.broadcast(response);
}
handleBroadcastMessage(senderId, message) {
const response = {
type: 'broadcast',
from: senderId,
message: message.content,
timestamp: new Date().toISOString()
};
// 发送给除发送者外的所有客户端
this.broadcast(response, senderId);
}
broadcast(message, excludeClientId = null) {
const data = JSON.stringify(message);
this.clients.forEach((client, clientId) => {
if (clientId !== excludeClientId && client.ws.readyState === WebSocket.OPEN) {
client.ws.send(data);
}
});
}
sendToClient(clientId, message) {
const client = this.clients.get(clientId);
if (client && client.ws.readyState === WebSocket.OPEN) {
client.ws.send(JSON.stringify(message));
}
}
getClientCount() {
return this.clients.size;
}
}
// 使用示例
const wsManager = new WebSocketServerManager(8080);
console.log('WebSocket服务器已启动');
// 定期广播服务器状态
setInterval(() => {
wsManager.broadcast({
type: 'server-status',
clientCount: wsManager.getClientCount(),
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
}, 60000);
*/
// 启动简化版WebSocket服务器
const wsServer = new SimpleWebSocketServer(8080);
wsServer.start();
数据处理模块
加密解密与安全
javascript
const crypto = require('node:crypto');
class CryptoUtils {
// 哈希函数
static createHash(data, algorithm = 'sha256') {
return crypto.createHash(algorithm).update(data).digest('hex');
}
// 密码哈希(带盐值)
static hashPassword(password, salt = null) {
if (!salt) {
salt = crypto.randomBytes(16).toString('hex');
}
const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512');
return {
salt,
hash: hash.toString('hex'),
combined: salt + ':' + hash.toString('hex')
};
}
// 验证密码
static verifyPassword(password, storedHash) {
const [salt, originalHash] = storedHash.split(':');
const { hash } = this.hashPassword(password, salt);
return hash === originalHash;
}
// 对称加密
static encrypt(text, key = null) {
if (!key) {
key = crypto.randomBytes(32); // 256位密钥
}
const iv = crypto.randomBytes(16); // 初始化向量
const cipher = crypto.createCipher('aes-256-cbc', key);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return {
encrypted,
key: key.toString('hex'),
iv: iv.toString('hex')
};
}
// 对称解密
static decrypt(encryptedData, key) {
const decipher = crypto.createDecipher('aes-256-cbc', Buffer.from(key, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// RSA密钥对生成
static generateRSAKeyPair() {
return crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
}
// RSA加密
static rsaEncrypt(text, publicKey) {
return crypto.publicEncrypt(publicKey, Buffer.from(text, 'utf8')).toString('base64');
}
// RSA解密
static rsaDecrypt(encryptedText, privateKey) {
return crypto.privateDecrypt(privateKey, Buffer.from(encryptedText, 'base64')).toString('utf8');
}
// 数字签名
static sign(data, privateKey) {
const sign = crypto.createSign('RSA-SHA256');
sign.update(data);
return sign.sign(privateKey, 'base64');
}
// 验证签名
static verify(data, signature, publicKey) {
const verify = crypto.createVerify('RSA-SHA256');
verify.update(data);
return verify.verify(publicKey, signature, 'base64');
}
}
// JWT令牌处理(简化版)
class JWTHelper {
static base64URLEncode(str) {
return Buffer.from(str)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
static base64URLDecode(str) {
str += new Array(5 - str.length % 4).join('=');
return Buffer.from(str.replace(/\-/g, '+').replace(/_/g, '/'), 'base64').toString();
}
static createToken(payload, secret, expiresIn = '1h') {
const header = {
alg: 'HS256',
typ: 'JWT'
};
const now = Math.floor(Date.now() / 1000);
const exp = now + (parseInt(expiresIn) * 3600); // 简化处理,假设都是小时
const tokenPayload = {
...payload,
iat: now,
exp: exp
};
const encodedHeader = this.base64URLEncode(JSON.stringify(header));
const encodedPayload = this.base64URLEncode(JSON.stringify(tokenPayload));
const signature = crypto
.createHmac('sha256', secret)
.update(encodedHeader + '.' + encodedPayload)
.digest('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
return `${encodedHeader}.${encodedPayload}.${signature}`;
}
static verifyToken(token, secret) {
try {
const [encodedHeader, encodedPayload, signature] = token.split('.');
// 验证签名
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(encodedHeader + '.' + encodedPayload)
.digest('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
if (signature !== expectedSignature) {
throw new Error('Invalid signature');
}
// 解析payload
const payload = JSON.parse(this.base64URLDecode(encodedPayload));
// 检查过期时间
const now = Math.floor(Date.now() / 1000);
if (payload.exp && payload.exp < now) {
throw new Error('Token expired');
}
return { valid: true, payload };
} catch (error) {
return { valid: false, error: error.message };
}
}
}
// 使用示例
console.log('=== 加密解密示例 ===');
// 哈希函数
const text = 'Hello Node.js Crypto';
const hash = CryptoUtils.createHash(text);
console.log('文本:', text);
console.log('SHA256哈希:', hash);
// 密码哈希
const password = 'mySecurePassword123';
const hashedPassword = CryptoUtils.hashPassword(password);
console.log('密码哈希:', hashedPassword.combined);
const isValid = CryptoUtils.verifyPassword(password, hashedPassword.combined);
console.log('密码验证:', isValid);
// 对称加密
const { encrypted, key } = CryptoUtils.encrypt('敏感数据需要加密');
console.log('加密后:', encrypted);
const decrypted = CryptoUtils.decrypt(encrypted, key);
console.log('解密后:', decrypted);
// RSA非对称加密
const { publicKey, privateKey } = CryptoUtils.generateRSAKeyPair();
const rsaEncrypted = CryptoUtils.rsaEncrypt('RSA加密测试', publicKey);
console.log('RSA加密后:', rsaEncrypted);
const rsaDecrypted = CryptoUtils.rsaDecrypt(rsaEncrypted, privateKey);
console.log('RSA解密后:', rsaDecrypted);
// 数字签名
const dataToSign = '重要文档内容';
const signature = CryptoUtils.sign(dataToSign, privateKey);
console.log('数字签名:', signature);
const signatureValid = CryptoUtils.verify(dataToSign, signature, publicKey);
console.log('签名验证:', signatureValid);
// JWT令牌
const jwtSecret = 'myJWTSecret';
const token = JWTHelper.createToken({ userId: 123, role: 'admin' }, jwtSecret, '2');
console.log('JWT令牌:', token);
const tokenVerification = JWTHelper.verifyToken(token, jwtSecret);
console.log('JWT验证:', tokenVerification);
最佳实践与常见问题
性能优化建议
javascript
class PerformanceOptimizer {
// 内存使用监控
static monitorMemoryUsage() {
const usage = process.memoryUsage();
return {
rss: Math.round(usage.rss / 1024 / 1024), // 常驻内存
heapUsed: Math.round(usage.heapUsed / 1024 / 1024), // 已用堆内存
heapTotal: Math.round(usage.heapTotal / 1024 / 1024), // 堆内存总量
external: Math.round(usage.external / 1024 / 1024), // 外部内存
arrayBuffers: Math.round(usage.arrayBuffers / 1024 / 1024) // ArrayBuffer内存
};
}
// 事件循环延迟监控
static measureEventLoopDelay() {
const { performance, PerformanceObserver } = require('perf_hooks');
return new Promise((resolve) => {
const start = performance.now();
setImmediate(() => {
const delay = performance.now() - start;
resolve(delay);
});
});
}
// 流式处理大文件
static async processLargeFileStream(inputPath, processor) {
const fs = require('node:fs');
const readline = require('node:readline');
const fileStream = fs.createReadStream(inputPath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let lineCount = 0;
for await (const line of rl) {
await processor(line, lineCount++);
// 定期让出控制权给事件循环
if (lineCount % 1000 === 0) {
await new Promise(resolve => setImmediate(resolve));
}
}
return lineCount;
}
// 对象池模式(减少GC压力)
static createObjectPool(factory, resetFn, initialSize = 10) {
const pool = [];
// 初始化对象池
for (let i = 0; i < initialSize; i++) {
pool.push(factory());
}
return {
acquire() {
return pool.length > 0 ? pool.pop() : factory();
},
release(obj) {
resetFn(obj);
pool.push(obj);
},
size() {
return pool.length;
}
};
}
}
// 错误处理最佳实践
class ErrorHandler {
constructor() {
this.setupGlobalHandlers();
}
setupGlobalHandlers() {
process.on('uncaughtException', (error) => {
console.error('未捕获异常:', error);
this.logError(error, 'UNCAUGHT_EXCEPTION');
// 优雅关闭
this.gracefulShutdown(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason);
this.logError(reason, 'UNHANDLED_REJECTION', { promise });
});
process.on('warning', (warning) => {
console.warn('Node.js警告:', warning);
this.logError(warning, 'NODE_WARNING');
});
}
logError(error, type, context = {}) {
const errorInfo = {
timestamp: new Date().toISOString(),
type,
message: error.message,
stack: error.stack,
context,
process: {
pid: process.pid,
memory: process.memoryUsage(),
uptime: process.uptime()
}
};
// 写入错误日志文件
const fs = require('node:fs');
const logFile = `error-${new Date().toISOString().split('T')[0]}.log`;
fs.appendFileSync(logFile, JSON.stringify(errorInfo) + '\n');
// 发送到监控系统
this.sendToMonitoring(errorInfo);
}
sendToMonitoring(errorInfo) {
// 这里可以集成监控系统,如Sentry、DataDog等
console.log('错误已记录到监控系统:', errorInfo.type);
}
async gracefulShutdown(code = 0) {
console.log('开始优雅关闭...');
try {
// 关闭服务器
// 关闭数据库连接
// 清理资源
setTimeout(() => {
console.log('强制退出');
process.exit(1);
}, 10000);
process.exit(code);
} catch (error) {
console.error('关闭过程出错:', error);
process.exit(1);
}
}
}
// 配置管理最佳实践
class ConfigManager {
constructor() {
this.config = this.loadConfig();
this.validateConfig();
}
loadConfig() {
const env = process.env.NODE_ENV || 'development';
const defaultConfig = {
port: 3000,
database: {
host: 'localhost',
port: 5432,
name: 'myapp'
},
redis: {
host: 'localhost',
port: 6379
},
jwt: {
expiresIn: '24h'
},
logging: {
level: 'info'
}
};
const envConfig = {
development: {
logging: { level: 'debug' }
},
production: {
port: process.env.PORT || 8080,
database: {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
name: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
},
redis: {
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '24h'
}
}
};
return this.mergeConfig(defaultConfig, envConfig[env] || {});
}
mergeConfig(defaultConfig, envConfig) {
const merged = { ...defaultConfig };
for (const [key, value] of Object.entries(envConfig)) {
if (typeof value === 'object' && !Array.isArray(value)) {
merged[key] = { ...merged[key], ...value };
} else {
merged[key] = value;
}
}
return merged;
}
validateConfig() {
const required = [
'port',
'database.host',
'database.port',
'database.name'
];
if (process.env.NODE_ENV === 'production') {
required.push(
'database.user',
'database.password',
'jwt.secret'
);
}
const missing = required.filter(path => {
const keys = path.split('.');
let current = this.config;
for (const key of keys) {
if (!current[key]) return true;
current = current[key];
}
return false;
});
if (missing.length > 0) {
throw new Error(`缺少必需配置: ${missing.join(', ')}`);
}
}
get(path, defaultValue = undefined) {
const keys = path.split('.');
let current = this.config;
for (const key of keys) {
if (!current[key]) return defaultValue;
current = current[key];
}
return current;
}
}
// 使用示例
console.log('=== 性能监控示例 ===');
console.log('内存使用:', PerformanceOptimizer.monitorMemoryUsage());
PerformanceOptimizer.measureEventLoopDelay().then(delay => {
console.log('事件循环延迟:', delay + 'ms');
});
// 对象池使用示例
const bufferPool = PerformanceOptimizer.createObjectPool(
() => Buffer.alloc(1024),
(buffer) => buffer.fill(0),
5
);
const buffer = bufferPool.acquire();
console.log('从对象池获取buffer,池大小:', bufferPool.size());
bufferPool.release(buffer);
console.log('返回buffer到对象池,池大小:', bufferPool.size());
// 初始化错误处理和配置管理
const errorHandler = new ErrorHandler();
const configManager = new ConfigManager();
console.log('应用配置:', {
port: configManager.get('port'),
dbHost: configManager.get('database.host'),
logLevel: configManager.get('logging.level')
});