
作者|姜沂(傾寒)
出品|阿裡巴巴新零售淘系技術部
S1 階段在使用 SwiftUI 編寫集團内部使用的 SOT APP 時,有幸參與到 GAIA (FaaS)平台雲端一體化的探索,從頭到尾實作了一套基于 Swift 語言實作的遵守 GAIA Funtion 标準的 Runtime Framework,并完成了從用戶端到後端使用統一的語言棧完成一體化鍊路的探索。
作為一個純 iOS Native 端開發者,對于後端的技術體感,大部分還遺留在上學期間做的論壇管理系統,加之 FaaS Serverless 等都是一些後端領域較前沿的技術點,尤其是在後端還算是初生牛犢的 Swift 語言,期間走過無數的彎路,但也學到了很多新的知識。
本文是對 Swift On GAIA 的階段性總結和思考。由于此次技術探索有較多跨端知識,作為一個移動端工程師的視角了解可能非常片面和有誤,如讀者發現對概念有解釋不對,歡迎大家留言區多多指正。由于在技術棧上前端生态已有較多探索, Native 端上的探索和技術儲備落後與前端,有些實作會随着雲端一體化得探索而改變,并不是一個已經完備的解決方案,歡迎各位開發愛好者積極讨論,造福生态。
PS:文末附郵箱,感興趣者可進行深入交流。
概念性介紹
Serverless
Serverless 起始是一個比較早的名詞,早到 2012年,彼時的我才剛背起小書包走進大學裡,但是早期的理論基礎已經被提出。
随着 2014年 AWS 的 Lambda 産品出現, Serverless 為雲中的應用提供了一種全新的架構體系, Serverless 開始大火,之後各大雲計算廠商的加入,Google Cloud Functions, Azure Funcions, IBM OpenWhisk Aliyun 以及其他國内的雲計算廠商,如 華為雲,騰訊雲,百度雲,短短數年時間 Serverless産品已遍地開花。
随着容器技術,IoT,5G,技術的快速發展, 技術上對去中心化,輕量虛拟化,細粒度計算等技術需求愈發強烈,而 Serverless 必将借勢迅速發展,對将來的富用戶端的研發模式的改變,則需要我們這些技術人持續的去探索和創造了。
我們在了解 Serverless 的過程中先來看一看雲服務的進化史,雲計算經曆了實體機房 -> IaaS -> PaaS -> SaaS -> FaaS/BaaS 。
▐ IaaS
IaaS(Infrastructure as a Service)基礎設施即服務。指把 IT 基礎設施作為一種服務通過網絡對外提供。在這種服務模型中,使用者不用自己建構一個資料中心,而是通過租用的方式來使用基礎設施服務,包括伺服器、存儲和網絡等。在這層公司通常購買的是存儲,網絡的基礎服務。
▐ PaaS
PaaS(Platform as a Service) 平台即服務,服務商提供基礎設施底層服務,提供作業系統(Windows,Linux)、資料庫伺服器、Web伺服器、負載均衡器和其他中間件,相對于 Iaas 客戶僅僅需要自己控制上層的應用程式部署與應用托管的環境。通常在這層使用者一般購買的是作業系統。
▐ SaaS
SaaS(Software as a Service) 軟體即服務,SaaS 是一種通過 Internet 提供軟體的模式,使用者不用再購買軟體,而改用向提供商租用基于 Web 的軟體,來管理企業經營活動,且無需對軟體進行維護,服務提供商會全權管理和維護軟體,通常這些常用的軟體有 資料庫,網絡服務,等。
可以通過 Microsoft Azure 服務的一張圖來直覺感受下
▐ FaaS
FaaS(Function as a service) 函數即服務,服務商提供一個平台,允許客戶開發、運作和管理應用程式功能,而無需建構和維護基礎架構。按照此模型建構應用程式是實作“無伺服器”體系結構的一種方式,通常在建構微服務應用程式時使用。
使用 FaaS 建構的軟體服務,開發者對底層的硬體平台,作業系統平台,軟體平台,越發的透明,開發者隻需關注核心的函數(功能實作)即可完成自己所需要的事,内部的部署,運維,彈性,都不需要開發者關心。
FaaS 主要有以下的優點:
- 低成本
- 快速擴容
- 更簡單的管理
- 綠色計算
目前國内外雲計算廠家基本都支援了 FaaS 的服務。
GAIA
GAIA是什麼?
按照官方文檔 空蒙 團隊的介紹 GAIA是淘寶新一代雲端一體化輕量級研發平台 詳細的可參考 “一次編碼、到處運作”,淘寶雲端一體化探索
GAIA解決的問題:
應用”承載多業務服務,并與基礎設施依賴緊密耦合,“應用”負重前行。
應用的傳遞流程成本高。
以上的介紹考慮的是後端技術棧的問題,下面來看一下用戶端的視角。
作為 iOS Native 開發者看到更有體感的切入點是所見即所得(What You See Is What You Get ),function版本化傳遞運作。
GAIA 平台大大縮短了後端的研發鍊路,提高了傳遞成本,屏蔽了運維細節,這對于一個跨棧的開發者也能簡單了解。
GAIA容器架構
看過 GAIA 的概念,有必要簡單的了解一下 GAIA 容器架構。
圖中右側部分,紅色的 Function是真正的業務代碼,可以以一個非常輕量,以函數級别傳遞,被 Function Framework 加載,并按照規範的生命周期管理函數的生命周期、健康檢查、業務調用等,通過RPC 與 SideCar 通信,SideCar Container 負責服務發現,流量管控,Function Event,這部分可以了解為規範,與語言無關,實作一套即可。
- GAIA 容器定義
GAIA 作為一個 FaaS 架構,有很多事情需要考慮,如服務發現,日志監控,運維管理,通信規則等,但這些都是内部實作的細節,是不需要業務方來了解的,這裡也就不做多贅述。
Swift On GAIA
作為一個端上開發者,恰逢使用 SwiftUI 建構 SOT APP 移動版,在滿足需求的同時,有探索新技術。
但是作為一款資料大盤的 APP,資料從哪裡來?從後端資料庫,由于之前從未有過移動端APP,後端同學并未對外提供 MTOP 的接口供移動端使用,了解到可以在 FaaS 平台調用已有的 HSF 服務,傳回領域内的模型,GAIA 平台可以對外釋出為 MTOP 接口,剛好滿足需求。
前期的調研中,發現 GAIA 的平台語言棧選擇了後端的王牌語言 Java,Function Runtime Framework 最早版本隻支援Java,後期随着前端棧的探索和 閑魚團隊的 Flutter 探索,目前平台已經支援 Dart Runtime, Node.js Runtime。
作為一個 iOS Native 開發者,沒有自己熟悉的語言怎麼辦?Swift 于 2019年 WWDC 宣布 釋出 5.x 版本,Swift5.x 版本 ABI 穩定,标志着 Swift 正式進入成熟語言行列,加上 Swift 誕生之初就是一門跨平台的語言,并且也有開源的 Server side workgroup推進着 Swift 在後端領域的探索,也湧現出一些 知名的庫 Kitura Vapor Perfect Zewo。
于是我們嘗試用 Swift 建構一套 Function Runtime Framework,先來了解下 Runtime Framework 是為了完成什麼?
Swift Runtime Framework 需要完成如下操作
- Swift 運作時初始化。
- 日志監控
- 通信協定
- 集團已有中間件調用
- Function 排程
- 釋出系統建構
在後端部署的服務都是可彈性的,GAIA 也不例外,Swift Function Runtime, Swift Function 傳遞都是制作成 Docker Image 統一傳遞。簡化如圖所示。
- Swift 運作時建構
Swift 語言是跨平台的,包括 Apple‘s OS, Linux Windows Android,RespibarryPi,但是官方放出的 ToolChain 隻有 Ubuntu,其他都需要從源碼手動建構, 集團提供的雲 Server 是 CentOS,需要手動建構并制作 Docker Image。
作為一個後端系統,不可能像移動端程式次次通過斷點調試,排查線上問題時,日志規範非常重要,這裡按照 GAIA 的 Function 規範實作即可。
由于業務 Function 都是通過容器傳遞,業務方實作的部分都是一個簡單的函數,這個函數被調用時是通過 SideCar 程序通過 RPC 調用而來的,是以需要實作GRPC 通信,這裡使用的是 Google 開源的 Protobuffer 和 GRPC 的 Swift 版本實作。
由于 Swift 語言通常的開發者都是 Apple 平台的開發者,使用的開發工具都是 Xcode,但是為了傳遞到後端,隻能使用 Swift Package Manager 傳遞,開發使用 Xcode 或者 Visual Studio Code Remote 開發。
- 集團已有服務通信
任何新平台,新架構的出現都需要一個漸進式遷移舊技術的能力,GAIA 也不例外,GAIA 背後屏蔽了很多集團已有中間件的能力和生态,在阿裡的語言棧是 Java ,但是對于一個新的語言棧則是困擾,因為原有的的語言棧并不是語言中立,平台中立的,如 HSF Tair EagleEye 等。
但幸好的是目前這些中間件生态還有一套 CPP 版本的 SDK 維護,Swift 天然就是和 C 混編的,C 可以調用 CPP,目前調用其他中間件服務通過 Swift 和 CPP 混編實作。
一個典型的業務互動時序圖如下:
正式上線
Funtion Runtime Framework 完成後,就可以通過 GAIA 的釋出平台建立函數,編寫自己的業務代碼裡,這裡就不分享如何操作了,直接上示例代碼和效果圖。
// File.swift
//
//
// Created by nero on 2019/9/12.
//
import GAIA
import HSF
import Foundation
struct EventResult: GAIA.EventResult {
var isSuccess: Bool = true
var code: String = "200"
var message: String = "SOT Test"
var payLoad: TestContent
init(payLoad: String) {
self.payLoad = TestContent(content: payLoad)
}
}
struct MtopUserQuery: Codable {
let pageNo: String
let pageSize: String
let appName: String
}
struct PageQuery: HSFModel {
let javaClassName = "com.xx.PageQuery"
let request: PageQueryRequest
let pageNo: Int
let pageSize: Int
init(pageNo: Int, pageSize: Int, appName: String) {
self.pageNo = pageNo
self.pageSize = pageSize
self.request = PageQueryRequest(appName: appName)
}
let apiConsumer = PageQueryAPIConsumer()
}
struct PageQueryAPIConsumer: HSFModel {
let javaClassName = "com.xx.ApiConsumer"
let clientName = "SOT-APP"
let token = "xxx"
}
struct PageQueryRequest: HSFModel {
let javaClassName = "com.xx.AppQueryRequest"
let appName: String
}
class Handler: GAIA.FunctionHandler {
init(){}
var consume: ConsumerService
func handle(when event: Event, context: FunctionContext) throws -> AnyEventResult {
switch event.payLoad {
case .mtop(body: let mtopRequest):
do {
let query = try JSONDecoder().decode(MtopUserQuery.self, from: mtopRequest.data)
let sotQuery = PageQuery(pageNo: query.pageNo, pageSize: query.pageSize, appName: query.appName)
let jsonStr = try consume.invoke(methodName: "queryApp", args: [sotQuery])
return EventResult(payLoad: jsonStr).erasedEventResult
} catch {
}
default:
break;
}
return EmptyEventResult().erasedEventResult
}
func active(when context: FunctionContext) {
}
func destroy(when context: FunctionContext) {
}
func isHealth(when context: FunctionContext) -> Bool {
return true
}
}
GAIA 雲端一體化的思考
Swift On GAIA 在雲端一體化的探索一期圓滿結束,一個 iOSer 也可以同時開發前後端程式,這對研發模式也創造了一些新的可能,最近也多次聽大佬們的一些分享,如閑魚團隊使用 Dart+flutter 在雲端一體化研發模式的探索,有一些不成熟的視角,暫且記錄一下。
技術棧日常研發調試的困難?
在研發模式交流和一些實際探索的體驗中發現,端上的研發風格和後端的研發風格差異較大,端上的同學傾向于打斷調試,實時預覽效果,背後的原力是因為端上要更快的傳遞,端上的環境更容易建構,但是後端的同學更傾向于日志系統,鍊路追蹤。但其實無論是斷點調試還是日志系統,本質上需要一個有效排查問題的系統,不然在實際開發中,由于跨技術棧會讓調試的成本變大, 系統一旦複雜起來反而會拖慢效率。
工程結構的更新
在 Swift On GAIA 的實際體驗中,使用的開發工具,應用傳遞方式,都不統一,各個語言棧都有自己的研發風格,工具鍊支撐,研發模式和工具鍊體系也需要對應的更新,避免鍊路過長,工具鍊割裂。
領域的邊界是什麼?
目前閑魚的大佬在 GAIA 完成了 Dart Function 環境的支援,可以讓用戶端同學向前更進一步,自己完成後端的能力,實作無上下遊依賴的業務閉環,并且屏蔽後端的細節。
不過在一些細節上的分析,發現不同的業務場景碰見的挑戰還是不同,如果一個 Function 隻使用已有的基礎設施,如接口聚合,簡單的邏輯處理是比較合适的,但如果這個業務連資料的生産者也由用戶端的同學來寫複雜度就變大了,因為跨端的思維方式不同,大前端同學可能不會思考更多存儲的設計,未來在業務擴大時就可能不容易擴充。
那麼在實作業務的的時候,如何界定一些領域的邊界是一個值得思考的點,需要一些方法論或者指導原則,來幫助 Function 同學決策這款技術選型的可擴充性。
人員組織架構更新
如果研發模式大更新,傳統的後端 API 釋出,各端接入的人員上下遊關系勢必會發聲比較大的變化,如何找到人員組織的方式也是需要重新定義和調整的。往小了說幹的活配置設定不一樣了,往大了說 組織架構也需要适應時代調整。
中間件語言中立,平台中立
目前後端大部分的語言棧都是 Java ,其中集團部分團隊使用 CPP,湧現了多個 CPP 版本的 SDK 用來調用 Java 的生态架構,如 HSF CPP 版本 Tail CPP 版本 ,随着 GAIA 平台接入語言棧的變多,加上富用戶端 Swift/Kotlin/Java/Javascript,要不要做一些類似 Protobuffer 這種通過中立的 DSL 定義解決語言差異性。
這裡作者是不太認可一套語言解決所有環境的,一是目前手淘的生态分為 Native+Weex+H5+小程式,本身就難以聚合,二是單拿 iOS 端,在蘋果限制下的跨平台總是有部分取舍的,不能解決全部問題。
領域特定/通用
未來 Swift 在 FaaS 平台上是朝着解決通用能力去前進還是建構領域模型,建構領域特征可以建構領域生态的 API,定義業務的模式,類似星環的風格,如果建構的是通用能力,解法可能是另外一種。
One More Thing
淘寶基礎平台團隊正在進行社招招聘,崗位有 iOS Android 用戶端開發工程師、Java 研發工程師、C/C++ 研發工程師、前端開發工程師、算法工程師。
歡迎投遞履歷至 :[email protected]
點此觀看團隊介紹視訊。參考
1、當我們聊Serverless時你應該知道這些
2、
曆時五天用 SwiftUI 做了一款 APP,阿裡工程師如何做的?3、What is Azure
4、基礎設施即服務wiki百科
5、IaaS,PaaS,SaaS 的差別
6、平台即服務wiki百科
7、FaaS
8、Kitura
9、Vapor
10、Perfect
11、Zewo
12、
研發效能領域洞察 | 如何找到适合自己的研發模式?13、
閑魚Flutter&FaaS雲端一體化架構14、
阿裡雲小程式 Serverless 教你如何 30 分鐘開發小程式!15、Knative:重新定義 serverless
掃描下方二維碼,關注「淘系技術」微信公衆号,擷取更多技術幹貨。