使用函数 initializer 接口优化应用层冷启动-阿里云开发者社区
优采云 发布时间: 2020-08-20 04:24使用函数 initializer 接口优化应用层冷启动-阿里云开发者社区
使用函数 initializer 接口优化应用层冷启动
_柳下2018-11-021641浏览量
简介:背景用户函数调用链路包括以下几个阶段:1)系统为函数分配估算资源;2)下载代码;3)启动容器并加载函数代码;4)用户函数内部进行初始化逻辑;5)函数处理恳求并将结果返回。其中1,2,3步是系统层面的冷启动开支,通过对调度以及各个环节的优化,函数估算(FC)能做到负载快速下降时稳定的延时,细节详见 函数估算系统冷启动优化。
背景
用户函数调用链路包括以下几个阶段:1)系统为函数分配估算资源;2)下载代码;3)启动容器并加载函数代码;4)用户函数内部进行初始化逻辑;5)函数处理恳求并将结果返回。其中1,2,3步是系统层面的冷启动开支,通过对调度以及各个环节的优化,函数估算(FC)能做到负载快速下降时稳定的延时,细节详见 函数估算系统冷启动优化。第4步是函数内部初始化逻辑,属于应用层面的冷启动开支,例如深度学习场景下加载尺寸较大的模型、数据库场景下连接池建立、函数依赖库加载等等。为了减少应用层冷启动对延时的影响,函数估算推出了 initializer 接口,系统能辨识用户函数的初始化逻辑,从而在调度上做相应的优化。
功能简介
现在用户能为函数设置 initializer 和 handler 两个入口,分别对应初始化逻辑和恳求处理逻辑。系统首先调用 initializer 完成函数的初始化,成功后再调用 handler 处理恳求。Initializer 是可选的,用户也可不实现,此时系统将跳过 initializer,直接调用 handler 处理恳求。
引入 initializer 接口的价值:
Initializer 接口规范
各个 runtime 的 initializer 接口有以下共性:
支持 runtime
下文将对各个 runtime 的 initializer 编写规则进行介绍:
python
当使用 Python 进行编程时,可参考下边示例:
# file :main.py
# initializer: main.my_initializer
def my_initializer(context):
print("hello world!")
更多细节请参考 python 函数入口。
nodejs
当使用 Nodejs 进行编程时,可参考下边示例:
// file :main.php
// initializer : main.my_initializer
exports.my_initializer = function(context, callback) {
console.log('hello world!');
callback(null, '');
};
更多细节请参考 nodejs 函数入口。
php
当使用 Php 进行编程时,可参考下边示例:
// file: main.js
// initializer: main.my_initializer
更多细节请参考 php 函数入口。
java
java 针对流式输入和通过形参的形式自定义输入和输出的两种函数方式都支持 initializer,当须要在 JAVA runtime 中添加 initializer 功能时,需在原有的函数结构基础上额外实现 initializer 预定义的插口。
一个简单的流式输入和 initializer 结合的示例如下:
package example;
import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.FunctionComputeLogger;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.fc.runtime.FunctionInitializer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class HelloFC implements StreamRequestHandler, FunctionInitializer {
@Override
public void initialize(Context context) {
FunctionComputeLogger logger = context.getLogger();
logger.debug(String.format("RequestID is %s %n", context.getRequestId()));
}
@Override
public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
FunctionComputeLogger logger = context.getLogger();
logger.debug(String.format("RequestID is %s %n", context.getRequestId()));
output.write(new String("hello world!").getBytes());
output.flush();
}
}
开发手册
当使用 initializer 接口时,可以通过 API、SDK、控制台、函数估算提供的丰富工具链(fcli、fun等工具)进行创建和更新。
SDK 开发
支持 initializer 的 SDK 有 Nodejs、Python、Php、Java 。以 Nodejs runtime 和 Php SDK 结合为例,创建 initializer 并进行更新操作。
对 initializer 的更新可以从有更新到无,即关掉 initializer 功能。也可以从无更新到有,即开启 initializer 功能。
// file: main.js
exports.initializer = function(context, callback) {
console.log('hello initializer!');
callback(null, "");
};
exports.handler = function(event, context, callback) {
callback(null, string("initializer"));
};
// file: new_main.js
exports.newInitializer = function(context, callback) {
console.log('hello new initializer!');
callback(null, "");
};
exports.handler = function(event, context, callback) {
callback(null, string("new initializer"));
};
<p>