面试题答案
一键面试检测故障
- 节点宕机检测
- 使用Node.js的内置模块
cluster
来管理多进程应用。cluster
模块提供了worker.on('exit', function(code, signal) {...})
事件,在工作进程(worker)退出时可以触发,通过这个事件可以检测到某个节点(工作进程所代表的逻辑节点)是否宕机。例如:
const cluster = require('cluster'); if (cluster.isMaster) { for (let i = 0; i < require('os').cpus().length; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); // 这里可以记录宕机日志等操作 }); } else { // 工作进程逻辑 }
- 使用Node.js的内置模块
- 网络分区检测
- 可以利用
ping
命令来检测网络连接状态。在Node.js中,可以使用child_process
模块调用系统的ping
命令。例如:
const { exec } = require('child_process'); function checkNetworkConnectivity(host) { return new Promise((resolve, reject) => { const command = `ping -c 1 ${host}`; exec(command, (error, stdout, stderr) => { if (error) { reject(error); return; } if (stdout.includes('1 received')) { resolve(true); } else { resolve(false); } }); }); } // 定时调用检查网络连接 setInterval(() => { checkNetworkConnectivity('google.com').then(isConnected => { if (!isConnected) { console.log('可能发生网络分区'); // 这里可以记录网络分区日志等操作 } }).catch(console.error); }, 5000);
- 可以利用
数据恢复
- 基于日志的恢复
- 在进行文件操作时,记录每一个关键的文件操作日志,例如创建文件、写入数据、删除文件等操作。可以使用Node.js的
fs.writeFile
来记录日志文件。例如:
const fs = require('fs'); const path = require('path'); const logFilePath = path.join(__dirname, 'file_operation_log.txt'); function logFileOperation(operation, filePath, data = null) { const logEntry = `${new Date().toISOString()} - ${operation}: ${filePath}`; if (data) { logEntry += ` - Data: ${JSON.stringify(data)}`; } fs.writeFile(logFilePath, logEntry + '\n', { flag: 'a' }, (err) => { if (err) { console.error('记录日志失败:', err); } }); } // 在文件操作函数中调用日志记录 function writeFileSafe(filePath, data) { logFileOperation('writeFile', filePath, data); fs.writeFile(filePath, data, (err) => { if (err) { console.error('写入文件失败:', err); } }); }
- 当发生故障后,可以读取日志文件,按照日志记录的操作顺序重新执行未完成的操作来恢复数据。例如:
fs.readFile(logFilePath, 'utf8', (err, data) => { if (err) { console.error('读取日志文件失败:', err); return; } const logLines = data.split('\n'); logLines.forEach((line) => { if (line) { const parts = line.split(' - '); const operation = parts[1].split(': ')[0]; const filePath = parts[1].split(': ')[1]; if (operation === 'writeFile') { const dataPart = parts[2].split(' - Data: ')[1]; const data = JSON.parse(dataPart); fs.writeFile(filePath, data, (err) => { if (err) { console.error('根据日志恢复写入文件失败:', err); } }); } } }); });
- 在进行文件操作时,记录每一个关键的文件操作日志,例如创建文件、写入数据、删除文件等操作。可以使用Node.js的
- 数据备份与恢复
- 定期对重要文件进行备份,可以使用
fs.copyFile
方法。例如:
const backupDir = path.join(__dirname, 'backups'); if (!fs.existsSync(backupDir)) { fs.mkdirSync(backupDir); } function backupFile(filePath) { const backupFilePath = path.join(backupDir, path.basename(filePath) + '_' + new Date().getTime()); fs.copyFile(filePath, backupFilePath, (err) => { if (err) { console.error('备份文件失败:', err); } }); } // 定时备份 setInterval(() => { const importantFiles = ['file1.txt', 'file2.txt']; importantFiles.forEach((file) => { backupFile(file); }); }, 60 * 1000);
- 当发生故障导致文件损坏或丢失时,可以从备份文件中恢复数据。例如:
function restoreFileFromBackup(filePath) { const backupDir = path.join(__dirname, 'backups'); const backupFiles = fs.readdirSync(backupDir).filter((file) => file.includes(path.basename(filePath))); if (backupFiles.length > 0) { const latestBackup = backupFiles.sort().pop(); const backupFilePath = path.join(backupDir, latestBackup); fs.copyFile(backupFilePath, filePath, (err) => { if (err) { console.error('从备份恢复文件失败:', err); } }); } else { console.error('没有找到备份文件来恢复'); } }
- 定期对重要文件进行备份,可以使用
防止数据丢失或损坏
- 文件操作原子性
- 对于一些关键的文件写入操作,使用
fs.writeFileSync
结合临时文件的方式来保证原子性。例如:
function writeFileAtomically(filePath, data) { const tempFilePath = filePath + '.tmp'; try { fs.writeFileSync(tempFilePath, data); fs.renameSync(tempFilePath, filePath); } catch (err) { // 如果操作失败,删除临时文件 if (fs.existsSync(tempFilePath)) { fs.unlinkSync(tempFilePath); } console.error('原子性写入文件失败:', err); } }
- 对于一些关键的文件写入操作,使用
- 数据校验
- 在写入数据时,可以计算数据的哈希值并一同存储。例如使用
crypto
模块计算SHA - 256哈希值:
const crypto = require('crypto'); function writeFileWithHash(filePath, data) { const hash = crypto.createHash('sha256').update(data).digest('hex'); const combinedData = `${data}\nHash: ${hash}`; fs.writeFile(filePath, combinedData, (err) => { if (err) { console.error('写入文件并记录哈希失败:', err); } }); }
- 在读取文件时,重新计算哈希值并与存储的哈希值进行比对,以验证数据的完整性。例如:
function readFileAndVerify(filePath) { fs.readFile(filePath, 'utf8', (err, data) => { if (err) { console.error('读取文件失败:', err); return; } const parts = data.split('\nHash: '); const originalData = parts[0]; const storedHash = parts[1]; const calculatedHash = crypto.createHash('sha256').update(originalData).digest('hex'); if (calculatedHash === storedHash) { console.log('数据完整性验证通过'); } else { console.log('数据可能已损坏'); } }); }
- 在写入数据时,可以计算数据的哈希值并一同存储。例如使用