您现在的位置是:网站首页 > 网络性能优化文章详情
网络性能优化
陈川
【
Node.js
】
36202人已围观
7055字
网络性能优化的核心目标
网络性能优化的核心目标是减少延迟、提高吞吐量、降低资源消耗。在Node.js环境中,这涉及到从代码层面到架构层面的多方面调整。一个典型的例子是减少不必要的I/O操作,比如使用内存缓存代替频繁的数据库查询:
const cache = new Map();
async function getCachedData(key) {
if (cache.has(key)) {
return cache.get(key);
}
const data = await fetchDataFromDB(key);
cache.set(key, data);
return data;
}
HTTP/2的优势与应用
HTTP/2的多路复用特性可以显著提升网络性能。在Node.js中启用HTTP/2非常简单:
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('<h1>Hello HTTP/2!</h1>');
});
server.listen(443);
连接池管理策略
数据库连接池的合理配置对性能影响巨大。以下是一个PostgreSQL连接池的优化示例:
const { Pool } = require('pg');
const pool = new Pool({
user: 'dbuser',
host: 'database.server.com',
database: 'mydb',
password: 'secretpassword',
port: 5432,
max: 20, // 最大连接数
idleTimeoutMillis: 30000, // 空闲连接超时
connectionTimeoutMillis: 2000 // 连接超时
});
async function query(text, params) {
const start = Date.now();
const res = await pool.query(text, params);
const duration = Date.now() - start;
console.log('Executed query', { text, duration, rows: res.rowCount });
return res;
}
压缩技术的实现
Node.js内置支持多种压缩算法。以下是使用Brotli压缩的示例:
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
http.createServer((req, res) => {
const raw = fs.createReadStream('index.html');
const acceptEncoding = req.headers['accept-encoding'] || '';
res.setHeader('Vary', 'Accept-Encoding');
if (acceptEncoding.includes('br')) {
res.setHeader('Content-Encoding', 'br');
raw.pipe(zlib.createBrotliCompress()).pipe(res);
} else if (acceptEncoding.includes('gzip')) {
res.setHeader('Content-Encoding', 'gzip');
raw.pipe(zlib.createGzip()).pipe(res);
} else {
raw.pipe(res);
}
}).listen(3000);
负载均衡配置
使用cluster模块实现多进程负载均衡:
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
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\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
缓存策略的深度优化
实现多级缓存策略可以大幅提升性能:
const NodeCache = require('node-cache');
const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });
async function getProductDetails(productId) {
const cacheKey = `product_${productId}`;
let product = myCache.get(cacheKey);
if (!product) {
product = await fetchFromDatabase(productId);
// 设置缓存,并添加过期回调
myCache.set(cacheKey, product, 3600, (key, value) => {
console.log(`Cache expired for ${key}`);
// 可以在这里实现写回逻辑
});
}
return product;
}
流式处理的优势
处理大文件时流式API可以显著降低内存使用:
const fs = require('fs');
const zlib = require('zlib');
const { pipeline } = require('stream');
// 传统方式(内存消耗大)
// fs.readFile('largefile.txt', (err, data) => {
// if (err) throw err;
// const compressed = zlib.gzipSync(data);
// fs.writeFile('largefile.txt.gz', compressed);
// });
// 流式处理
pipeline(
fs.createReadStream('largefile.txt'),
zlib.createGzip(),
fs.createWriteStream('largefile.txt.gz'),
(err) => {
if (err) {
console.error('Pipeline failed', err);
} else {
console.log('Pipeline succeeded');
}
}
);
DNS查询优化
Node.js中的DNS缓存策略:
const dns = require('dns');
const { promisify } = require('util');
const resolve4 = promisify(dns.resolve4);
// 自定义缓存实现
const dnsCache = new Map();
async function cachedDnsLookup(hostname) {
if (dnsCache.has(hostname)) {
return dnsCache.get(hostname);
}
const addresses = await resolve4(hostname);
dnsCache.set(hostname, addresses);
// 设置5分钟缓存
setTimeout(() => {
dnsCache.delete(hostname);
}, 300000);
return addresses;
}
请求批处理技术
合并多个小请求可以显著减少网络开销:
class BatchProcessor {
constructor() {
this.queue = [];
this.timeout = null;
this.batchSize = 10;
this.timeoutMs = 50;
}
addRequest(request) {
return new Promise((resolve) => {
this.queue.push({ request, resolve });
if (this.queue.length >= this.batchSize) {
this.processBatch();
} else if (!this.timeout) {
this.timeout = setTimeout(() => this.processBatch(), this.timeoutMs);
}
});
}
async processBatch() {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
const currentBatch = this.queue.splice(0, this.batchSize);
if (currentBatch.length === 0) return;
const batchResults = await processMultipleRequests(
currentBatch.map(item => item.request)
);
currentBatch.forEach((item, index) => {
item.resolve(batchResults[index]);
});
}
}
性能监控与分析
使用Performance Hooks进行细粒度性能监控:
const { PerformanceObserver, performance } = require('perf_hooks');
const obs = new PerformanceObserver((items) => {
items.getEntries().forEach((entry) => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
obs.observe({ entryTypes: ['measure'] });
// 标记重要操作的时间点
performance.mark('A');
// 执行一些操作
performance.mark('B');
performance.measure('A to B', 'A', 'B');
现代JavaScript特性优化
利用现代JS特性提升执行效率:
// 使用Map代替普通对象作为字典
const cache = new Map();
// 使用WeakMap存储私有数据
const privateData = new WeakMap();
class MyClass {
constructor() {
privateData.set(this, {
secret: 42
});
}
getSecret() {
return privateData.get(this).secret;
}
}
// 使用BigInt处理大整数
const bigNumber = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1);
事件循环优化技巧
合理利用事件循环各阶段:
// 将CPU密集型任务拆分到多个tick中
function processChunk(chunk, callback) {
// 处理一小块数据
// ...
if (moreToProcess) {
// 使用setImmediate将剩余工作放到下一个事件循环迭代
setImmediate(() => processChunk(nextChunk, callback));
} else {
callback();
}
}
// 优先使用setImmediate而不是process.nextTick
// 避免I/O饥饿
setImmediate(() => {
console.log('This runs in the check phase');
});
内存管理最佳实践
避免内存泄漏的常见模式:
// 正确的事件监听器管理
class EventEmitterExample {
constructor() {
this.listeners = new Set();
}
addListener(fn) {
this.listeners.add(fn);
return () => this.listeners.delete(fn);
}
emit(data) {
for (const listener of this.listeners) {
listener(data);
}
}
}
// 使用WeakRef避免保持不必要的引用
const weakRef = new WeakRef(largeObject);
// 当需要时检查对象是否还存在
const deref = weakRef.deref();
if (deref) {
// 对象仍然存在
}
上一篇: DNS解析
下一篇: RESTful API设计