Custom Runtime - 打破云函数语言限制

2020-09-02 10:10:07 浏览数 (1)

| 导语 本文主要介绍腾讯云Serverless SCF云函数中Custom Runtime怎样解锁语言限制,以及通过实例说明如何使用SCF Custom Runtime。

引言

SCF作为腾讯云Faas核心产品,支持javascript, python, php, java, go等多语言函数。但是,在实际使用过程中。我们从用户方面发现以下问题:

- 更多语言支持。我们时常会收到来自内外的各种关于编程语言的咨询,比如SCF是否支持dotnet, rust, deno甚至C等多种语言环境

- 关于现有语言的功能拓展。比如PHP想要安装更多的插件,需要使用phpize来在执行环境中安装(由于部分插件可能和os library等底层库相关),但是云函数由于安全等原因,限制了函数权限等问题。 

- 关于runtime的拓展性。举个栗子, 现有SCF java语言环境是java8, 如果用户想要在SCF中使用JDK11或者更新的JDK15,有没有办法解决呢? 

- 使用成本。目前,用户如果想要自己的业务代码嵌入SCF, 需要了解SCF各个语言提供的入口函数及编程方法, 虽然我们已经尽量将使用方法和接口设计的简单,但对于一些用户来说,仍然要处理编程语言上的接口依赖,以及学习如何正确使用这些接口API。 

- 维护成本。简单来说, 如果复用现有方案,给SCF提供多语言支持,也是可行的。但是需要给每一种语言编写一套使用SCF的API,而这些API的维护成本,不仅仅是需要SCF研发同学懂得各种语言,还需要了解各个语言的安全特性,使用特性等一大堆后续维护的问题,成本确实不低。

那么, 有没有一种方法,我们只需要维护一套统一的API,而用户方面不仅能从各种编程语言上解耦,还能提供以上提出的各种问题呢?

答案是肯定滴 -- Custom Runtime

Custom Runtime简介

Custom Runtime (以下简称CR)使用起来比较简单,CR会暴露一套HTTP API提供给用户环境,用户只需要到特定端口上发送/接收 http请求,即可以获得SCF下发的各种event,并返回处理结果。具体的文档可以参考 (Custom Runtime说明)https://cloud.tencent.com/document/product/583/47274

总体来说,要使用custom runtime, 用户只需要准备以下几件事:

1. bootstrap 可执行程序: 这个可以是任何形式的Linux可执行文件,比如C语言编译出的二进制, 再比如一个简单的shell脚本。

2. 用户的事件处理函数:也就是通过CR约定的HttpAPI 实现event的获得和处理,结果返回。

3. 用户语言runtime(可选): 针对解释型语言,或者说需要runtime来运行的语言,比如js, python, dotnet等,需要用户提供自己的runtime,并在bootstrap中提供相应的启动runtime的命令。 

官网上有个利用CR实现shell云函数的例子,有兴趣的小伙伴可以看看:(本文下面也会介绍一个Deno的实例)

https://cloud.tencent.com/document/product/583/47610

Custom Runtime 具体模型及用法示例

Custom Runtime函数的内部处理流程如下:

目前Custom Runtime的实现在SCF侧是一个Http Server. 用户侧代码作为http client通过约定的API给SCF发请求来获得事件及相关信息,并发送http请求返回处理结果给SCF服务。

HttpServer 的端口号和URL,通过两个环境变量传递到云函数环境中 SCF_RUNTIME_API:SCF_RUNTIME_API_PORT 

HTTP API定义如下:具体信息,请见 https://cloud.tencent.com/document/product/583/47274

对比上面流程图, 解释如下:

1. 冷启动阶段(函数部署阶段):

- 冷启动阶段主要是部署用户代码,完成用户初始化,这个阶段SCF会在用户提供的程序包(zip包)中寻找bootstrap可执行程序,然后拉起该程序。bootstrap由用户实现,内部启动用户代码等工作。

- 用户函数在冷启动阶段需要完成代码初始化工作, 并通知SCF,初始化工作完成。即发送POST 到SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/init/ready.

- SCF服务侧接收用户ready的请求,初始化工作结束,通知上层服务。函数进入调用流程(即event此时可以下发到函数侧)

2. 热启动阶段(调用阶段)

- 函数通过GET SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/next获得 event及相关ctx信息

- SCF在函数拉取event之后, 等待用户函数返回

- 函数处理event之后, 如正常返回,通过POST SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/response 传递返回信息给SCF服务, 如函数调用出现异常(此处指业务代码需要返回错误信息), 则通过 POST SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/error 返回错误信息。

- SCF服务传递返回给上层服务,函数一次调用结束,进入下一次event调用周期。

这里我用SCF中CustomRuntime的Deno模板示例做个说明:

首先看看我的程序包里主要有啥:

- bootstrap: 入口文件,这里是shell, 可以看到红线标注这一行就是启动deno程序

- deno 二进制:Deno runtime, 启动deno程序必须的launcher

- demo.ts: 用户函数,里面就实现了上面提到的和SCF服务端交互的逻辑。也是用户业务逻辑的主要处理函数.

bootstrap的内容上面已经有了,主要是启动demo.ts, 下面我们看看demo.ts里面:

我已经把相关的解释修放在注释里了,基本上就是初始化阶段的代码。

下面看看调用怎么完成的:

可以看到就是循环通过GET (fetch)拉取event, 然后调用processEvent()进行处理

processEvent() 逻辑:

分别处理正常返回和错误返回。最后看一下我们怎么封装的这里的postData()函数:

以上就是 一个Deno函数使用SCF的Custom Runtime实现云函数的全过程。

总结

从上文可以看到以下几点:

1. CR和语言无关-> SCF和语言无关。也就是说只要可以实现一个http client,就可以通过http api的调用和SCF进行交互,从而完成云函数的事件处理及调用。

2. bootstrap是入口。也就是说,如果我用C语言实现一个http client,按照CR的约定完成与SCF的交互,我完全可以编译成一个名字叫bootstrap的二进制,然后就可以跑C的faas函数了。 

3. bootstrap可配置。用户可以在bootstrap里面启动多个进程,想怎么玩就怎么玩,当然,要符合安全,毕竟用户函数运行环境有安全限制。但是,这已经可以解决一些“云函数 agent进程”的需求。

4. 使用简单:相对于学习各个语言的函数编写规范,了解云函数对各个语言的支持。使用CR只需要学习HTTP API的使用即可。更多的语言,环境相关的问题都是用户在业务开发中使用到的,不需要额外学习。

其他

Custom Runtime 刚刚上线, 我们已经看到了一些外网客户非常活跃的关注,比如:

- 有人用custom runtime把Swift放到了SCF 里面,并做了相应的支持: https://github.com/stevapple/swift-tencent-scf-runtime

- 有人用custom runtime在SCF中跑了WASM, 并在上面做了Rust语言的支持: https://www.freecodecamp.org/news/rust-webassembly-serverless-tencent-cloud/

还有很多类似场景,我们也在不断的努力,引入更多的语言, 借助语言的生态,带动serverless的生态发展。 

最后的最后, 目前CR刚刚上线,后续还有一系列的延伸和优化, 比如拓展CR的Http server/client模式,函数不一定非得是http client,SCF服务侧也不一定非得是http server,通过这种拓展来满足不同的应用请求。再比如利用CR结合更多的SCF能力,在用户易用性方面提升,目前CR已经和SCF的层机制结合,减轻用户上传语言runtime或者语言框架的复杂度等等。 

总之,欢迎各位体验SCF Custom Runtime, 留下宝贵的意见!

无处不在的辛普森悖论

从0到1实现一款轻量级大数据分析系统

腾讯的组织能力是什么

0 人点赞