nodejs如何实现类似php的opendir目录相互隔离的fastcgi多租户虚拟空间?
网友回复
在Node.js中实现类似PHP FastCGI的多租户虚拟空间需要考虑进程隔离、文件系统隔离和资源限制。以下是完整的实现方案:
1. 主控制器(Master Process)
// master.js
const cluster = require('cluster');
const fs = require('fs');
const path = require('path');
const http = require('http');
const { Worker } = require('worker_threads');
class VirtualHostManager {
constructor() {
this.tenants = new Map();
this.workers = new Map();
}
// 注册租户
registerTenant(tenantId, config) {
this.tenants.set(tenantId, {
id: tenantId,
rootDir: config.rootDir,
uid: config.uid,
gid: config.gid,
maxMemory: config.maxMemory || 128 * 1024 * 1024, // 128MB
maxCpu: config.maxCpu || 0.5,
domain: config.domain,
port: config.port
});
}
// 为每个租户创建隔离的工作进程
spawnTenantWorker(tenantId) {
const tenant = this.tenants.get(tenantId);
if (!tenant) return;
if (cluster.isMaster) {
const worker = cluster.fork({
TENANT_ID: tenantId,
TENANT_ROOT: tenant.rootDir,
TENANT_UID: tenant.uid,
TENANT_GID: tenant.gid,
NODE_OPTIONS: `--max-old-space-size=${Math.floor(tenant.maxMemory / 1024 / 1024)}`
});
this.workers.set(tenantId, worker);
worker.on('exit', (code, signal) => {
console.log(`Tenant ${tenantId} worker died, restarting...`);
this.spawnTenantWorker(tenantId);
});
}
}
} 2. 沙箱环境(Sandbox)
// sandbox.js
const vm = require('vm');
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
class TenantSandbox {
constructor(tenantConfig) {
this.tenantId = tenantConfig.id;
this.rootDir = tenantConfig.rootDir;
this.uid = tenantConfig.uid;
this.gid = tenantConfig.gid;
this.context = this.createContext();
}
// 创建隔离的执行上下文
createContext() {
const sandbox = {
console: console,
setTimeout: setTimeout,
setInterval: setInterval,
clearTimeout: clearTimeout,
clearInterval: clearInterval,
Buffer: Buffer,
process: {
env: {},
version: process.version,
platform: process.platform,
arch: process.arch,
cwd: () => this.rootDir,
memoryUsage: process.memoryUsage
},
require: this.createSafeRequire(),
__dirname: this.rootDir,
__filename: ''
};
// 添加安全的文件系统API
sandbox.fs = this.createSafeFS();
return vm.createContext(sandbox);
}
// 创建受限的require函数
createSafeRequire() {
const allowedModules = ['http', 'https', 'url', 'querystring', 'crypto'];
return (moduleName) => {
// 只允许加载白名单模块
if (allowedModules.includes(moduleName)) {
return require(moduleName);
}
// 检查是否是相对路径模块
if (moduleName.startsWith('./') || moduleName.startsWith('../')) {
const modulePath = path.resolve(this.rootDir, moduleName);
// 确保模块在租户目录内
if (!modulePath.startsWith(this.rootDir)) {
throw new Error(`Access denied: ${moduleName}`);
}
return require(modulePath);
}
throw new Error(`Module not allowed: ${moduleName}`);
};
}
// 创建受限的文件系统API
createSafeFS() {
const safeFS = {};
const self = this;
// 包装fs方法,限制在租户目录内
const wrapFSMethod = (method) => {
return (...args) => {
// 检查路径参数
if (args[0] && typeof args[0] === 'string') {
const resolvedPath =...点击查看剩余70%


