- 自定义函数运行时
- 协议约定
- 配置约定
- 启动约定
自定义函数运行时
函数运行时是函数执行的载体,通过加载函数代码来调用函数,跟函数实现的语言强相关。比如python代码需要使用python runtime来调用。这里就涉及到多种语言的问题,为了统一调用接口和协议,我们最终选择了GRPC,借助其强大的跨语言IDL和高性能RPC通讯能力,打造可灵活扩展的函数计算框架。
协议约定
GRPC的消息和服务定义如下,开发者可直接用于生成各自编程语言的消息和服务实现,GRPC使用方法可参考make pb命令,也可参考GRPC官网的文档。
syntax = "proto3";package runtime;// The runtime definition.service Runtime {// Handle handles requestrpc Handle (Message) returns (Message) {} // 消息处理接口}// The request message.message Message {uint32 QOS = 1; // MQTT消息的QOSstring Topic = 2; // MQTT消息的主题bytes Payload = 3; // MQTT消息的内容string FunctionName = 11; // 被调用的函数名string FunctionInvokeID = 12; // 函数调用ID}
注意:Docker容器模式下,函数实例的资源限制不要低于50M内存,20个线程。
配置约定
函数配置的所有定义如下。对于自定义函数runtime,只需关注Function.Handler和Function.CodeDir的定义和使用,其他配置都是函数计算框架使用的配置。
// Runtime runtime configtype Runtime struct {// 模块哦诶只Module `yaml:",inline" json:",inline"`// 服务配置Server RuntimeServer `yaml:"server" json:"server"`//Function Function `yaml:"function" json:"function"`}// RuntimeServer function runtime server configtype RuntimeServer struct {Address string `yaml:"address" json:"address" validate:"nonzero"`Timeout time.Duration `yaml:"timeout" json:"timeout" default:"30s"`Message struct {Length Length `yaml:"length" json:"length" default:"{\"max\":4194304}"`} `yaml:"message" json:"message"`}// Function function configtype Function struct {// 函数ID,目前用于映射函数代码所在的目录ID string `yaml:"id" json:"id" validate:"regexp=^[a-zA-Z0-9_-]{1\\,140}$"`// 函数名,函数调用使用的名称Name string `yaml:"name" json:"name" validate:"regexp=^[a-zA-Z0-9_-]{1\\,140}$"`// 函数执行的入口Handler string `yaml:"handler" json:"handler" validate:"nonzero"`// 函数代码所在目录CodeDir string `yaml:"codedir" json:"codedir"`// 实例配置Instance Instance `yaml:"instance" json:"instance"`// 函数runtime,docker容器模式下是函数runtime的镜像,native进程模式下是函数runtime的可执行程序路径Entry string `yaml:"entry" json:"entry"`// 函数runtime启动进程时传入的环境变量Env map[string]string `yaml:"env" json:"env"`}// Instance instance config for function runtime moduletype Instance struct {// 最少实例数Min int `yaml:"min" json:"min" default:"0" validate:"min=0, max=100"`// 最多实例数Max int `yaml:"max" json:"max" default:"1" validate:"min=1, max=100"`// 实例最大空闲时间IdleTime time.Duration `yaml:"idletime" json:"idletime" default:"10m"`// 实例调用超时时间Timeout time.Duration `yaml:"timeout" json:"timeout" default:"5m"`// 实例的资源配置Resources Resources `yaml:",inline" json:",inline"`// 消息最大长度限制Message struct {Length Length `yaml:"length" json:"length" default:"{\"max\":4194304}"`} `yaml:"message" json:"message"`}
启动约定
函数runtime实际上也是一种模块,只是比较特殊,是被函数计算模块在运行过程中按需启动的模块,归为临时模块。其启动方式和普通模块启动的方式基本一致,只不过临时模块没有固定路径,不支持从配置文件中加载配置。因此约定通过传参的方式传入配置信息,使用JSON格式,比如-c "{\"name\":\"sayhi\", …}"。
函数runtime启动并加载配置后,首先根据Server配置初始化GRPC server,然后根据Function的配置加载函数代码入口,等待函数计算模块来调用,最后注意监听SIGTERM信号来优雅退出。完整的实现过程可参考python27 runtime。
最后更新于 2018-12-28 10:23:09
原文: https://openedge.tech/docs/customize/How-to-develop-a-customize-runtime-for-function
