// 用子进程方案确保函数计算每次执行的时候不存在全局变量依赖问题 exports.handler = require('./index-client').handler // 线上测试方案不可行:子进程无法输出打印信息,以及 // 线上报错问题子进程退出的时候会修改本地文件系统,需要重定向到/tmp目录中 // message: Error: EROFS: read-only file system, mkdir '/code/var' // exports.handler11111 = async function (event, context, callback) { // return new Promise((resolve, reject) => { // const cluster = require('cluster') // if (cluster.isMaster) { // const fse = require('fs-extra') // // 创建子进程模拟线上请求的隔离方便global变量的使用保持与FC环境的一致性 // const worker = cluster.fork() // let __out__ = { // statusCode: 550, // } // // worker.on('message', msg => { // // console.log('111=>' + JSON.stringify(msg)) // // __out__ = msg // // }) // worker.on('exit', function (worker, code, signal) { // __out__ = fse.readJSONSync('/tmp/sub-process-out.json') // console.log('222=>' + JSON.stringify({__out__, worker, code, signal})) // // callback(null, __out__) // callback(null, __out__) // resolve() // // // 根据请求类型GET/POST/OPTIONS进行正确的HTML或AXJS请求输出响应 // // // console.log('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); // // callback(null, { // // isBase64Encoded: true, // // statusCode: 555, // // headers: { // // "Content-type": "application/json", // // }, // // // base64 encode body so it can be safely returned as JSON value // // body: new Buffer(JSON.stringify({a: 44, b: 55})).toString('base64') // // }) // // resolve() // }) // } else { // const fse = require('fs-extra') // process.on('unhandledRejection', (err) => { // // process.send({ // // statusCode: 551, // // }) // console.log('unhandledRejection', err) // fse.writeJSONSync('/tmp/sub-process-out.json', { // statusCode: 551, // }) // process.exit() // }) // process.on('uncaughtException', (err) => { // // process.send({ // // statusCode: 552, // // }) // console.log('uncaughtException', err) // fse.writeJSONSync('/tmp/sub-process-out.json', { // statusCode: 552, // }) // process.exit() // }) // // let jsonResponse = { // isBase64Encoded: true, // statusCode: 200, // headers: { // "Content-type": "application/json", // }, // // base64 encode body so it can be safely returned as JSON value // body: new Buffer(JSON.stringify({a: 1, b: new Date()})).toString('base64') // } // console.log(jsonResponse) // fse.ensureFileSync('/tmp/sub-process-out.json') // // fse.writeFileSync('/tmp/sub-process-out.json', '{"statusCode":599}') // fse.writeJSONSync('/tmp/sub-process-out.json', jsonResponse) // // process.send({a:1,b:2,c:'c'}) // // process.send(jsonResponse) // // callback(null, jsonResponse) // process.nextTick(() => { // process.exit(0) // }) // // require('./index-client').handler(event, context, (x, msg) => { // // process.send(msg) // // }).then(data => { // // process.exit() // // }) // // .catch(err => { // // // callback(null, { // // // statusCode: 553, // // // }) // // process.exit() // // }) // } // }) // } // 实验结果: // 父子进程模型在线上FC环境是不可用的目前,begg的多进程模型不可用仅可用于研发环境的单机FC线上环境模拟。 // 线上FC的环境是基于express构建的改造环境,一个容器只对应一个请求,下个请求来了会复用该容器,上次残留的全局变量也会保存下来。 // 改进方案:请求上下文的复用机制。每次请求开始的时候需要对请求上下文进行重新初始化处理,确保会话状态的一致性。 // const cluster = require('cluster') // if (cluster.isMaster) { // exports.handler = function (event, context, callback) { // console.log('xxxxxx') // console.log(11111) // const worker = cluster.fork() // console.log(22222) // worker.on('exit', function (worker, code, signal) { // console.log(22222333333) // callback(null,{statusCode:200}) // }) // } // }else{ // // 子进程此处执行无效!!FC线上环境不支持此用法。 // // console.log = ()=>{} // // console.log(33333) // } // 线上错误日志信息如下: // FC Invoke Start RequestId: 4d2b4f06-709d-552c-1560-dfa821e1058c // load code for handler:index.handler // 2018-09-15T23:14:17.882Z 4d2b4f06-709d-552c-1560-dfa821e1058c [verbose] xxxxxx // 2018-09-15T23:14:17.883Z 4d2b4f06-709d-552c-1560-dfa821e1058c [verbose] 11111 // 2018-09-15T23:14:17.900Z 4d2b4f06-709d-552c-1560-dfa821e1058c [verbose] 22222 // /var/fc/runtime/nodejs8/node_modules/mkdirp/index.js:90 // throw err0; // ^ // Error: EROFS: read-only file system, mkdir '/code/var' // at Object.fs.mkdirSync (fs.js:885:18) // at sync (/var/fc/runtime/nodejs8/node_modules/mkdirp/index.js:71:13) // at Function.sync (/var/fc/runtime/nodejs8/node_modules/mkdirp/index.js:77:24) // at newLogger (/var/fc/runtime/nodejs8/src/logger.js:22:12) // at Object. (/var/fc/runtime/nodejs8/src/logger.js:54:14) // at Module._compile (module.js:635:30) // at Object.Module._extensions..js (module.js:646:10) // at Module.load (module.js:554:32) // at tryModuleLoad (module.js:497:12) // at Function.Module._load (module.js:489:3) // 2018-09-15T23:14:18.109Z 4d2b4f06-709d-552c-1560-dfa821e1058c [verbose] 22222333333 // FC Invoke End RequestId: 4d2b4f06-709d-552c-1560-dfa821e1058c // // TODO 进一步实验调用子进程模型(这个是可行的曾经在有数图片渲染服务上验证过可行性,直接执行子进程将执行结果回传到文本文件上, // TODO 但是存在的问题日志信息没法输出问题,方案仍然不可行。) // const cross_spawn = require('cross-spawn') // // 同步系统命令调用执行 // async function xcmd(...args) { // try { // const options = {} // options.cwd = options.cwd || process.env.__ctxPath || process.cwd(); // // xassert(_.isArray(args) && args.length > 0) // const cmd = args.shift() // const ret = cross_spawn.sync(cmd, args, Object.assign({stdio: 'inherit'}, options)) // // xassert(ret.status === 0, ERR$UNKNOWN, ret) // return ret // } catch (err) { // await xwarn(err) // xthrow(err) // } // }