本文介绍Custom Runtime的背景信息、容器环境、基本原理、配置要求、公共请求头和日志规范,您可以参见这些信息打造属于您的自定义运行环境。

背景信息

Custom Runtime是自定义运行环境。基于Custom Runtime您可以打造属于您的运行环境,例如:
  • 定制个性化语言,例如Lua。
  • 定制编程语言指定版本的运行环境,例如Node.js 16。

当您打算使用某种语言打造Custom Runtime,但是该语言不是Custom Runtime的内置语言,您需要将该语言的解析器或运行时和代码文件一起打包部署到函数计算,来实现您的预期目标。例如当运行环境是Node.js 16时,您需要先下载Node.js 16所需的解释器到代码中,然后再将打包后的代码部署到函数计算

Custom Runtime内置以下语言版本。您可以直接创建以下语言版本的Custom Runtime,无需安装第三方解释器:
  • Python 3.7.4
  • Node.js 10.16.2
  • PHP 7.4.12
  • Ruby 2.7
  • PowerShell 7.1.0
  • OpenJDK 1.8.0(Open JDK Version 1.8.0_232)

关于Custom Runtime的内置软件,请参见详细信息

容器环境

Custom Runtime的容器环境如下:
  • 操作系统版本:Debian 9。
  • 用户权限:
    • 2021年12月01日之后创建的函数,函数的执行用户为root。
    • 2021年12月01日之前创建的函数,函数的执行用户为非root。
  • 目录权限:
    • 2021年12月01日之后创建的函数,所有目录均可写。
    • 2021年12月01日之前创建的函数,只有/tmp目录可写。

基本原理

Custom Runtime本质上是自定义运行时,您只需创建一个启动目标服务(默认端口为9000的HTTP Server)的可执行文件bootstrap,然后将该文件和您的代码文件一起打成ZIP包,最后以该ZIP包作为代码包创建一个Custom Runtime的函数。该运行时可包含在函数的部署程序包内。

例如函数的程序包名称为function.zip,该运行时各个语言程序包内的文件形式和相应bootstrap文件内容如下:

.
├── bootstrap
├── demo.jar

bootstrap文件内容如下:

#!/usr/bin/env bash
java -jar demo.jar	

.
├── bootstrap
├── server.py

bootstrap文件内容如下:

#!/bin/bash
python server.py

.
├── bootstrap
├── server.js

bootstrap文件内容如下:

#!/bin/bash
node server.js

.
├── bootstrap
├── server.php

bootstrap文件内容如下:

#!/bin/bash
php server.php

说明 如果您的程序代码包内存在一个可执行文件bootstrap,函数计算将运行该文件。如果未找到该文件或该文件不可执行,则函数在被调用后将返回错误。

函数计算冷启动Custom Runtime时,会默认调用bootstrap文件启动您自定义的HTTP Server。然后这个HTTP Server接管了函数计算系统的所有请求,包括来自您的事件函数调用及HTTP函数调用。

您在开发函数具体的逻辑之前,一般会确认开发的函数是事件函数还是HTTP函数,原理如下所示:

  • 事件函数hanshujisuancustomeruntimeshijianhanshuq
  • HTTP函数customruntimehttphanshuq

HTTP Server配置要求

创建HTTP Server时您需要满足以下要求:

  • Custom Runtime启动的服务一定要监听0.0.0.0:CAPort*:CAPort端口。如果您使用127.0.0.1:CAPort端口,会导致请求超时,出现以下错误:
    {
      "ErrorCode":"FunctionNotStarted",
      "ErrorMessage":"The CA's http server cannot be started:ContainerStartDuration:25000000000. Ping CA failed due to: dial tcp 21.0.5.7:9000: getsockopt: connection refused Logs : 2019-11-29T09:53:30.859837462Z Listening on port 9000"
    }

    Custom Runtime的监听端口(CAPort) 默认是9000。如果Custom Runtime使用默认的监听端口,那么您实现的Custom Runtime的HTTP Server监听的端口也必须是9000。 如果Custom Runtime使用的监听端口是8080,那么您实现的Custom Runtime的HTTP Server监听的端口也必须是8080。

  • Custom Runtime的bootstrap文件,如果是Shell脚本一定要添加#!/bin/bash,否则会出现以下错误:
    {
      "ErrorCode":"CAExited",
        "ErrorMessage":"The CA process either cannot be started or exited:ContainerStartDuration:25037266905. CA process cannot be started or exited already: rpc error: code = 106 desc = ContainerStartDuration:25000000000. Ping CA failed due to: dial tcp 21.0.7.2:9000: i/o timeout Logs : 2019-11-29T07:27:50.759658265Z panic: standard_init_linux.go:178: exec user process caused \"exec format error\"     
    }                

    如果是二进制可执行文件,例如Go、C++直接编译出来的目标二进制文件,则不需要添加#!/bin/bash

  • Custom Runtime的bootstrap文件,一定要具备可执行权限,否则会出现以下错误:
    {
      "ErrorCode":"CAFilePermission",
        "ErrorMessage":"The CA process cannot be started due to bootstrap file don't have execute permissions
    }  
    您可以通过以下方式解决该问题:
    • 在打包文件前执行chmod +x bootstrapchmod 755 bootstrap命令。
    • 如果您使用的是Windows操作系统,您需要将bootstrap文件格式修改为UNIX格式。
  • Connection需要设置为Keep-Alive,Server端请求超时时间需设置在15分钟及以上。示例如下:
    //例如Node.js使用express时。  
    
    var server = app.listen(PORT, HOST);
    server.timeout = 0; // never timeout
    server.keepAliveTimeout = 0; // keepalive, never timeout
  • HTTP Server需要在120秒内启动完毕。

函数计算公共请求头

Custom Runtime从函数计算系统中接收到的公共请求头如下表所示。如果您需要访问阿里云其他服务,您可能需要用到临时AccessKey的Headers。如果您需要迁移已有的应用,可忽略下文的内容。

说明
  • 事件函数和HTTP函数均包含Common Headers。
  • 公共请求头是函数计算系统自动生成的,主要包含权限、函数的基本信息等。
Header 描述
x-fc-request-id Request ID。
x-fc-access-key-id 临时AccessKey ID。
x-fc-access-key-secret 临时AccessKey Secret。
x-fc-security-token 临时Security Token。
x-fc-function-handler 函数的Handler,如果Runtime本身就是函数,则该值是没有意义的。
x-fc-function-memory 函数最大能使用的内存。
x-fc-function-initializer Initializer函数的Handler,如果Runtime本身就是函数,则该值是不需要的。
x-fc-initialization-timeout Initializer函数执行的超时时间。
x-fc-region 函数所在的地域。
x-fc-account-id 函数所有者的UID。
x-fc-qualifier 函数调用时指定的服务版本或别名。更多信息,请参见灰度发布示例
x-fc-version-id 函数版本。
x-fc-service-name 函数所在的服务的名字。
x-fc-service-logproject 函数所在服务配置的日志项目。
x-fc-service-logstore 函数所在服务配置的日志仓库。
x-fc-control-path 函数的请求类型。
对于Custom Runtime或Custom Container,您可以根据Headers中的参数来判断函数调用是HTTP函数调用还是事件函数调用。参数信息如下:
  • /invoke:该请求为事件函数调用。/invoke表示是Invoke函数调用请求。
  • /http-invoke:该请求为HTTP函数调用。/http-invoke表示是HTTP invoke函数调用请求,函数计算会将您的请求(包括Path、Body和Headers)加上Common Headers后转发给Custom Runtime或Custom Container,Custom Runtime或Custom Container返回的响应头和响应体则会被返回给客户端。
  • /initialize/initialize表示第一次创建执行环境时,函数计算系统自动发起的Initialize函数调用请求。在容器的生命周期内,有且仅成功调用一次,类似于Class构造函数。

函数日志格式

推荐您在创建服务时使用日志服务SLS,Custom Runtime中所有打印到标准输出(Stdout)的日志会被自动收集到您指定的日志服务中。具体步骤,请参见配置日志

函数计算系统在其他运行环境(除Custom Runtime及Custom Container外)中调用函数时,请求头中包含x-fc-log-type" = "Tail",那么返回的响应头包含x-fc-log-result的内容就是函数执行时打印的日志,日志大小最大为4 KB。您可以在函数计算控制台函数执行结果中查看该日志。如果您希望在控制台的执行结果中看到Custom Runtime的运行日志,您需要在代码中记录请求开始和结束日志。

内容 是否必选 代码
启动Runtime
说明 该内容为函数冷启动的标志。
FunctionCompute ${runtime} runtime inited.
说明 ${runtime}可以为自定义语言类型,但最好不要使用官方的语言名称,例如Node.js、Python、PHP等。
Invoke开始的日志 FC Invoke Start RequestId: ${RequestId}
Invoke结束的日志 FC Invoke End RequestId: ${RequestId}
Initialize开始的日志
说明 如果是Initializer函数,则需要记录。
FC Initialize Start RequestId: ${RequestId}
Initialize结束的日志
说明 如果是Initializer函数,则需要记录。
FC Initialize End RequestId: ${RequestId}
除了以上特殊的信息之外,推荐您在自己的日志中包含请求ID,这样可以方便您日后诊断问题,推荐日志格式为$utcdatetime(yyyy-MM-ddTHH:mm:ss.fff) $requestId [$Level] $message
说明 不同语言下指定日志级别的接口不同,请您根据实际运行环境设置。更多信息,请参见日志记录

更多信息

Custom Runtime的限制信息,请参见资源使用限制