面试题答案
一键面试优势
- 高并发处理能力:传统阻塞I/O在进行I/O操作(如读取文件、数据库查询等)时,会阻塞当前线程,导致服务器无法处理其他请求。而Node.js的非阻塞I/O允许在I/O操作进行时,主线程继续执行后续代码,从而可以同时处理多个请求,极大地提高了服务器的并发处理能力。例如,当一个用户请求图片资源时,在读取图片文件的I/O操作过程中,服务器不会被阻塞,仍然可以处理其他用户的请求。
- 资源利用率高:由于非阻塞I/O不会长时间占用线程资源,使得服务器可以使用少量的线程来处理大量的请求。这降低了系统资源的开销,尤其是在高并发场景下,减少了线程创建、销毁以及线程上下文切换的开销。相比之下,传统阻塞I/O为每个请求分配一个线程,在高并发时线程数量过多会消耗大量系统资源。
- 响应速度快:非阻塞I/O能更快地响应客户端请求。因为即使有I/O操作在进行,服务器也能迅速返回响应,而不是等待I/O操作完成才处理下一个请求。例如在处理动态网页请求时,服务器在查询数据库获取数据的同时,可以先将已有的HTML模板返回给客户端进行渲染,而不是等数据全部获取后才返回响应。
实际应用提升性能示例
假设我们要构建一个简单的文件上传和处理Web应用。
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
let data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
// 非阻塞写入文件
const filePath = path.join(__dirname, 'uploadedFile.txt');
fs.writeFile(filePath, data, err => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error writing file');
} else {
// 非阻塞读取文件并处理
fs.readFile(filePath, 'utf8', (readErr, fileData) => {
if (readErr) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error reading file');
} else {
// 这里对文件数据进行处理,例如统计字数等
const wordCount = fileData.split(' ').length;
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`File uploaded and processed. Word count: ${wordCount}`);
}
});
}
});
});
} else {
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('Method Not Allowed');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
在这个例子中,无论是文件写入还是读取操作,都采用了非阻塞方式。在文件写入操作进行时,服务器不会被阻塞,可以继续处理其他请求;文件读取也是非阻塞的,在读取文件的同时,主线程可以处理其他任务,从而提升了整个Web应用的性能。