架構新紀元(二):什麼是雲原生?

雲原生(Cloud Native)最初是由 Pivotal 公司的 Matt Stine 於 2013 年提出的。Pivotal 公司 先後開源了雲原生的 Java 開發框架 Spring Boot 和 Spring Cloud。隨後,Google 在 2015 年成立 了 CNCF(Cloud Native Computing Foundation),使得雲原生受到越來越多的關注。

概述

要想理解什麼是雲原生,我們需要先理解什麼是雲。

有人認爲“雲”的同義詞是“可公開所有信息的互聯網”,這個說法是不正確的。雲一般指 的是一個提供資源的平臺,雲計算的本質是按需分配資源和彈性計算。

顧名思義,雲原生應用即專門爲在雲平臺部署和運行而設計的應用。雲原生應用並非完全顛覆傳統的應用,採用雲原生的設計模式可以優化和改進傳統應用模式,使應用更加適合在雲平臺上運行。

在雲計算越來越流行的今天,雲原生成了一個必然的導向。雲原生存在的意義是解放開發和運維,而不是讓開發和運維工作變得更加複雜和繁重。

其實,大部分傳統應用即便不做任何改動,也可以在基於 Linux 操作系統內核的雲平臺上 部署和運行,但是僅以能夠部署和運行爲主要目的,將雲主機當作物理機一樣使用,是無法充 分利用雲平臺的能力的。

讓應用能夠利用雲平臺實現資源的按需分配和彈性伸縮,是雲原生應用被重點關注的地方。 雲原生還關注規模,分佈式系統應該具備將節點擴展到成千上萬個的能力,並且這些節點應具 有多租戶和自愈能力。

雲原生使得應用本身具有“柔性”,即面對強大壓力的緩解能力以及壓力過後的恢復能力。 正所謂“剛而易折,柔則長存”,對於一個單機處理能力很強的“剛性”系統而言,一旦崩潰, 則很難恢復;而通過雲原生實現的關注分佈式與可水平伸縮的“柔性”系統,是不太容易全線 覆滅的。

從本質上來說,雲原生是一種設計模式,它要求雲原生應用具備可用性和伸縮性,以及自動化部署和管理的能力,可隨處運行,並且能夠通過持續集成、持續交付工具提升研發、測試與發佈的效率。

在雲原生體系中,有下面兩組詞語用於形容應用。

  • 無狀態(stateless)、牲畜(cattle)、無名(nameless)、可丟棄(disposable):表示應用 並未採用本地內存和磁盤存儲狀態和日誌,因此可以將應用隨意部署到另一個全新的 環境中,在本書中我們將這類應用統稱爲無狀態應用。

  • 有狀態(stateful)、寵物(pet)、有名(having name)、不可丟棄(non-disposable):表 示應用狀態將依賴於本地的運行環境,因此無法將應用隨意部署至其他環境,應用是 不能隨意擴展的,在本書中我們將這類應用統稱爲有狀態應用。

雲原生與十二要素

十二要素(The Twelve Factors)是由 Heroku 團隊提出的雲應用設計理念,它爲構建流程標 準化和高可移植的 SaaS 應用提供了完善的方法論。遵循十二要素設計的應用具備雲原生應用的 所有特徵。十二要素適用於任何語言開發的後端應用服務,它提供的方法論和核心思想如下。

  • 將流程自動化和標準化,降低新員工的學習成本。
  • 劃清與底層操作系統間的界限,以保證最大的可移植性。
  • 適合部署在現代雲平臺上,避免對服務器與操作系統進行管理。
  • 將開發環境與生產環境的差異降至最低,便於實施持續交付和敏捷開發。
  • 應用可以在不改變現有工具、架構或開發流程的情況下,方便地進行水平伸縮。

十二要素重點關注應用程序的健康成長,開發者之間的有效代碼協作,以及避免軟件腐蝕。 十二要素的內容如圖 1-8 所示。

下面我們來逐條介紹一下十二要素。

1.基準代碼(Codebase)

同一應用對應同一套基準代碼,並能夠多次部署。

部署到不同環境的同一個應用,其基準代碼庫應該相同,但每份部署可以包含各自環境中的不同配置。一次部署對應一個運行起來的應用程序,應用與部署的關係是一對多的,這體現了應用代碼的可重用性。同一套基準代碼可以重用到多次部署中去,共享的是代碼,而不同的僅僅是配置。從另一個角度來說,非運行時的應用對應的是代碼倉庫,它的每一個運行時實例都對應一次部署,同一代碼倉庫可以保障應用的復原能力。

推薦使用 Git、SVN 等優秀的源代碼管理工具作爲基準代碼庫。基準代碼與部署的關係如 圖 1-9 所示。

2.依賴(Dependencies)

顯式聲明第三方依賴。

隨着技術的發展,應用程序的開發已不再是一個從零開始的過程,大量的第三方類庫使得工程師們可以站在巨人的肩膀上進行增量式開發。應用程序不應隱式地依賴類庫,而是應該通過依賴清單明確地聲明其依賴項。

顯式聲明依賴簡化了環境配置流程,開發工程師僅需要安裝編程語言環境和它對應的依賴管理工具,並從代碼庫中檢索出代碼,即可通過一個命令來構建所有的依賴項,從而輕鬆地開始工作。

十二要素要求應用同樣不應該隱式依賴某些系統工具,比如 curl。即使這些系統工具存在 於所有的現代操作系統中,也無法保證未來的操作系統都能支持或兼容現有應用的使用方式。

現代編程語言都會提供依賴打包管理工具,如 Java 語言的Maven、Gradle 以及早期的 Ant 等。

3.配置(Config)

將配置存儲至環境變量。

應用的配置在不同環境中部署時也會有所差異,若應用將配置以編碼的方式寫入程序的常量,則會造成代碼與配置混淆。十二要素強調配置應該與代碼分離,不應在源碼中包含任何與環境相關的敏感信息。

雖然將配置提煉到屬性文件可以實現將其與代碼分離,但屬性文件仍然可能會被不小心地提交至源碼倉庫。因此,十二要素推薦將配置存儲於環境變量中,這樣可以非常方便地在不同的部署環境間修改,而無須改動代碼。

與配置文件相比,環境變量與語言和系統無關。將配置存儲在環境變量中能夠方便與 Docker 等基於容器的應用配合使用,也易於與 Kubernetes 的 ConfigMap 配合使用。將配置排除在代碼 之外的標準取決於,應用是否可以立刻開源且不必擔心暴露任何系統的敏感信息。

十二要素並不贊同採用配置分組的方式管理配置。有些開發團隊願意將應用的配置按照特 定的環境(如開發環境、測試環境和生產環境)進行分組。採用配置分組方式不利於擴展,當 工程師添加他們自己的開發環境(例如 john-dev)時,將導致各種配置組合激增,給管理部署 增加額外的不確定性。

十二要素要求環境變量的粒度足夠小且相對獨立,它們不應該作爲環境組合使用,而是應該獨立存在於每個部署之中。當應用程序擁有更多種類的配置項或進行環境部署時,採用這種配置管理方式更容易實現平滑過渡。

需要特別指出的是,這裏所指的配置並不包括應用程序的內部配置。舉例來說,Spring 容 器中 Bean 的依賴注入配置,或者 Servlet 的映射配置文件 web.xml 等,它們更應該被認爲是代 碼的一部分。

4.後端服務(Backing Services)

將後端服務作爲鬆耦合的資源。

後端服務是指應用程序所依賴的通過網絡調用的遠程服務,如數據庫、緩存、消息中間件 以及文件系統等,不同後端服務之間的區別僅僅在於資源的 URL 不同。

十二要素要求應用程序不應該區別對待本地服務和遠程服務,它們同樣都屬於附加資源。 應用程序可以在不改動任何代碼、僅修改資源地址的情況下,將出現硬件問題的數據庫切換爲 備份數據庫,或將本地數據庫切換爲雲數據庫。應用程序與這些附加資源應該保持鬆耦合的狀 態。圖 1-10 展示了後端服務鬆耦合的狀態。

5.構建、發佈、運行(Build、Release、Run)

嚴格分離構建階段與運行階段。

分離構建階段與運行階段的根本在於,要嚴格區分應用的非運行時狀態和運行時狀態。構建是將應用的源代碼編譯打包成可執行軟件的過程,屬於非運行時行爲。將基準代碼轉化爲一份部署一般要經過構建階段、發佈階段和運行階段。構建階段是將源碼從編譯狀態轉化爲可執行的二進制文件的過程;發佈階段是將構建結果與當前部署所需要的配置相結合,並分發至運行環境的過程;運行階段是在執行環境中啓動一系列發佈完畢的應用程序進程的過程。

十二要素規定,禁止在運行階段改動代碼,這樣做會導致基準代碼失去同步。建議每個發 布版本對應一個唯一的發佈 ID,發佈版本只能追加而不能修改,除了回滾,其他變動都應該產 生新的發佈版本。構建與發佈的流程如圖 1-11 所示。

6.進程(Processes)

將應用作爲無狀態的進程運行。

應用進程應該是無狀態的。只有無狀態的應用才能做到水平伸縮,從而利用雲平臺彈性伸縮的能力,而需要持久化的數據應該存儲於後端服務中。

在有些遺留系統的設計中,Web 應用通常會將用戶會話中的數據緩存至內存,並保證將同 一用戶的後續請求路由到同一個進程,這種會話被稱爲黏性會話。十二要素並不推薦這種做法, 會話數據應該保存至 Redis 這樣的帶有過期時間的緩存中,並作爲後端服務提供服務。

7.端口綁定(Port Binding)

通過端口綁定對外發布服務。

應用本身對於發佈服務的環境不應該有過多的要求,不需要依賴雲平臺提供應用運行容器, 只要雲平臺分配某個端口對外發布服務即可。通過端口綁定訪問服務也意味着任何應用都可以 成爲另一個應用的後端服務。

例如,可以利用 Jetty 這種內嵌的 Web 服務器或 Spring Boot 等快速開發框架來開發包含可 發佈 HTTP 服務的應用。

8.併發(Concurrency)

能夠通過水平伸縮應用程序進程來實現併發。

雲平臺操作系統與 UNIX 操作系統類似,運行在系統之上的不同進程彼此獨立並且共享操作系統管理的硬件資源。不同的應用彼此獨立、互不干擾地運行在一個雲平臺上,可以充分利用雲平臺的整體計算能力。這樣的進程模型對於系統擴容非常實用。

開發人員應該將不同類型的工作分配給不同的進程,例如,將 HTTP 請求交給 Web 服務器 的進程來處理,將常駐後臺進程交給 worker 進程負責,將定時任務交給 clock 進程負責。這條 原則與微服務的設計原則有異曲同工之妙,它希望應用開發者將應用的職責儘可能進行拆分。 圖 1-12 清晰地展示瞭如何通過增加不同類型的應用進程來實現系統的水平伸縮。

9.已處理(Disposability)

可以快速啓動和優雅關閉應用。

快速啓動是爲了充分利用雲平臺根據需要調度資源的能力,在需要的時候,以最小的延時擴展計算能力,提供服務。優雅關閉是爲了保證應用邏輯的完整性,將該完成的任務正確完成並釋放資源,將未能完成的任務重新交回系統由其他應用的運行實例來繼續完成。隨時可能有大量部署在雲平臺上的應用實例啓動、運行和關閉,因此快速啓動和優雅關閉應用對於維持系統的高性能和穩定性尤爲重要。

10.開發環境與線上環境等價(Dev/Prod parity)

要保持開發環境與線上環境等價。

開發環境和線上環境之間存在着很多差異,主要包括代碼差異和操作差異。開發人員正在編寫的代碼可能需要很長時間纔會上線,這將導致開發環境和線上環境的代碼差異很大。在開發環境中,代碼一般由開發人員編寫並調試,而在線上環境中,代碼則由運維人員部署,不同的操作方式也可能帶來環境的差異。

保持環境一致,可以提高功能測試和集成測試的有效性,避免出現開發環境測試正常但生 產環境出現問題的情況。推薦使用 Jenkins 等持續集成工具來縮短生產代碼和代碼庫中的代碼不 一致的時間,並採用自動化部署的方式避免操作差異。

11.日誌(Logs)

使用事件流處理日誌。

運行在雲平臺上的應用處在複雜的分佈式基礎設施之上,如果日誌仍然寫在硬盤的一個文件中,將給系統排錯或通過日誌挖掘信息帶來很大的困難,並且當日志與應用綁定時,應用不能作爲無狀態進程,也就無法充分利用雲平臺的擴容能力了。

爲了解決以上問題,我們應採取相應措施——應用將日誌輸出到標準輸出(STDOUT),然 後由雲平臺統一收集並處理。在線上環境中,進程的輸出事件流由運行環境截獲,運行環境會 將所有輸出事件流整合在一起,然後發送給一個或多個最終的處理程序,用於查看或長期存檔。

推薦使用 Flume、Filebeat 或 fluentd 等日誌收集工具。日誌事件流最終可以被髮送到 Elasticsearch 或 Splunk 這樣的日誌索引及分析系統中,用於排錯查詢和後期分析。

12.管理進程(Admin Processes)

將後臺管理任務當作一次性進程運行。

與用來處理應用的常規業務進程不同,工程師經常希望執行一些用於管理或維護應用的一次性任務,這類任務被稱爲後臺管理任務,例如檢查和清理環境、遷移數據等。

這些後臺管理任務應該作爲一次性進程,與常駐進程使用同樣的環境,基於同樣的代碼庫和配置發佈運行。總而言之,一次性進程同樣應該遵循前面提到的十一個要素。

遵循十二要素的應用程序環境是一次性且可複製的。由於應用程序的狀態均通過後端服務持有,因此無狀態的應用有助於編排系統自動化擴展。擴容時,編排系統僅須將應用程序的運行時環境數量擴充到期望位並直接啓動進程即可;縮容時,則需要停止應用進程並刪除環境,無須進行環境狀態備份。

要想了解有關十二要素的詳細內容,請參見官方網站:https://www.12factor.net/。

相關文章
架構新紀元(一):從分佈式架構到雲原生架構

本文節選自圖書《未來架構:從服務化到雲原生》第一章。本書對快速演進中的雲原生數據架構、典型分佈式數據庫中間件進行了剖析,重點介紹 Service Mesh 等新興概念,創新性地提出了 Database Mesh 的理念,深度揭祕 Apache 項目——ShardingSphere。

購買鏈接https://u.jd.com/sbmG4Y

作者簡介
張亮
京東數科數據研發負責人,Apache ShardingSphere 發起人兼 PPMC 成員。熱愛分享,擁抱開源,主張代碼優雅化,擅長以 Java 爲主的分佈式架構以及以 Kubernetes 和 Mesos 爲主的雲平臺的構建。ShardingSphere 已進入 Apache 軟件基金會,是京東集團首個進入 Apache 的開源項目,也是 Apache 首個分佈式數據庫中間件。

吳晟
Apache SkyWalking 創始人及 PPMC 成員,Apache ShardingSphere 原型作者及 PPMC 成員,Apache Zipkin 貢獻者,Apache 孵化器導師,CNCF 基金會 OpenTracing 標準化委員會成員,W3C Trace Context 規範貢獻者。擅長分佈式架構、性能監控與診斷、分佈式追蹤、雲原生監控等領域。

敖小劍
具有十七年軟件開發經驗,資深碼農,微服務專家,Cloud Native 擁護者,敏捷實踐者,Service Mesh 佈道師,ServiceMesher 中文社區聯合創始人。專注於基礎架構建設,對微服務、雲計算等相關技術有着深入研究和獨到見解。

宋淨超
螞蟻金服雲原生布道師,ServiceMesher 中文社區聯合創始人,Kubernetes 社區成員,Istio 社區成員,《Cloud Native Go》《Python 雲原生》《雲原生 Java》等圖書譯者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章