導(dǎo)語 | 云函數(shù)SCF是騰訊云為企業(yè)和開發(fā)者們提供的無服務(wù)器執(zhí)行環(huán)境,幫助大家在無需購買和管理服務(wù)器的情況下運行代碼。但是SCF在使用過程中經(jīng)常會受到開發(fā)語言方面的限制,造成拓展性和成本上的問題。本文就將為大家介紹使用Custom Runtime來解鎖SCF語言限制,希望與大家一同交流。文章作者:臧琳,騰訊云Serverless 研發(fā)工程師。
一、背景
SCF作為騰訊云FaaS核心產(chǎn)品,支持javascript、python、php、java、go等多語言函數(shù)。但是,在用戶實際使用過程中,我們發(fā)現(xiàn)了一些問題:
1.尋求更多語言支持
我們時常會收到來自內(nèi)外的各種關(guān)于編程語言的咨詢,比如SCF是否支持dotnet、rust、deno甚至C等多種語言環(huán)境。
2.關(guān)于現(xiàn)有語言的功能拓展
比如php想要安裝更多的插件,就需要在執(zhí)行環(huán)境中使用phpize來安裝(因為部分插件可能和os library等底層庫相關(guān)),但是云函數(shù)因為安全等原因,限制了相關(guān)權(quán)限。
3.關(guān)于Runtime的拓展性
舉個例子,現(xiàn)有SCF java的語言環(huán)境是java8,如果用戶想要在SCF中使用JDK11或者更新的JDK15,有沒有辦法解決呢?
4.使用成本
目前,用戶如果想要在自己的業(yè)務(wù)代碼中嵌入SCF,需要了解SCF各個語言提供的入口函數(shù)及編程方法。雖然我們已經(jīng)盡量將使用方法和接口設(shè)計得簡單,但對于一些用戶來說,仍然要處理編程語言上的接口依賴,以及學(xué)習(xí)如何正確使用這些接口API。
5.維護成本
簡單來說,如果復(fù)用現(xiàn)有方案,給SCF提供多語言支持其實是可行的,但是需要給每一種語言編寫一套使用SCF的API。這不僅僅需要SCF研發(fā)同學(xué)懂得各種語言,還需要他們了解各個語言的安全特性,使用特性等,維護成本很高。
那么,有沒有一種方法能夠讓我們只需要維護一套統(tǒng)一的API,就能讓用戶從各種編程語言中解耦,還能解決上述列舉的各項問題呢?答案就在于使用——Custom Runtime。
二、Custom Runtime簡介
Custom Runtime(以下簡稱CR)使用方法較為簡單:CR會暴露一套HTTP API提供給用戶環(huán)境,而用戶只需要到特定端口上發(fā)送/接收HTTP請求,即可以獲得SCF下發(fā)的各種event,并返回處理結(jié)果。具體的文檔可以參考:Custom Runtime說明[1]。
總體來說,要使用Custom Runtime,用戶需要做好以下準(zhǔn)備:
1.bootstrap可執(zhí)行程序
此執(zhí)行程序可以是任何形式的Linux可執(zhí)行文件,比如C語言編譯出的二進制文件,或者是一個簡單的shell腳本。
2.用戶的事件處理函數(shù)
也就是通過CR約定的HTTP API實現(xiàn)event的獲得和處理,以及結(jié)果返回。
3.用戶語言Runtime(可選)
針對解釋型語言,或者是需要Runtime來運行的語言,比如js、python、dotnet等,需要用戶提供自己的Runtime,并在bootstrap中提供相應(yīng)的啟動Runtime的命令。
騰訊云官網(wǎng)上也提供了利用CR實現(xiàn)shell云函數(shù)的示例[2],有興趣的小伙伴可以看看。
三、Custom Runtime具體模型及用法示例
Custom Runtime函數(shù)的內(nèi)部處理流程如下所示:
目前Custom Runtime的實現(xiàn)在SCF側(cè)是一個HTTP Server。用戶側(cè)代碼作為HTTP Client通過約定的API給SCF發(fā)請求來獲得事件及相關(guān)信息,并發(fā)送HTTP請求返回處理結(jié)果給SCF服務(wù)。
HTTP Server端口號和URL,通過兩個環(huán)境變量傳遞到云函數(shù)環(huán)境中:
SCF_RUNTIME_API:SCF_RUNTIME_API_PORT
HTTP API定義如下圖所示:
1.冷啟動階段(函數(shù)部署階段)
冷啟動階段主要是部署用戶代碼,完成用戶初始化,這個階段SCF會在用戶提供的程序包(zip包)中尋找bootstrap可執(zhí)行程序,然后拉起該程序。bootstrap由用戶實現(xiàn),內(nèi)部啟動用戶代碼等工作。
用戶函數(shù)在冷啟動階段需要完成代碼初始化工作,并通知SCF,初始化工作完成。即發(fā)POST到SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/init/ready.
SCF服務(wù)側(cè)接收用戶ready的請求,初始化工作結(jié)束,通知上層服務(wù)。函數(shù)進入調(diào)用流程(即event此時可以下發(fā)到函數(shù)側(cè))。
2.熱啟動階段(調(diào)用階段)
函數(shù)通過GET SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/next獲得event及相關(guān)ctx信息。
SCF在函數(shù)拉取event之后,等待用戶函數(shù)返回。
函數(shù)處理event之后,如正常返回,通過POST SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/response傳遞返回信息給SCF服務(wù)。
如函數(shù)調(diào)用出現(xiàn)異常(此處指業(yè)務(wù)代碼需要返回錯誤信息),則通過POST SCF_RUNTIME_API:SCF_RUNTIME_API_PORT/runtime/invocation/error返回錯誤信息。
SCF服務(wù)傳遞返回給上層服務(wù),函數(shù)一次調(diào)用結(jié)束,進入下一次event調(diào)用周期。
這里我們用SCF中CustomRuntime的Deno模板示例做說明,如下圖所示,程序包里有:
·bootstrap:入口文件,這里是shell,可以看到紅線標(biāo)注這一行就是啟動deno程序;
·deno二進制:Deno Runtime,啟動deno程序必須的launcher;
·demo.ts:用戶函數(shù),里面就實現(xiàn)了上面提到的和SCF服務(wù)端交互的邏輯,也是用戶業(yè)務(wù)邏輯的主要處理函數(shù)。
bootstrap主要是啟動demo.ts,下面我們看看demo.ts里的代碼實現(xiàn):
可以看到,主要是完成初始化階段。下面再來看看調(diào)用是怎么完成的:
可以看到,是通過GET(fetch)循環(huán)拉取event,然后調(diào)用processEvent()來進行處理。processEvent()邏輯如下所示:
分別處理正常返回和錯誤返回。最后再來看一下我們是怎么封裝這里的postData()函數(shù)的:
以上就是一個Deno函數(shù)使用SCF的Custom Runtime實現(xiàn)云函數(shù)的全過程。
四、結(jié)語
從上文的論述我們不難看出:
1.SCF與語言無關(guān)
因為CR的使用與語言無關(guān),所以解鎖了SCF的語言限制,也就是說只要可以實現(xiàn)一個HTTP Client,就可以通過HTTP API的調(diào)用和SCF進行交互,從而完成云函數(shù)的事件處理及調(diào)用。
2.bootstrap是入口
舉個例子,如果我用C語言實現(xiàn)一個HTTP Client,按照CR的約定完成與SCF的交互,那么完全可以編譯成一個名字叫bootstrap的二進制文件,然后就可以跑C的FaaS函數(shù)了。
3.bootstrap可配置
用戶可以在bootstrap里面啟動多個進程,可以解鎖多種玩法,當(dāng)然,要符合安全,畢竟用戶函數(shù)運行環(huán)境有安全限制。但是,這已經(jīng)可以解決一些“云函數(shù)+agent進程”的需求。
4.使用簡單
相對于學(xué)習(xí)各個語言的函數(shù)編寫規(guī)范,了解云函數(shù)對各個語言的支持。使用CR只需要學(xué)習(xí)HTTP API的使用即可。更多的語言,環(huán)境相關(guān)的問題都是用戶在業(yè)務(wù)開發(fā)中使用到的,不需要額外學(xué)習(xí)。
Custom Runtime剛剛上線,已經(jīng)得到了一些外網(wǎng)客戶的關(guān)注。比如,有人用Custom Runtime把Swift放到了SCF里面,并做了相應(yīng)的支持[3];有人用Custom Runtime在SCF中跑了WASM,并在上面做了Rust語言的支持[4]。
還有很多類似場景,我們也在不斷的努力,引入更多的語言,借助語言的生態(tài),帶動Serverless的生態(tài)發(fā)展。最后,歡迎大家體驗SCF Custom Runtime,留下寶貴的意見!
參考資料:
[1]Custom Runtime說明:
https://cloud.tencent.com/document/product/583/47274
[2]官網(wǎng)示例:
https://cloud.tencent.com/document/product/583/47610
[3]場景拓展1:
https://github.com/stevapple/swift-tencent-scf-runtime
[4]場景拓展2:
https://www.freecodecamp.org/news/rust-webassembly-serverless-tencent-cloud/
One More Thing