函数计算在实例中调用您的函数,该实例提供一个安全和隔离的运行时环境。函数计算基于实例生命周期增加多种回调操作,有效解决传统应用迁移至Serverless架构时遇到的指标数据延迟或丢失等痛点。本文介绍函数实例生命周期、如何配置实例周期回调函数及回调函数日志查询。
实例生命周期介绍
如上图所示,函数计算的实例生命周期可分为构建阶段(Creating)、调用阶段(Invoke)和销毁阶段(Destroy)。
构建阶段(Creating)
在构建阶段,函数计算会按照顺序执行三项任务:
实例创建(Instance Create)
运行时初始化(Runtime Initialization)
运行函数配置的Init回调方法(Init Hook)
当您使用预留模式时,函数计算会在您设置预留实例后,立即启动函数实例并执行
Creating
流程。此时可能还没有函数调用,因此运行时初始化、Init回调和调用阶段之间可能会存在较长时间的间隔。当您使用按量模式时,函数计算在收到请求出发后,立即执行
Creating
初始化流程,如果函数有配置Init回调方法,会先执行完Init回调后再执行Invoke
流程。对一个函数实例,函数配置的Init回调方法只会执行一次,如果执行失败,会重新启动一个函数实例执行
Init
流程,Init
回调失败的实例会直接销毁。调用阶段(Invoke)
在调用阶段,函数计算支持的标准运行时,一个实例在同一时间只会执行一个请求。自定义运行时或自定义容器运行时,一个实例在同一时间可以执行多个请求。您可以通过设置单实例多并发实现,具体操作,请参见设置实例并发度。
销毁阶段(Destroy)
如果函数实例在一段时间内没有收到任何调用,则触发此阶段。在销毁阶段,函数计算会先执行PreStop回调方法。您可以在PreStop回调方法中执行一些清理任务。
实例冻结机制
在没有调用请求时,函数计算会将实例冻结(Freeze),当新的请求来到时,函数计算会将实例解冻(Thaw)。如下图所示。
实例冻结主要发生在以下两种情况。
实例初始化阶段完成后,调用阶段前。
函数一次调用阶段结束后,下一次调用阶段前。
在一次调用阶段完成后,函数计算将冻结函数实例,程序中的后台进程、线程或协程无法继续运行,异步日志也可能没有写入成功。
当您使用预留实例,且没有开启闲置计费功能时,实例不会进行冻结操作。
使用限制
所有运行时均支持Initialize和PreStop回调方法。
PreStop回调方法的输入参数没有event参数。
PreStop回调函数无返回值,在函数末尾增加返回逻辑无效。
如果使用Java Runtime,您需要将fc-java-core更新至1.4.0及以上版本,否则无法使用PreStop扩展回调函数。
当函数执行返回时,函数计算将冻结函数实例,用户不可假设调用返回时所有异步进程、线程、协程等执行完成,也不可假设本次异步写入的日志被刷新。
前提条件
已完成函数的创建,具体请参见创建函数。
配置实例生命周期回调方法
唤起PreStop中产生的费用计费方式与InvokeFunction计费方式一致。具体信息,请参见计费说明。
通过控制台配置回调
当您使用控制台创建函数时,函数计算不支持您PreStop回调,您需要在更新函数时配置该回调函数。
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数详情页,选择配置页签,然后在左侧导航栏,选择生命周期,然后单击编辑。
在编辑生命周期面板,设置回调程序和回调超时时间,然后单击确定。
说明每一个扩展函数都需要配置单独的回调程序和超时时间,其中回调程序格式为[文件名].[扩展函数名]。例如在Python Runtime中,创建函数时指定的PreStop回调为index.preStop,那么文件名为index.py,PreStop函数名为preStop。
配置回调函数后,您需要在代码执行中实现对应的函数。
单击代码页签,在代码编辑区域,输入扩展函数代码。
例如,您配置的PreStop回调程序为
index.preStop
,则需要实现preStop函数。不同语言运行时实现函数实例生命周期回调的方法请参见函数实例生命周期回调方法。说明在线IDE支持PHP、Python、Node.js和Custom Runtime;但不支持Java、Go和.NET这类编译性语言,以及Custom Container。
单击代码编辑器上方的部署代码,然后单击测试函数。
通过Serverless Devs配置回调
使用Serverless Devs配置PreStop扩展函数时,s.yaml
配置文件示例代码片段如下所示:
codeUri: './code.zip'
......
instanceLifecycleConfig:
preStop:
handler: index.PreStop
timeout: 60
如果您需要关闭某个扩展函数,需要将扩展函数的handler
参数显示置空,否则后端默认不更新。例如关闭PreStop函数,您需要按照以下配置进行部署更新,此时PreStop函数的timeout
参数已无效。
codeUri: './code.zip'
......
instanceLifecycleConfig:
preStop:
handler: ""
timeout: 60
不同语言运行时实现函数实例生命周期回调的方法请参见函数实例生命周期回调方法。
通过SDK配置回调
您可以通过SDK部署和更新扩展函数。本文介绍如何获取在创建函数时配置PreFreeze函数的SDK示例代码。
进入CreateFunction - 创建函数页面,单击调试,进入OpenAPI门户。
在参数配置页签,根据需要创建函数的基本信息填写输入参数。
其中您可以在实例生命周期函数配置
instanceLifecycleConfig
字段配置PreStop回调。参数配置完成后,单击SDK 示例页签,从而获取对应语言的SDK示例代码。
不同语言运行时实现函数实例生命周期回调的方法请参见函数实例生命周期回调方法。
函数实例生命周期回调方法
函数计算中所有运行时均支持Initialize和PreStop两种回调方法。运行时实现函数实例生命周期回调的方法请参考以下内容。
运行时 | 描述 | 参考文档 |
Node.js | 通过Node.js实现并应用函数实例生命周期回调方法。 | |
Python | 通过Python实现并应用函数实例生命周期回调方法。 | |
PHP | 通过PHP实现并应用函数实例生命周期回调方法。 | |
Java | 通过Java运行时实现函数实例生命周期回调的方法。 | |
C# | 通过C#运行时实现函数实例生命周期回调的方法。 | |
Go | 通过Go实现函数实例生命周期回调的方法。 | |
Custom Runtime | 通过Custom Runtime实现函数实例生命周期回调的方法。 | |
Custom Container | 通过Custom Container Runtime实现函数实例生命周期回调的方法。 |
查询回调函数相关日志
配置函数实例生命周期回调并执行代码实现对应的回调函数后,您可以查询实例生命周期回调函数的相关日志。
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数详情页,选择日志页签,然后在调用请求页签,单击目标请求行右侧操作列的高级日志。
您可以使用复制的实例ID,查询所有生命周期回调函数的Start/End日志;还可以使用
实例ID+函数实例生命周期回调关键字
查询指定回调函数的Start/End日志,例如,c-62833f38-20f1629801fa4bd***** and PreStop
。此外,您还可以根据Start/End日志中的RequestId查询请求的日志信息。如果用户日志中没有RequestId,可以单击该日志中的图标获取上下文日志。
计费说明
实例生命周期回调方法的请求数不计费。其他费用与实例调用阶段的计费逻辑相同。计费时间的统计如下图所示
关于计费方式的具体信息,请参见计费概述。