Nodejs 服务启动时遇到了有问题的 js 文件,如何不让整个服务挂掉?
Nodejs 服务启动时遇到了有问题的 js 文件,如何不让整个服务挂掉?
最近在用基于 nodejs 开发的 hubot 做可配置的聊天机器人.领导要求用户前端提交 js 代码,后端生成 js 文件,然后 hubot 服务端加载生成的 js 文件来达到自定义响应的目的.但是我在开发的时候遇到了这个问题,如果提交过来的 js 代码有问题,服务端加载这个 js 文件会导致整个服务挂掉.我想到的解决方法有两种:一种是对提交过来的 js 代码做校验.这部分我做了校验括号的,不知道怎么校验类似于 if 没写 i 这种错误.还有一种就是启动服务的时候,遇到有问题的 js 文件不让服务端挂掉,但是这部分不知道该怎么实现. 希望大家能指点一下我,多谢多谢.
写的 J’s 在浏览器上先跑一下?
node.js 的代码,浏览器也能跑的吗?
感觉相当于代码批改一样。
一般是对照输入与预期输出。
但是最好是隔绝运行一次,类似的有各种代码学习网站的在线编译。
https://github.com/mattgodbolt/compiler-explorer
https://www.bytelang.com/
第一个 github 我刚也搜到啦,正在看.多谢~
pm2 了解一下
好的,多谢~
node --check input.js 这样?不过用户的输入不应该在沙箱里跑么,不应该在服务主进程环境执行呀。
先尝试生成 AST 语法树,再过一遍 eslint,有错误应该都能发现。启动服务时不加载相应 js,响应时加载呢,外围加 try catch 若有错误可以 catch 到并不会导致崩溃,如果正常加载了下次再 required 其实是缓存了。
也可以开启另一个服务专门加载 js 并执行,当前服务可以通过各种方式去请求返回数据。如果没有人工审核,其实限制不了用户提交的恶意代码产生的破坏。
直接捕获错误,然后重启服务不就行了? request 事件的都 try catch 呗
我对 nodejs 这块不是很熟悉,而且也不清楚这个 hubot 是怎么加载 js 文件的,所以这个错误不知道怎么 try catch.
- 用 vm 控制他可以使用的全局变量,
2. 让他的代码同步执行不许异步
3. 外层 try catch 捕获错误
用以上方法让他的代码用上面的方式在一个子进程里面执行。监控这个子进程运行状态(时长,cpu,内存消耗)玩意有啥问题直接 kill 掉。他代码运行结束进程间把结果通信回来。
eval 一下?
try catch
不合适就报错,就不要执行了
当然我觉得用 child_process + 沙箱 的环境跑一下是最放心的
在Node.js中,当服务启动时遇到有问题的JavaScript文件,通常会导致整个应用崩溃。为了防止这种情况,你可以使用try-catch
块、domain
模块(虽然已被废弃)或更现代的async_hooks
和cluster
模块。然而,最常用且推荐的方式是使用cluster
模块来实现主从架构,以及通过进程间通信(IPC)来管理子进程。
以下是一个简单的示例,展示如何使用cluster
模块来防止单个有问题的文件导致整个服务挂掉:
const cluster = require('cluster');
const os = require('os');
const http = require('http');
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died. Restarting...`);
cluster.fork();
});
} else {
// Workers can share any TCP connection
// In this case, it is an HTTP server
http.createServer((req, res) => {
try {
// 这里放置可能出错的代码
throw new Error('Test Error'); // 示例错误
res.writeHead(200);
res.end('Hello World\n');
} catch (err) {
console.error('Error caught in worker:', err);
res.status(500).end('Internal Server Error');
}
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
这种方式确保了即使一个子进程崩溃,其他子进程仍然可以正常运行,并且主进程会自动重启崩溃的子进程。