全部产品
阿里云办公

Node.js 运行环境

更新时间:2018-09-12 10:23:04

函数计算目前支持 Nodejs 6.10(runtime = nodejs6)和 Nodejs 8.9.0(runtime = nodejs8)运行环境。本文介绍了 Nodejs 运行环境的以下内容:

使用 logger

您的函数通过 console.log 打印的内容会被收集到创建 service 时指定的 Logstore 中,有关函数日志的更多信息,请参考 函数日志

  1. exports.handler = function (event, context, callback) {
  2. console.info(null, 'hello world');
  3. callback(null, 'hello world');
  4. };

上面的代码输出的日志内容是:

  1. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world

使用 console.warnconsole.error 分别可以打包 WARN / ERROR 级别的日志。

可以通过接口 setLogLevel 来改变日志级别,其中日志级别从高到低有如下几种

  • error:对应的接口是 console.error
  • warn:对应的接口是 console.warn
  • info:对应的接口是 console.info
  • verbose:对应的接口是 console.log
  • debug:对应的接口是 console.debug
  1. 'use strict';
  2. exports.handler = function(evt, ctx, cb) {
  3. console.setLogLevel("error");
  4. console.error("console error 1");
  5. console.info("console info 1");
  6. console.warn("console warn 1");
  7. console.log("console log 1");
  8. console.setLogLevel("warn");
  9. console.error("console error 2");
  10. console.info("console info 2");
  11. console.warn("console warn 2");
  12. console.log("console log 2");
  13. console.setLogLevel("info");
  14. cb(null, evt);
  15. };

上面的代码输出的日志内容是:

  1. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [ERROR] console error 1
  2. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [ERROR] console error 2
  3. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [WARN] console warn 2

使用内置的模块

除了 Nodejs 的标准模块,函数计算的 Nodejs 运行环境中还包含了一些常用模块,您可以直接引用,目前包含的模块有:

模块名称 版本 模块介绍 相关链接
co 4.6.0 控制流 https://github.com/tj/co
gm 1.23.0 图片处理库 https://github.com/aheckmann/gm
ali-oss 4.10.1 OSS SDK https://github.com/ali-sdk/ali-oss
ali-mns 2.6.5 MNS SDK https://github.com/InCar/ali-mns
tablestore 4.0.11 OTS SDK https://github.com/aliyun/aliyun-tablestore-nodejs-sdk
aliyun-sdk 1.10.12 Aliyun SDK https://github.com/aliyun-UED/aliyun-sdk-js
@alicloud/fc2 2.0.3 函数计算SDK https://github.com/aliyun/fc-nodejs-sdk
opencv 6.0.0 视觉算法库 https://github.com/peterbraden/node-opencv
body 5.1.0 http body 解析库 https://github.com/Raynos/body
raw-body 2.3.2 http body 解析库 https://github.com/stream-utils/raw-body

例如使用 gm 进行图片翻转的函数如下:

  1. var gm = require('gm').subClass({ imageMagick: true });
  2. exports.handler = function (event, context, callback) {
  3. gm(event)
  4. .flip()
  5. .toBuffer('PNG', function (err, buffer) {
  6. if (err) return callback(err);
  7. callback(null, buffer);
  8. });
  9. };

注意:上面的函数直接使用 event 作为图片的二进制数据并且直接把生成的图片作为二进制数据返回。

使用自定义模块

如果您需要使用自定义的模块,则需要将它们与代码一起打包。下面将演示通过 fcli 添加一个访问 mysql 的模块 mysql 的步骤:

  1. 建立一个目录用于存放代码和依赖模块:

    1. mkdir /tmp/code
  2. 新建代码文件,例如 /tmp/code/index.js ,在代码中使用 mysql:

    1. var mysql = require('mysql');
    2. exports.handler = function(event, context, callback) {
    3. var connection = mysql.createConnection({
    4. host : 'localhost',
    5. user : 'me',
    6. password : 'secret',
    7. database : 'my_db'
    8. });
    9. connection.connect();
    10. connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    11. if (error) return callback(error);
    12. console.log('The solution is: ', results[0].solution);
    13. callback(null, results[0].solution);
    14. });
    15. connection.end();
    16. };
  3. 在 /tmp/code 目录下安装依赖:

    1. cd /tmp/code
    2. npm install mysql

    安装完成之后,/tmp/code 目录的内容应该是这样:

    1. ls -l /tmp/code
    2. -rw-r--r-- 1 rockuw wheel 511 Aug 15 17:58 index.js
    3. drwxr-xr-x 13 rockuw wheel 442 Aug 15 18:01 node_modules
  4. 使用 fcli 创建函数并调用:

    1. ./fcli shell
    2. mkf my-func -h index.handler --runtime nodejs6 -d /tmp/code
    3. invk my-func

调用外部命令

用户的函数可能会用到一些工具,而这些工具并不是用 Nodejs 写的(例如 shell 脚本 / C++ 或者 go 编译出来的可执行文件)。用户仍然可以将它们与代码一起打包,然后在函数中通过运行外部命令的方法来使用它们。下面的例子中演示了如何运行一个 shell 脚本:

  1. var exec = require('child_process');
  2. exports.handler = function(event, context, callback) {
  3. var scriptPath = process.env['FC_FUNC_CODE_PATH'] + '/script.sh';
  4. exec.exec('bash '+scriptPath, {}, function(err, stdout, stderr) {
  5. if (err) return callback(err);
  6. console.log(stdout, stderr);
  7. callback(null, stdout);
  8. });
  9. };

需要注意的是,使用 C / C++ / go 编译出来的可执行文件,需要与函数计算的运行环境兼容。函数计算的 Nodejs 运行环境是:

  • Linux 内核版本:Linux 4.4.24-2.al7.x86_64
  • docker 基础镜像:docker pull node:6.10

理解 callback

Nodejs 采用异步编程的模型,用户函数必须通过调用 callback 来返回数据或者错误。如果函数中没有使用 callback,则会提示函数运行超时。

1. 确保callback被调用

如果在函数中没有调用 callback,则系统将认为函数没有结束,会等待函数结果直到超时。例如下面的函数调用时将收到超时错误:

  1. exports.handler = function(event, context, callback) {
  2. console.log('hello world');
  3. };

调用结果:

  1. {"errorMessage":"Function timed out after 3 seconds"}

2. callback 被调用后则函数结束

callback 被调用后函数就会停止运行,重复调用 callback 只接受第一次调用的结果;需确保所有任务在 callback 调用之前完成,否则它们将不会被运行。例如下面的函数,将返回 “hello world” 并且 “message” 不会 被打印:

  1. exports.handler = function(event, context, callback) {
  2. callback(null, 'hello world');
  3. callback(null, 'done');
  4. setTimeout(function() {
  5. console.log('message');
  6. }, 1000);
  7. };

错误处理

对于 Nodejs 运行环境的函数,用户可能收到两种错误,错误类型记录在返回的 HTTP Header 字段中 (X-Fc-Error-Type):

  1. HandledInvocationError:通过 callback 的第一个参数返回的错误。
  2. UnhandledInvocationError:其他错误,包括未捕获异常、超时错误和OOM(Out of memory)错误等。

    示例1 返回 HandledInvocationError

  1. exports.handler = function(event, context, callback) {
  2. callback(new Error('oops'));
  3. };

调用时收到的响应为:

  1. {
  2. "errorMessage": "oops",
  3. "errorType": "Error",
  4. "stackTrace": [
  5. "at exports.handler (/code/index.js:2:12)"
  6. ]
  7. }

示例2 返回 UnhandledInvocationError

  1. exports.handler = function(event, context, callback) {
  2. throw new Error('oops');
  3. };

调用时收到的响应为:

  1. {"errorMessage":"Process exited unexpectedly before completing request"}

有关函数计算的错误类型,请参考文章 错误类型