面试题答案
一键面试文件系统操作优化
- 使用异步操作:
- 在Node.js中,
fs
模块提供了同步和异步两种操作方式。对于高并发Web应用,应使用异步操作,如fs.readFile
、fs.writeFile
等。这是因为同步操作会阻塞事件循环,导致应用在文件操作期间无法处理其他请求,而异步操作不会阻塞,能让应用继续处理其他任务。 - 示例:
const fs = require('fs'); const util = require('util'); const readFileAsync = util.promisify(fs.readFile); const writeFileAsync = util.promisify(fs.writeFile); async function readAndWrite() { try { const data = await readFileAsync('input.txt', 'utf8'); await writeFileAsync('output.txt', data); console.log('File read and written successfully'); } catch (err) { console.error(err); } } readAndWrite();
- 在Node.js中,
- 缓存频繁读取的文件:
- 对于经常读取且内容变动不频繁的文件,可以在内存中缓存其内容。这样在后续请求中,优先从缓存中获取数据,减少文件系统的I/O操作。
- 可以使用简单的JavaScript对象作为缓存,例如:
const fileCache = {}; async function getFileContent(filePath) { if (fileCache[filePath]) { return fileCache[filePath]; } const data = await util.promisify(fs.readFile)(filePath, 'utf8'); fileCache[filePath] = data; return data; }
- 流操作:
- 当处理大文件时,使用流(stream)进行操作可以显著提高性能。流允许逐块处理数据,而不是一次性将整个文件读入内存。
- 例如,读取大文件并写入另一个文件:
const fs = require('fs'); const readableStream = fs.createReadStream('largeFile.txt'); const writableStream = fs.createWriteStream('newLargeFile.txt'); readableStream.pipe(writableStream);
数据库连接池管理
- 使用连接池库:
- 在Node.js中,对于不同的数据库有相应的连接池库。例如,对于MySQL可以使用
mysql2
库的连接池功能,对于PostgreSQL可以使用pg
库的连接池。 - 以
mysql2
为例:
const mysql = require('mysql2'); const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'password', database: 'test', connectionLimit: 10 // 设置连接池中的最大连接数 }); pool.query('SELECT * FROM users', (err, results) => { if (err) { console.error(err); return; } console.log(results); });
- 在Node.js中,对于不同的数据库有相应的连接池库。例如,对于MySQL可以使用
- 合理设置连接池参数:
- 连接池大小:根据应用的并发量和数据库服务器的性能来设置合适的连接池大小。如果连接池过小,在高并发时可能会出现连接不够用的情况;如果过大,可能会耗尽数据库服务器资源。可以通过性能测试来确定最佳的连接池大小。
- 连接超时:设置合理的连接超时时间,避免长时间等待无效连接。如果一个连接在指定时间内无法建立,应及时返回错误,避免应用一直阻塞。
- 连接复用与释放:
- 连接池中的连接应被复用,当一个请求处理完成后,将连接返回给连接池,而不是每次请求都创建新的连接。同时,要注意及时释放不再使用的连接,防止连接泄漏。在连接使用完毕后,调用相应的方法将连接归还给连接池,如
pool.releaseConnection(connection)
(不同库的方法可能略有不同)。
- 连接池中的连接应被复用,当一个请求处理完成后,将连接返回给连接池,而不是每次请求都创建新的连接。同时,要注意及时释放不再使用的连接,防止连接泄漏。在连接使用完毕后,调用相应的方法将连接归还给连接池,如
- 健康检查:
- 定期对连接池中的连接进行健康检查,确保连接的有效性。对于无效连接,及时从连接池中移除并重新创建。可以通过定时任务,定期执行简单的数据库查询(如
SELECT 1
)来检查连接是否正常。如果查询失败,说明连接无效,进行相应处理。
- 定期对连接池中的连接进行健康检查,确保连接的有效性。对于无效连接,及时从连接池中移除并重新创建。可以通过定时任务,定期执行简单的数据库查询(如