開篇
2020年11月份,阿裡雲智能開源了Serverless 社群的開發者工具Serverless Devs(後簡稱S) 彌補了國内在Serverless 開發者工具的一個空白。通過高度靈活的配置設定,實作了無廠商鎖定的支援;直覺易懂的可視化配套也帶來了極緻的開發者使用體驗。
通過S你可以體驗Serverless hello world 以及 建構生産級Serverless 應用 。你也可以盡情發揮自己的創意,在S 這個平台上為更多的開發者貢獻自己的 應用群組件。本篇将會從整個技術架構視角為你揭開S的神秘面紗,希望通過本篇文章可以幫助你了解S的核心設計理念和實作的基本原理,在類似的可擴充應用設計中帶來一些解題思路。
S外貌 - 功能結構全景展示
為了更友善的講解,我們可以先看看S的全景圖

如上圖所示S 核心構成大緻分成了5部分,他們分别是
1 - 核心啟動器 ;
2 - GUI 圖形界面 ;
3 - 核心元件庫s/core和 實作fc部署的 s-framework ;
4 - 應用中心;
5 - 以FC 為基礎的Serverless 服務接口。
其中 1,2,3是完全開源開放的,4,5則目前由阿裡雲雲原生團隊提供經費負責維護。
值的一提的是,S工具側服務端應用以及S的社群接口服務都是依賴阿裡雲函數計算産品,穩定性,可靠性,安全,可觀測等能力皆由其保障。
S整個服務側的開發都專注在業務域,服務端的開發模式基本就是線上撸碼,線上建構,線上釋出,線上版本管理。 這樣的模式為我們的快速疊代釋出提供了有力的保障(從開始到第一個版本的研發結束時間至少縮短一周)
接下來的重點介紹會集中在1,2,3部分。在這之前,為了友善更好的了解S的執行過程,我們就先說一說S的靈魂-- 配置約定部分
S靈魂-配置約定
S的配置檔案包括 應用/元件 , 秘鑰資訊,緩存資訊。其中應用/元件 是最核心的部分,也是構成整個生态體系最主要的部分。
我們先看一個hexo部落格應用的配置檔案
HexoComponent: # 主體(唯一鍵)
Component: hexo # 元件名
Provider: alibaba # 供應商
Extends: # 擴充能力
deploy: # 針對deploy 的擴充
- Hook: npm install --production
Path: ./src
Pre: true
- Hook: npm run build
Path: ./src
Pre: true
Properties: # 屬性配置
Region: cn-hangzhou
CodeUri: ./src
Detail:
Service:
Name: hanxiedemo
Access: hanxie #通路秘鑰
S啟動器可以解讀這個配置然後把一個hexo 的部落格系統部署到 函數計算上。這個配置本身沒有任何處理邏輯,僅是資源和配置描述,他表達的是這樣一件事:
主體HexoComponent ,利用 阿裡雲提供的 hexo 元件以及客戶自身在阿裡雲的秘鑰 解鎖了部署本地部落格應用FC産品的操作。此外,解鎖這個部署操作需要的配套參數 Properties以及執行部署前的指令集也可以被描述進去完善部署操作本身。
在這樣的範式定義下,配合真正執行邏輯的元件,即可完成各種複雜的操作。當然,軟體應用的真實場景會比這個hexo應用要更複雜,可能會由多個具備獨立業務邏輯的步驟而成,并且可能有前後的依賴,針對這種情況,我們來看一下如何配置:
Global: # 全局變量
Access: release
Region: cn-beijing
AccessKeyId: '${Env(AccessKeyId)}'
AccessKeySecret: '${Env(AccessKeySecret)}'
OSSConfBucketSourceName: serverlessbook-image-source
OSSConfBucketTargetName: serverlessbook-image-target
OSSConfObjectSignUrlTimeOut: 1200
SourceBucket: # 存儲源主體
Component: oss
Provider: alibaba
Access: hanxie
Properties:
Region: '${Global.Region}'
Bucket: '${Global.OSSConfBucketSourceName}'
CodeUri: ./test
TargetBucket: # 存儲目标主體
Component: oss
Provider: alibaba
Access: hanxie
Properties:
Region: '${Global.Region}'
Bucket: '${Global.OSSConfBucketTargetName}'
Acl: public-read
ServerlessBookImageDemo: # 執行轉化邏輯主體
Component: fc # 執行轉化邏輯詳情
Provider: alibaba
Access: hanxie
Extends:
deploy:
- Hook: s ServerlessBookImageDemo install docker
Src: ./src
Pre: true
Properties:
Region: '${Global.Region}'
Service:
Name: ServerlessBook
Description: Serverless圖書案例
Log:
Project: aliyun-fc-cn-beijing-9bd4a65b-c9d1-529d-9ce0-c91adfb823ab
LogStore: function-log
Function:
Name: serverless_image
Description: 圖檔壓縮、水印
CodeUri: ./src
Handler: index.handler
MemorySize: 128
Runtime: python3
Timeout: 5
Environment:
- Key: AccessKeyId
Value: '${Global.AccessKeyId}'
- Key: AccessKeySecret
Value: '${Global.AccessKeySecret}'
- Key: OSSConfBucketSourceName
Value: '${SourceBucket.Output.Bucket}'
- Key: OSSConfBucketTargetName
Value: '${TargetBucket.Output.Bucket}'
- Key: OSSConfEndPoint
Value: '${SourceBucket.Output.Endpoint.Publish}'
- Key: OSSConfObjectSignUrlTimeOut
Value: '1200'
Triggers:
- Name: OSSTrigger
Type: OSS
Parameters:
Bucket: '${SourceBucket.Output.Bucket}'
Events:
- 'oss:ObjectCreated:*'
Filter:
Prefix: ''
Suffix: ''
這是一個圖檔Ai處理的應用,基本邏輯就是ServerlessBookImageDemo主體,從已有的OSS存儲上拿到源圖檔檔案,經過一系列步驟流程操作,轉存到目标OSS。為了配合完成這些操作,提前設定好了各種授權配置。并把他們作為全局變量供給3個主體去調用,可以看到,這個複雜配置描述了獨立的執行邏輯之間如何協同調用。配置檔案通過 “${}”的文法糖描述動态變量,S可以自動解析裝配,除此之外 S可以根據調用關系自動識别配置檔案中主體的先後執行順序 ,意味着你隻需要關注每一個主體的輸入和輸出,而不用為他們各自的執行先後去做特殊編排。
講到這裡你或許還是很迷惑,因為配置看起來很複雜,這是因為入參部分也就是Properties 完全屬于自定義範疇,是以可以延展的非常複雜(實際上我們有針對這類配置的可視化解決方案,稍後會介紹),但是除了這個,配置檔案還是有自己的固定範式(劃重點)
首先 最外層的Key (我稱為主體),隻有2類,一類Global,另一類就是唯一的鍵名,比如上面的SourceBucket,TargetBucket,ServerlessBookImageDemo;
其次非Global 主體 的範式也是固定的:
- Component - 核心執行邏輯元件;
- Provider - 服務商 ;
- Access-通路秘鑰配置;
- Extends - 主體執行指令的擴充,它包括對應指令執行前後的要做什麼操作;
- Properties - 輸入參數,注意這個輸入參數是給 Component 使用的。
是以你隻要掌握上面劃線部分的内容,這些配置檔案再複雜也能快速識别出他的主體邏輯。
為了解決複雜配置的問題社群還提供了配套的可視化方案,簡化開發者和使用者的配置使用

① 啟動器
S 啟動器是 serverless devs 最核心的部分,我們經常比喻說Serverless Devs 可以讓開發者像使用手機一樣玩轉Serverless,這個手機的OS 就是說的S 啟動器本器,他負責完成配置檔案解析,元件加載,任務排程,日志輸出,釋出管控,國際化等能力。
靈活的指令集
我們說S啟動器也是一個靈活的“瘦子”,是因為雖然他支援各種指令自定義,但實際上内置指令隻有
init, config, platform, search, set, gui 這六個,通過将配置檔案的主體和指令動态加載到核心實作這個騷操作。就舉上面水印處理的例子,如果我們在項目外敲 S 這個指令,
輸出的隻有上面提到的6個指令

但是如果在水印項目的目錄下則會有9個

如果再進一步的展開 s ServerlessBookImageDemo 則會繼續把ServerlessBookImageDemo主體下的指令全部列舉出來,這樣的好處就是可以針對單個主體做功能調用,這裡面列出來的指令實際上是主體下元件包含的真實方法。當然也有壞處,就是不利于做規範限制,那麼針對目前的配置問題社群也正在讨論新的
規範,歡迎大家一起加入

開發者可以通過開發自己的元件并将它的方法執行通過s 指令的方式觸發。
動态的執行解析
當我們使用s deploy 指令的時候,啟動器會先把 deploy 指令預加載到系統指令裡,
接下來會自動觸發 deploy的執行,可以簡述為:
預先對配置檔案進行解析,分離出變量元素,并進行對應的填充,如果遇到兩個主體有先後依賴則進行順序排序,最後生成待執行主體序列。
接下來按照序列周遊每一個主體 然後去檢索主體下包含的元件,
執行donwload-》前置鈎子檢查執行-》具體元件方法執行的動作。


可以看到,S啟動器的核心邏輯是解析相應的配置,組織執行順序,排程執行任務, 真正的執行邏輯實際上是交給了具體的元件。執行邏輯部分下放到元件,使得S具備了支援不同雲廠商的能力。
③ S framework
元件是核心的邏輯,我們就先來看看 元件的基類 核心庫 s/core | s/framework
首先要說明的是 s/core 是 完全無廠商場依賴的基礎庫。
s/framework 繼承了 s/core 的基礎能力但卻依賴 阿裡雲fc元件,它可以幫助開發者快速建構依托于阿裡雲fc 的應用場景,但是本身是鎖定了雲商的,這點需要大家知曉。
基本關系

怎麼用
s/core
import { Component, Log } from '@serverless-devs/s-core';
class YourComponent extends Component {
async test(inputs ) {
const fc = await this.load('fc', 'Component'); // 通過load 方法加載已經存在于app store上的元件
const logger = new Log()
logger.log('test core logger ...');
}
}
s/framework
const FrameWork = require('@serverless-devs/s-framework');
class YourComponent extends FrameWork {
async deploy(inputs) {
const frameworkInputs = inputs;
const customerProperty = inputs.Properties.YourCustomerProperty;
if (customerProperty) {
// 做自己的邏輯處理,比如整合目錄,釋出等
// 可以重新修改入參值 frameworkInputs.Properties.CodeUri = new value;
}
return await super.deploy(frameworkInputs);
}
}
② S 可視化工具
如果說S 啟動器 + S/framework 及所衍生的元件讓S實作了支援無廠商鎖定的能力,那麼S Gui 則是幫助S在使用體驗上更進一步。
應用/元件/插件
這三個概念在講解s gui 之前想先簡單說明一下,或許這邊會有一些同學的困惑,通常你從app store 搜尋項目的時候會發現一個hexo 的部落格會出現好幾個結果。有些是元件,有些是應用,那麼元件和應用是什麼關系呢?

應用本身不具備具體的執行邏輯細節,是一個項目的完整描述。它包含全局配置設定部分,項目約定配置,每一個項目又由元件,服務商,秘鑰資訊,元件入參組成。 應用的配置解析,執行步驟是由核心啟動器來把控
元件才是執行邏輯的核心部分,hexo的部署邏輯,圖檔Ai的轉換邏輯都是在元件裡完成的,開發者通過将動态的參數剝離給使用的人,做到多場景的支援。而且大部分的應用業務場景都可以依賴我們提供的framework基礎能力完成,比如前端架構托管,多語言的framework 托管等,當然如果你想建構更複雜的場景以及跟雲商關聯,那就需要花一些功夫打通雲商服務的sdk了。
插件是更小的執行邏輯單元,通常會放到 應用配置的extends選項中,用來抽離多個不同場景元件的公共邏輯單元。這部分因重要性較低,暫不做過多介紹。
釋出的可視化和解析的可視化
S 的元件從生産釋出 到真正展現給社群的同學使用,主要涉及2個可視化配置部分
第一個是作為元件作者要把自己的元件文檔,元件參數配置描述清楚

如上,元件作者需要将元件的入參說明一一配置成 類似下面Region,Detail的資料結構,一旦入參很多,并且是複合類型的,比如Detail,手寫起來會非常麻煩,現在提供了gui 的支援,元件開發者就可以很輕松的建構複雜的配置項。
Region:
Description: 地域
Required: true
Example: ''
Default: ''
Type:
- String
Detail:
Description: 詳細
Required: true
Example: ''
Default: ''
Type:
- Struct:
Service:
Description: 服務
Required: true
Example: ''
Default: ''
Type:
- Struct:
Name:
Description: 服務名
Required: true
Example: ''
Default: ''
Type:
- String
當然我們給使用者使用的時候也會簡化成可視化的方案,比如基于上面的realworld-web-static 元件建構的靜态托管應用最終呈現給使用者的配置

我們看到同樣是 Region 和 Detail 這兩個屬性,在開發者描述的時候用的資料結構會比較麻煩,但是給使用者這邊用的時候就非常簡單。
總結下來,S Gui 把簡單留給了開發者,同時幫開發者把簡單留給了使用者。
極簡工程架構
S Gui 是完全基于開源項目建構, 桌面部分是用的electron 官方的demo,Browser 的頁面則是 create react 初始化的标準 React項目,沒有摻雜過多的依賴。是以如果你比較熟悉React 技術棧,并且希望建構一個結構清爽的桌面項目,也可以直接把S Gui 當成初始化模闆使用

此外,我們提供了全套的桌面打包建構腳本,隻需執行npm run build 就可以完成Browser 前端打包建構-> electron 多平台資源整合 -> 壓縮桌面包 -> 釋出OSS 一系列流程。 這大約幫助可以節省 20min 的建構釋出時間。
開源開放極具美感的新一代UI庫




Gui 的視覺部分使用的是 阿裡雲智能自研的 Ui庫
b-design,最初是為我們的合作夥伴提供更具現代感的設計體驗服務,現在則完全開放給Serverless 社群使用
@b-design/ui
import { Button } from "@b-design/ui";
import "@b-design/ui/dist/index.css";
寫在最後
因為篇幅的問題,對S的介紹還是相對籠統,如有說明不清楚的還請見諒,另外因為S 本身也是新生的一款Serverless 開發者工具,本身還有很多的不足。我們希望能夠有更多的小夥伴加入讨論共建,尤其最近我們決定
對S 的“靈魂”做進一步的“美化”(
讨論連結),這裡面可能涉及大量的核心邏輯改動,也需要拿到更多開發者的寶貴意見,以下是我們的學習群二維碼,如果有興趣的話歡迎你的加入。

如果您對我們的S工具感興趣,就麻煩幫忙動動手指給我們的項目加個Star吧
S 指令行git位址
https://github.com/Serverless-Devs/Serverless-DevsS Gui git 位址
https://github.com/Serverless-Devs/Serverless-Devs-App-Store