開發與維運

喧譁的背後:Serverless 的概念及挑戰

505頭圖.png

作者 | 許曉斌  阿里雲高級技術專家,目前負責阿里集團 Serverless 研發運維平臺建設,《Maven 實戰》作者,曾經是 Maven 中央倉庫的維護者。

導讀:本文作者作為阿里集團 Serverless 研發運維平臺負責人,從應用架構的角度去分析 Serverless 為何會讓那麼多人著迷,它的核心概念究竟是什麼,並總結了一些落地 Serverless 必然會面臨的問題。

前言

我曾在《Serverless 的喧譁與騷動》一文中對 Serverless 今天在行業中所處的狀態做了一個比喻,這個比喻是這麼說的:

Serverless is like teenage sex: Everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it.

雖然距離寫那篇文章已經過去了半年的時間,但是這種狀態在我看來其實沒有發生太大的變化,有很多的一線研發或者管理者對 Serverless 技術的理解是非常片面的,有些甚至是錯誤的。如果缺乏對應用架構演進的理解,缺乏對於雲基礎設施能力的理解,缺乏對風險的判斷,盲目的上新技術可能不僅無法兌現業務價值,浪費精力,然而會引入無謂的技術風險。

本文嘗試從應用架構的角度,去分析 Serverless 為何會讓那麼多人著迷,它的核心概念究竟是什麼,以及從我個人的實際經驗出發,總結一些落地 Serverless 必然會面臨的問題。

應用架構的演進

為了能更好的理解 Serverless,讓我們先來回顧一下應用架構的演進方式。十多年前主流的應用架構都是單體應用,部署形式就是一臺服務器加一個數據庫,在這種架構下,運維人員會小心翼翼地維護這臺服務器,以保證服務的可用性。隨著業務的增長,這種最簡單的架構很快會面臨兩個問題。首先,這裡只有一臺服務器,如果這臺服務器出現故障,例如硬件損壞,那麼整個服務就會不可用;其次,業務量變大之後,一臺服務器的資源很快會無法承載所有流量。解決這兩個問題的最直接方法就是在流量入口加一個負載均衡器,同時單體應用同時部署到多臺服務器上,這樣服務器的單點問題就解決了,同時這個單體應用也具備了水平伸縮的能力。

業務進一步增長,更多的研發人員加入到團隊,一起在單體應用上開發特性。這個時候由於單體應用內的代碼沒有明確的物理邊界,大家很快就會遇到各種衝突,需要人工的協調,以及大量的 conflict merge 操作,研發效率直線下降。這個時候大家就開始把單體應用拆分成一個個可以獨立開發、獨立測試、獨立部署的微服務應用,服務和服務之間通過 API 通訊,如 HTTP,GRPC 或者 DUBBO。基於領域驅動設計中 Bounded Context 拆分的微服務架構能夠大幅提升中大型團隊的研發效率,如果想了解關於 Bounded Context 的更多內容,推薦大家閱讀領域驅動設計相關的書籍。

應用從單體架構演進到微服務架構,從物理的角度看,分佈式就成了默認選項了,這個時候應用架構師就不得不面對分佈式帶來的新挑戰。在這個過程中大家都會開始使用一些分佈式服務和框架,例如緩存服務 Redis,配置服務 ACM,狀態協調服務 ZooKeeper,消息服務 Kafka,還有通訊框架如 GRPC 或者 DUBBO,以及分佈式追蹤系統等等,這裡就不逐一羅列了。除了分佈式環境帶來的挑戰之外,微服務架構給運維帶來的新的挑戰。研發人員原來只需要運維一個應用,現在可能就需要十個甚至更多的應用的,這意味著安全 patch 升級,容量評估,故障診斷等事務工作量成倍的增長,這個時候,應用分發的標準,生命週期的標準,觀測的標準,自動化彈性等能力的重要性就凸顯出來。

現在讓我們談下“雲原生”這個詞,簡單的理解,一個架構是否是雲原生,就是看這個架構是否是長在雲上的。這個“長在”雲上的理解不是簡單的說用雲的 IaaS 層服務,比如簡單的 ECS,OSS 這些基本的計算存儲;而是應該理解成有沒有使用雲上的分佈式服務,比如 Redis,Kafka 等等,這些服務才是直接會直接影響到業務架構的。前面我們說到,微服務架構下,分佈式服務是必要的,原來大家都是自己研發這樣的服務,或者基於開源版本自己運維這樣的服務,而到了雲原生的時代,業務就直接使用雲服務了。

另外兩個不得不提的技術就是 Docker 和 Kubenetes,其中前者標準化了應用分發的標準,不論是 Spring Boot 寫的應用,還是 NodeJS 寫的應用,都以鏡像的方式分發;而後者在前者的技術上又定義了應用生命週期的標準,一個應用從啟動到上線,到健康檢查,下線,有了統一的標準。有了應用分發的標準和生命週期的標準,雲就能提供標準化的應用託管服務。包括應用的版本管理,發佈,上線後的觀測,自愈等等。例如對於無狀態的應用來說,一個底層物理節點的故障根本就不會影響到研發,因為應用託管服務基於標準化應用生命週期可以自動完成騰挪工作,在故障物理節點上將應用的容器下線,在新的物理節點上啟動同等數量的應用容器。我們看到,雲原生進一步的釋放了價值紅利。

在此基礎上,由於應用託管服務能夠感知到應用運行期的數據,例如業務流量的併發,cpu load,內存佔用等等,業務就可以配置基於這些指標的伸縮規則,由平臺執行這些規則,根據業務流量的實際情況增加或者減少容器數量,這就是最基本的 auto scaling,自動伸縮。這就能夠幫助用戶避免在業務低峰期限制資源,節省成本,提升運維效率。

在架構的演進過程中,研發運維人員在逐漸的把關注點從機器上移走,希望更多地由平臺系統管理機器,而不是由人去管理,這就是一個很樸素的 Serverless 理解。

Serverless 的核心概念

其實我們都知道,雖然說是 Serverless,但 Server(服務器)是不可能真正消失的,Serverless 裡這個 less 更確切的說是開發不用關心的意思。這就好比現代編程語言 Java 和 Python,開發就不用手工分配和釋放內存了,但內存還在哪裡,只不過交給垃圾收集器管理了。稱一個能幫助你管理服務器的平臺為 Serverless 平臺,就好比稱呼 Java 和 Python 為 Memoryless 語言一樣。

如果我們把目光放到今天雲的時代,那麼就不能狹義地把 Serverless 僅僅理解成為不用關心服務器。雲上的資源除了服務器所包含的基礎計算、網絡、存儲資源之外,還包括各種類別的更上層的資源,例如數據庫、緩存、消息等等。

2019年2月,UC 伯克利大學發表了一篇標題為《Cloud Programming Simplified: A Berkeley View on Serverless Computing》的論文,論文中也有一個非常清晰形象的比喻,文中這樣描述:

在雲的上下文中,Serverful 的計算就像使用低級的彙編語言編程,而 Serverless 的計算就像使用 Python 這樣的高級語言進行編程。例如如 c = a + b 這樣簡單的表達式,如果用匯編描述,就必須先選擇幾個寄存器,把值加載到寄存器,進行數學計算,再存儲結果。這就好比今天在雲環境下 Serverful 的計算,開發首先需要分配或找到可用的資源,然後加載代碼和數據,再執行計算,將計算的結果存儲起來,最後還需要管理資源的釋放。

論文中所謂的 Serverful 計算,是我們今天主流的使用雲的方式,但不應該是未來我們使用雲的方式。我認為 Serverless 的願景應該是 Write locally, compile to the cloud,即代碼只關心業務邏輯,由工具和雲去管理資源。現在我們對 Serverless 有了一個比較總體但抽象的概念,下面我再具體介紹一下 Serverless 平臺的主要特點。

第一:不用關心服務器

管理一兩臺服務器可能不是什麼麻煩的事情,管理數千甚至數萬臺服務器就沒那麼簡單了。任何一臺服務器都可能出現故障,如果自動識別故障,摘除有問題的實例,這是 Serverless 平臺必須具備的能力;此外,操作系統的安全補丁升級,需要做到不影響業務,自動完成;日誌和監控系統需要默認打通;系統的安全策略需要自動配置好以避免風險;當資源不夠的時候,需要能夠自動分配資源並安裝相關的代碼和配置,等等。

第二:自動彈性

今天的互聯網應用都被設計成能夠按可伸縮的架構,當業務有比較明顯的高峰和低谷的時候,或者業務有臨時的容量需求的時候(比如營銷活動),Serverless 平臺都能夠及時且穩定的實現自動彈性。為了實現這個能力,平臺需要有非常強大的資源調度能力,以及對應用各項指標(如 load,併發)非常敏銳的感知能力。

第三:按實際資源使用計費

Serverful 的方式使用雲資源,是按佔用而非使用計費的,用戶在雲上購買了三臺 ECS,那麼不管用戶實際使用了這三臺 ECS 多少的 CPU 和內存,他都需要支付這三臺 ECS 整體的費用。Serverless 模式下,用戶是按實際使用的資源付費的,例如一個請求實際使用了一臺 1core2g 規格資源 100ms 的時間,那麼用戶就只需要為該規格的單價乘以時間(即100ms)付費。類似的,用戶如果用的是 Serverless 數據庫,那麼就只需要為 query 實際消耗的資源,以及數據存儲的資源付費。

第四:更少的代碼,更快的交付速度

基於 Serverless 架構的代碼通常會重度使用後端的服務,將數據、狀態管理等內容從代碼中分離出去;此外,更徹底的 FaaS 架構則把代碼的 Runtime 也交給了平臺管理。這就意味著,同樣的應用,Serverless 模式下的代碼相比 Serverful 模式會少很多,因此不論是從分發還是啟動,都會更快。Serverless 平臺也通常提供非常成熟的代碼構建發佈,版本切換等特性,提升交付速度。

實現 Serverless 面臨的挑戰

講了那麼多 Serverless 的好處,但是實際要在主流的場景大規模的落地 Serverless,並不是一件容易的事情,面臨的挑戰有很多,下面我具體分析一下這些挑戰:

挑戰一:業務輕量化困難

要實現徹底的自動彈性,按實際使用資源付費,就意味著平臺需要能夠在秒級甚至毫秒級別擴容出業務實例。這對基礎設施是一個挑戰,對業務,尤其是比較龐大的業務應用來說,更提出了很高的要求。如果一個應用的分發和啟動需要十分鐘,那麼自動彈性的響應能力就基本無法跟上業務流量的變化了。解決這個問題有很多方法,微服務化能夠把巨型應用拆小;而 FaaS 就通過一種全新的應用架構,把應用拆分成更細粒度的函數來做到輕量化,當然,這種方法的缺點是需要業務做比較大的改造。對於 Java 語言來說,Java 9 引入的 modules,以及 GraalVM 的 native image 技術都能夠幫助 Java 應用程序瘦身,降低啟動時間。

挑戰二:基礎設施響應能力不足

一旦 Serverless 的應用或者函數的實例能夠實現秒級,甚至毫秒級擴容,相關基礎設施就很快會面臨巨大的壓力。最常見的基礎設施就是服務發現和日誌監控系統,原本整個集群實例的變化頻率可能是每小時幾次,現在這個頻率變成了每秒幾次;此外,如果這些系統的響應能力跟不上實例變化的速度,例如對於業務來說,容器實例 2 秒就完成了擴容,但還需要等待 10 秒服務發現才能完成同步,那麼整個體驗也就大打折扣了。

挑戰三:業務進程生命週期與容器不一致

Serverless 平臺依賴標準化的應用生命週期,才能實現完全自動的容器騰挪,應用自愈等特性。而在基於標準容器及 Kubenetes 的體系下,平臺能控制的生命週期就是容器的生命週期。因此就需要業務做到業務進程的生命週期和容器的生命週期保持一致,具體包括啟動、停止、以及 readiness probe 和 liveness probe 的規範等等。在實際情況中,很多業務雖然做了容器化改造,但實際上容器中除了包含業務主進程之外,還包括很多輔助進程,這也會導致業務進程和容器的生命週期不一致。

挑戰四:可觀測能力需完善

在 Serverful 的模式下,如果生產環境出現任何問題,服務器是不會消失的,用戶會很自然的想到登陸到服務器上去,操作 linux 命令,搜索日誌,分析進程,甚至 dump 內存來進行問題分析。到了 Serverless 模式下,我們說用戶不需要關心服務器了,也就是說默認情況下是看不到服務器了,那麼這個時候如果系統出現異常了,而且平臺無法完成自愈怎麼辦呢?用戶還是需要有豐富的排查診斷工具,能夠觀測到包括流量、系統指標、依賴服務等等各方面綜合的狀態,以實現快速準確的問題診斷。當圍繞 Serverless 模式的全面可觀測能力不足的時候,用戶必然不會對此感到放心。

挑戰五:研發運維心智需要改變

幾乎所有的研發,在職業生涯中第一次部署自己的應用程序的時候,都是面向一臺服務器的,或者說是面向一個 IP 的,這是一種非常強大的習慣。今天我們依然能看到很多的應用程序還是有狀態的,無法做到自動更換實例;也能看到很多的變更部署行為和 IP 綁定了起來,例如單獨選一臺特定的機器做 Beta 等等;還有許多發佈系統,在做 Rolling Update 的時候,是不會更換實例的,相關的運維繫統也就基於這個假設建設能力了。在 Serverless 逐漸落地的過程中,研發需要轉換一些思維的模式,逐步地去適應 “IP 隨時可能會發生變化” 這樣一種心智,轉而更多的從服務版本,以及從流量的視角去運維自己的系統。

小結

讓我們回到《Cloud Programming Simplified: A Berkeley View on Serverless Computing》論文中那個精彩的比喻:今天我們使用雲就像是用匯編寫代碼。我認為這種現狀會不斷地得以改觀,理想情況下,用戶交付給平臺部署的包中,應該 100% 是用戶描述業務的代碼。雖然現狀遠不是那樣,不過可以看到很多技術,如 Service Mesh,Dapr.io,cloudsteate.io,都在把與業務無關的,但是分佈式架構又必須的邏輯,從業務的運行時中剝離出去,交給平臺管理。這種趨勢在最近一年中逐漸清晰和強烈,對此 Bilgin Ibryam 在《Multi-Runtime Microservices Architecture》一文中做了很好的總結,一併推薦閱讀。

本文中我們看到 Serverless 的演進對應用架構,到持續交付,服務治理、運維監控都提出了新的要求,其實除此之外,Serverless 也會對計算存儲網絡等更底層的技術設施提出更高的響應能力要求。因此,這其實是一次貫穿應用、平臺、基礎設施多個層面的,比較徹底的技術演進,有幸參與其中,我覺得還是非常興奮的。

為了更多開發者能夠享受到 Serverless 帶來的紅利,這一次,我們集結了 10+ 位阿里巴巴 Serverless 領域技術專家,打造出最適合開發者入門的 Serverless 公開課,讓你即學即用,輕鬆擁抱雲計算的新範式——Serverless。

點擊即可免費觀看課程:https://developer.aliyun.com/learning/roadmap/serverless

阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”

Leave a Reply

Your email address will not be published. Required fields are marked *