作者 | 禾易
來源 | 阿里巴巴中間件(ID:Aliware_2018)
造夢者 | 王樹彬,阿里巴巴閑魚架構負責人
2014年6月28日,阿里即將赴美上市的這一年,西溪園區的一個茶水間里,28個人日夜趕工了三個月后,上線了一個閑置交易平臺——閑魚。
今年5月份,在阿里巴巴的年報中對外公布了閑魚的數據:GMV2000億元,同比增長100%,每天在線賣家數超過3000萬人。 閑魚已經從一個茶水間創業的內部小產品,變成了在C2C領域的領先平臺。
據艾媒數據估計,2020年全年的二手物品交易市場的規模將達到萬億以上。線上交易的繁榮亟需技術架構做相應的調整、演進才能支撐業務的快速發展。閑魚對于阿里而言,有比營收更重要的意義,那就是創新。
創新不只體現在業務模式上,閑魚的技術架構也在探索最新的方向——向Flutter化、云原生/Serverless化發展。
2009年,從浙江大學畢業的王樹彬,在UT斯康達工作了三年后,加入阿里巴巴。2017年,王樹彬首次將Flutter引入到閑魚,從2018年開始,王樹彬帶領閑魚技術團隊在下一盤更大的棋:布局Serverless。
顛覆性創新往往是從邊緣性的地方出現,而向云原生化/Serverless化升級,對于閑魚是一條全新的路,但趟出了這條路,對于很多做線上交易的公司有著巨大的借鑒意義。
今天,我們就一起聊聊閑魚的云原生故事。

為什么要做Serverless?
閑魚是依托阿里電商體系的前臺型業務,有非常獨特的業務特點和用戶訴求,在底層依托阿里系統的同時,在表現層和業務層需要探索適合閑魚的、并且更加快速靈活的研發體系。
按照傳統的開發方式,閑魚原有的 IT 系統會面臨很多痛點,比如:
-
客戶端交互層、服務端業務膠水層、領域層邊界劃分不清晰,這就導致很小的業務需求就需要整條鏈路的同學參與,協同成本高,開發調試周期長。
-
服務端存在巨型應用,研發耦合、發布耦合、運維耦合嚴重,甚至系統穩定性也受到很大挑戰,單個業務問題往往會影響整個應用。
-
運維成本極高。為了保障業務的穩定性和可用性,阿里對每一個應用上線都有相應的規范和規則。哪怕是一個很小的內部應用,一天可能只有一兩個訪問量,上線也需要遵守既有的規范,這勢必會消耗一些固定資源。
單個應用消耗的資源可能很有限,但所有應用消耗的資源累積起來也是一個不小的數字。而對于巨型應用,由于影響面巨大,發布時要有更加嚴格的流程和步驟,一次發布至少要耗時6小時,導致運維成本極高。
Serverless 的出現,一方面使云端一體化研發成為可能,很多小業務需求的協同成本可以大大降低。另一方面,Serverless 使業務膠水層的巨型應用,有了比微服務更加合理的拆分方式。
傳統巨型應用的成本(速度)、穩定、質量相互制約的瓶頸,可以用下面這個三角形來直觀的表示。

云原生/Serverless 這些新技術的出現,可以使應用運維能力下沉,傳統巨型應用的成本(速度)、穩定、質量相互制約的瓶頸才有可能被打破。
閑魚在落地新技術的過程中,先圍繞 Flutter 重點攻堅了 Flutter 混合工程體系、高性能組件庫。然后圍繞Serverless 重點攻堅云端一體化研發體系、服務端業務組裝層架構體系。
閑魚客戶端基于 Flutter 進行架構演進與創新,通過 Flutter 統一 Android 和 IOS 雙端提升研發效能之后,希望通過 Flutter+Serverless 解決各角色間存在的大量的協同問題,正是這些問題導致整體研發效率低,移動端離業務越來越遠,服務端沒有時間做底層領域沉淀。
通過 Serverless 的引入,閑魚會明顯看到整體研發效率的提升。

一邊探索,一邊實踐
2018年,閑魚技術團隊開始探索 Serverless,整體分為四個階段:自建Dart Server、依托FaaS平臺、云端一體化、傳統巨型應用Serverless化。
2018年5月,以 Serverless 思路構建了2s內冷啟動的 Dart Server 應用框架,用于服務端業務膠水層的輕量化開發。
2018年底到2019年初,閑魚啟動與Gaia團隊協同共建基于Gaia平臺的Dart 運行時,并上線了部分業務。注:Gaia是基于阿里云的面向淘寶業務特點封裝的、用于淘寶業務的FaaS平臺。
2019年,閑魚基于Gaia的Dart Runtime標準化,探索 Flutter+FaaS 云端編程一體化,領域接口元數據化,最終誕生了 Nexus 等膠水層業務框架,并在閑魚20多個業務落地。
2020年,閑魚開始進行云端的工程&工具一體化,目標是實現一個工程、多端部署。現在,王樹彬正帶著技術團隊攻堅業務膠水層的傳統巨型應用治理,使傳統應用向Serverless化遷移,“最快3個月,最晚6個月,我們就會交出一份漂亮的答卷。”
具體來看過去這兩年的時間里,閑魚在Serverless上的實踐成果,主要分為5個方面:
-
云端編程模型一體化框架(Nexus API)
這個框架的目標是使Flutter、FaaS的編程模型統一,打通UI、交互、數據、邏輯。王樹彬提到,一開始說要做Flutter + FaaS一體化的時候,我們對“一體化“這三個字的認知相對比較模糊,只是知道端側的同學可以用 Dart 這門語言來寫FaaS函數,這其實還停留在語言上的一體化。
對于FaaS所能做的事,也僅僅停留在前端實施已久的BFF層面。
我們花了很長時間來討論,基于Dart生態下,前端的 FaaS 在研發交付其實并不高效,研發階段主要面臨的問題是:
編程語言不統一:編程語言本身雖然不是最大的障礙,但這也確實給前端開發者增加不少門檻,而且更重要的是語言背后的生態、環境與體系更是一道高高的墻。
開發模式與架構割裂,環境復雜:端側一個工程,FaaS側也有一個獨立的工程,它們背后有自己的一套構建、調試、集成/發布的工具鏈;除此之外,FaaS 還有自己配套的環境、Runtime、框架作為支撐。
開發者面對這樣復雜的 FaaS 研發環境與雙重的研發工作流是無法做到高效交付的。
最終,我們對一體化有了一個比較清晰的共識,那就是要實現兩個核心的一體化:
-
語言一體化
-
開發模式與架構一體化
編程語言的一體化可以為開發者提供一種熟悉的技術棧,開發模式與架構一體化能幫助開發者解決工程割裂以及背后復雜的 FaaS 本地運行環境問題,帶來與原研發模式基本一致的研發體驗。
通過這兩個層面的一體化,最終達到開發 Flutter 頁面和開發 FaaS 無明顯Gap。例如,閑魚客戶端Flutter以往是用Redux框架開發,在Nexus API框架下,可以使Redux與FaaS調用無縫集成。

-
CLI 開發工具標準化
云端一體化開發時,通過 CLI(命令行工具)屏蔽 FaaS 開發的一些細節,使客戶端開發 FaaS 時的開發體驗標準化,符合客戶端同學的本地開發習慣。

-
基礎服務 BaaS 化
過去兩年,我們在逐漸簡化基礎服務能力,如對象存儲、消息、搜索。同時,建設業務領域層服務的元數據中心,這些簡化的基礎服務能力,再加上已有的業務領域層服務,使客戶端同學可以快速組裝業務。
-
云端工程一體化
閑魚在成功引入 Flutter 后,在端側形成了以 Flutter 為主、H5為輔的跨端研發體系,使傳統的 Android 和 iOS 的兩端研發,合并成一端。在端上的生產力得到釋放時,我們發現端的同學有機會向下層走一點,使服務端面向簡單的數據組裝邏輯,由端的同學一人閉環完成,這套模式尤其適用于一些小業務的需求。
類似的嘗試業界其實早就有了,例如 GraphQL 框架的流行,前端的BFF層的形成。但有了Serverless,服務端輕量代碼的開發可以極大地簡化,所以閑魚選擇這個時機推進云端一體化。
云端一體化涉及到云端編程框架、工具鏈、工程體系、基礎服務BaaS化、領域服務下沉,同時,也涉及人員上的組織保障、分工重塑、安全生產培訓等。
-
傳統巨型應用的Serverless化改造
Serverless不是銀彈,但與業務膠水層的特點很匹配,非常適用于解決膠水層的傳統巨型應用的拆分,這也是閑魚正在攻堅的下一個難題。


難題與破局
閑魚落地 Serverless 的過程中并非一帆風順。王樹彬提到,在Serverless云端一體化過程中,遇到了一些技術難題,比如JAVA富客戶端的異構語言訪問、開放環境如何統一以及客戶端同學對領域接口不熟悉等問題。
在閑魚的Java系統中,存在大量的Java富客戶端應用。針對Java富客戶端的異構語言訪問,閑魚以Sidecar的模式,建立Java的Proxy來解決這類問題。
緊接著,為了讓開發環境統一,閑魚開發了自己的CLI工具(GCLI)。GCLI是一個基于支撐 FaaS 研發生命周期的命令行工具,它定義了閑魚 FaaS 開發閉環,統一了 FaaS 的研發環境,是提升FaaS研發效率的利器。
GCLI 將研發閉環拆解成適合Serverless 研發習慣的開發指令。為了讓用戶繼承其研發習慣和工具,閑魚優先選擇了基于本地的開發方案;使用Docker技術統一開發環境,在 Dcoker 內聲明Dart FaaS技術棧依賴的運行環境(軟件+配置)。
借助容器技術,FaaS 的軟件環境可以移植到任何支持linux運行的操作系統,從而解決了環境統一的問題;GCLI 通過 FaaS Open API 實現本地和函數平臺實現互操作,形成完整的研發閉環。
最后,針對客戶端同學對領域接口不熟悉的問題,閑魚開發了領域層的元數據中心。
云端一體化重塑了傳統的云、端邊界,減少了協同,也給人員的分工帶來了更大的靈活性,技術上的研發效率、研發質量也明顯提升。而這些改變對于業務帶來的直接好處,就是可以讓業務有更快的迭代速度、更快地適應市場和用戶需求的變化。
云端一體化目前應用在閑魚的重交互場景以及輕量業務場景中,其帶來的技術效率、質量提升更容易以量化的數據形式呈現。例如,以典型的中大型業務需求抽樣統計,開發人日降低了30%,千行代碼Bug率降低了20%。
如果以零散需求統計,數據提升會更加明顯。以往的小需求由于多個同學參與,往往排期需要幾周,而云端一體化后,資源的靈活性明顯提高,使需求響應速度大大提升。

“但是,還有一些問題沒有解決”,王樹彬說,在 Serverless 的巨型應用拆分方面,閑魚遇到的問題更加嚴峻,比如:
-
微服務和 Serverless 的選型
-
在 Functions 之間代碼復用
-
對函數的依賴做統一升級
這幾個問題的方案,閑魚還在逐步驗證中,待經驗成熟后再向大家詳細分享,歡迎持續關注。

借鑒與思考
什么樣的公司、應用或場景應該選用 Serverless 的架構模式?目前沒有具體的定義,關鍵在于想清楚。想清楚,就需要平衡好收益、成本、效率和應對市場的能力。
其中,成本是企業更為關注的因素,這其中包括基礎設施搭建的成本、運維成本、擴容成本、安全成本等。
Netflix是落地 Serverless 的一個成功的典型,Netflix 在產品設計上一直都有創新的基因,除了不間斷的 A/B 測試之外,每周都會發布很多新功能。
為了確保這樣高強度的工作成果,就需要一個 API 服務平臺來幫助客戶端工程師快速而有效地將更改的需求部署到服務層。
FaaS 通過把那些與服務相關的所有平臺組件抽象為業務邏輯本身來實現這一目標,而 Serverless 模式能夠為Netflix提供一個平臺,即使沒有服務器和運營經驗的工程師也可以開發高可用的服務。
采用 FaaS 模式,本質上是對交易速度和可能性的定制化。有些應用程序的 FaaS 服務表現得很好——Netflix API 的情況就是如此,Netflix 運行的是相對統一的微服務,只需要訪問和改變下游服務的數據。
然而,如果服務需要定制化,例如需要改變服務平臺的各個組成部分,像 RPC、數據訪問、緩存、認證等,那么 FaaS 模式可能無法為這些服務提供足夠的靈活性。
自建 Serverless 平臺對企業IT人員的要求比較高,同時建設成本也很高。另外,實施Serverless 需要一個成熟的生態。
絕大多數情況下,已經上云的企業應該優先考慮云廠商的Serverless產品,而沒有上云的企業,需要考慮現有系統的生態情況是否能與云廠商的Serverless產品兼容。
對于 Serverless 產品的選型,應該綜合幾個方面來看:生態的成熟度,支持的開發語言,功能豐富度,收費標準等,關鍵是結合企業自身業務發展的需求。

關于未來
O'Reilly 曾對 Serverless 的應用情況進行了過一次調查,發現軟件行業的開發者關注和應用 Serverless 非常多,這在意料之中,但是金融和銀行業也在高度關注Serverless,原因之一是越來越多的金融科技初創企業的誕生,它們承擔了傳統基礎架構的責任,并且以更開放的心態,接納和擁抱 Serverless 。
對于拒絕 Serverless 的理由,60% 的受訪者表示是安全問題。因為很多行業對于 IT 環境的安全性要求很高,而采用任何新技術都可能會帶來安全風險。
此外,開發者另外一層顧慮主要是擔心被廠商綁定,這就導致具備一定規模的組織會基于開源方案,如 Knative,搭建自己的 Serverless 平臺。而一旦某個開源方案成為主流,云廠商就會主動去兼容開源標準并增大社區投入。
Serverless 除了對技術和業務產生影響外,對于企業組織架構和技術人員也提出了新的要求。
首先,Serverless 改變了溝通結構。按照康威定律,組織架構需要適應新的溝通結構,才是最好的匹配。
閑魚以前負責客戶端和服務端的同學是分開的,在全新的 Flutter+Serverless 的背景下,組織結構也需要做相應的調整。經過討論,閑魚最終決定按照業務線劃分,將客戶端、服務端的同學按業務線重新組合到一起。
其次,Serverless 使客戶端的同學有機會更多的了解業務,這就要求客戶端同學更加具有業務敏感度。Serverless 促使客戶端同學擴大了技術邊界,也需要了解一定的服務端開發概念。
最后,Serverless 要求原有的服務端同學有更好的數據建模、領域建模能力,從而有助于底層接口復用度更好。
從最開始不被外界看好,甚至被調侃為“咸魚”,到如今實現了千萬DAU,盤活了一個萬億級市場,閑魚的出現,無論是對前端的電商生態,還是用戶在互聯網上的生活形式,都產生了重要的影響。
為了支撐起閑魚萬億的交易規模,王樹彬和技術團隊正在緊鑼密鼓地進行傳統巨型應用的 Serverless 化改造,“闖過了 Serverless 的這一關,才是我比較滿意的狀態。”