• 自定义函数运行时
    • 协议约定
    • 配置约定
    • 启动约定

    自定义函数运行时

    函数运行时是函数执行的载体,通过加载函数代码来调用函数,跟函数实现的语言强相关。比如python代码需要使用python runtime来调用。这里就涉及到多种语言的问题,为了统一调用接口和协议,我们最终选择了GRPC,借助其强大的跨语言IDL和高性能RPC通讯能力,打造可灵活扩展的函数计算框架。

    协议约定

    GRPC的消息和服务定义如下,开发者可直接用于生成各自编程语言的消息和服务实现,GRPC使用方法可参考make pb命令,也可参考GRPC官网的文档。

    1. syntax = "proto3";
    2. package runtime;
    3. // The runtime definition.
    4. service Runtime {
    5. // Handle handles request
    6. rpc Handle (Message) returns (Message) {} // 消息处理接口
    7. }
    8. // The request message.
    9. message Message {
    10. uint32 QOS = 1; // MQTT消息的QOS
    11. string Topic = 2; // MQTT消息的主题
    12. bytes Payload = 3; // MQTT消息的内容
    13. string FunctionName = 11; // 被调用的函数名
    14. string FunctionInvokeID = 12; // 函数调用ID
    15. }

    注意:Docker容器模式下,函数实例的资源限制不要低于50M内存,20个线程。

    配置约定

    函数配置的所有定义如下。对于自定义函数runtime,只需关注Function.Handler和Function.CodeDir的定义和使用,其他配置都是函数计算框架使用的配置。

    1. // Runtime runtime config
    2. type Runtime struct {
    3. // 模块哦诶只
    4. Module `yaml:",inline" json:",inline"`
    5. // 服务配置
    6. Server RuntimeServer `yaml:"server" json:"server"`
    7. //
    8. Function Function `yaml:"function" json:"function"`
    9. }
    10. // RuntimeServer function runtime server config
    11. type RuntimeServer struct {
    12. Address string `yaml:"address" json:"address" validate:"nonzero"`
    13. Timeout time.Duration `yaml:"timeout" json:"timeout" default:"30s"`
    14. Message struct {
    15. Length Length `yaml:"length" json:"length" default:"{\"max\":4194304}"`
    16. } `yaml:"message" json:"message"`
    17. }
    18. // Function function config
    19. type Function struct {
    20. // 函数ID,目前用于映射函数代码所在的目录
    21. ID string `yaml:"id" json:"id" validate:"regexp=^[a-zA-Z0-9_-]{1\\,140}$"`
    22. // 函数名,函数调用使用的名称
    23. Name string `yaml:"name" json:"name" validate:"regexp=^[a-zA-Z0-9_-]{1\\,140}$"`
    24. // 函数执行的入口
    25. Handler string `yaml:"handler" json:"handler" validate:"nonzero"`
    26. // 函数代码所在目录
    27. CodeDir string `yaml:"codedir" json:"codedir"`
    28. // 实例配置
    29. Instance Instance `yaml:"instance" json:"instance"`
    30. // 函数runtime,docker容器模式下是函数runtime的镜像,native进程模式下是函数runtime的可执行程序路径
    31. Entry string `yaml:"entry" json:"entry"`
    32. // 函数runtime启动进程时传入的环境变量
    33. Env map[string]string `yaml:"env" json:"env"`
    34. }
    35. // Instance instance config for function runtime module
    36. type Instance struct {
    37. // 最少实例数
    38. Min int `yaml:"min" json:"min" default:"0" validate:"min=0, max=100"`
    39. // 最多实例数
    40. Max int `yaml:"max" json:"max" default:"1" validate:"min=1, max=100"`
    41. // 实例最大空闲时间
    42. IdleTime time.Duration `yaml:"idletime" json:"idletime" default:"10m"`
    43. // 实例调用超时时间
    44. Timeout time.Duration `yaml:"timeout" json:"timeout" default:"5m"`
    45. // 实例的资源配置
    46. Resources Resources `yaml:",inline" json:",inline"`
    47. // 消息最大长度限制
    48. Message struct {
    49. Length Length `yaml:"length" json:"length" default:"{\"max\":4194304}"`
    50. } `yaml:"message" json:"message"`
    51. }

    启动约定

    函数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