按語
Heroku是云應(yīng)用平臺(tái)的先驅(qū),從對(duì)外提供服務(wù)以來,他們已經(jīng)有上百萬應(yīng)用的托管和運(yùn)營(yíng)經(jīng)驗(yàn)。其創(chuàng)始人Adam Wiggins根據(jù)這些經(jīng)驗(yàn),提出了十二要素應(yīng)用宣言 。The Twelve-Factor App定義了一個(gè)優(yōu)雅的互聯(lián)網(wǎng)應(yīng)用在設(shè)計(jì)過程中,需要遵循的一些基本原則。
不過, The Twelve-Factor是在特定的時(shí)期,針對(duì)特定的平臺(tái)實(shí)踐所總結(jié)出來的。12元素依然璀璨,很多原則依然具有普適性;但是在應(yīng)用全面遷移到云端的今天,Cloud Native時(shí)代的應(yīng)用開發(fā),需要有更多與時(shí)俱進(jìn)的實(shí)踐新原則。The Twelve-Factor的哪些原則依然是適用的?哪些在實(shí)踐需要與時(shí)俱進(jìn)?這些都是眾多Cloud Native的實(shí)踐者需要探求的答案。
新原則1:微服務(wù)應(yīng)該以無狀態(tài)的方式運(yùn)行
The Twelve-Factor指出一個(gè)應(yīng)用在運(yùn)行時(shí),應(yīng)該以一個(gè)或者多個(gè)無狀態(tài)的進(jìn)程來運(yùn)行。進(jìn)程之間需要做到無狀態(tài),并且無共享。任何需要持久化的數(shù)據(jù),都應(yīng)該寫入到后端服務(wù)中,譬如數(shù)據(jù)庫。這一原則,目的是避免進(jìn)程和進(jìn)程之間的耦合。讓每一個(gè)進(jìn)程,能夠獨(dú)立于其他實(shí)體單獨(dú)構(gòu)建和運(yùn)行。
在很多在線系統(tǒng)中,會(huì)使用session(會(huì)話)來傳遞當(dāng)前的狀態(tài)。當(dāng)被調(diào)用方接收到session后,會(huì)將它保存下來,后續(xù)的請(qǐng)求,都會(huì)被路由到這個(gè)服務(wù)中。這時(shí)請(qǐng)求和請(qǐng)求之間,會(huì)有嚴(yán)格的調(diào)用順序。Cloud Native的實(shí)踐原則是需要避免這種情況。
在Cloud Native理念中,每一個(gè)功能實(shí)體實(shí)際上是以一個(gè)微服務(wù)的形式運(yùn)行的。微服務(wù)是一個(gè)單獨(dú)的自治系統(tǒng),它可以不依賴其他服務(wù)而單獨(dú)存在。所有的微服務(wù),都應(yīng)該是以一種無狀態(tài)的接口對(duì)外提供服務(wù)(譬如Restful API)。微服務(wù)自身不應(yīng)該保存任何的狀態(tài)。如果微服務(wù)需要持續(xù)地保存數(shù)據(jù),應(yīng)該采用的做法是:調(diào)用服務(wù)化的存儲(chǔ),將數(shù)據(jù)保存在另一個(gè)存儲(chǔ)服務(wù)里面。微服務(wù)之所以小塊頭能發(fā)揮大能量,正是源于無狀態(tài)的設(shè)計(jì)從而保證可以同時(shí)由多個(gè)實(shí)例提供服務(wù),讓服務(wù)能力能夠自由的伸縮。
當(dāng)然,在實(shí)際的實(shí)踐過程中,特別是針對(duì)大的系統(tǒng),很難做到完全無狀態(tài)的拆分。對(duì)一個(gè)完整的微服務(wù)架構(gòu),會(huì)分為事務(wù)性服務(wù)和存儲(chǔ)型服務(wù)。通常說來,事務(wù)性服務(wù)需要做到無狀態(tài)設(shè)計(jì);所有的持久化數(shù)據(jù),可以通過存儲(chǔ)型服務(wù)來進(jìn)行存儲(chǔ)和讀取。存儲(chǔ)型服務(wù)盡量使用云端提供的集中式的服務(wù)化存儲(chǔ)能力,譬如云端的對(duì)象存儲(chǔ)。
新原則2:應(yīng)通過配置來唯一定義一個(gè)系統(tǒng)
The Twelve-Factor的第五條原則提到了應(yīng)用需要嚴(yán)格區(qū)分構(gòu)建、發(fā)布、運(yùn)行這三個(gè)步驟:譬如直接修改處于運(yùn)行狀態(tài)的代碼是非常不可取的做法,因?yàn)檫@些修改很難再同步回構(gòu)建步驟。The Twelve-Factor的第五原則,很好的規(guī)范了一個(gè)應(yīng)用從開發(fā)到運(yùn)營(yíng)的標(biāo)準(zhǔn)化的操作流程。但是第五原則,只是保證了應(yīng)用源碼的唯一性。很多時(shí)候,一個(gè)系統(tǒng)的故障,并不僅僅是由源碼導(dǎo)致的,很大一部分故障,和配置以及環(huán)境的變化存在關(guān)系。所以The Twelve-Factor的第五原則在Cloud Native的理念下,需要與時(shí)俱進(jìn)。
Cloud Native在實(shí)踐時(shí),是通過Docker+微服務(wù)的方式去實(shí)現(xiàn)的。Docker實(shí)現(xiàn)了Build、Ship、Run的統(tǒng)一。任何系統(tǒng),都是可以通過一些配置,唯一定義出來的。當(dāng)這個(gè)系統(tǒng)定義出來以后,應(yīng)該是能夠重構(gòu)出來,不隨著時(shí)間、運(yùn)行環(huán)境或依賴條件變化而變化。同時(shí),這個(gè)系統(tǒng)不管處于開發(fā)階段、測(cè)試階段還是運(yùn)營(yíng)階段,其狀態(tài)都是唯一的。
譬如,在實(shí)踐過程中,可以通過Docker Compose的YAML文件唯一的定義一個(gè)容器間互聯(lián)的系統(tǒng)。這個(gè)系統(tǒng)的配置是唯一確定的,可以在任何的容器環(huán)境下去執(zhí)行。會(huì)有一個(gè)唯一的倉庫(Docker Registry)來存儲(chǔ)鏡像。所有的鏡像,都是通過Dockerfile唯一定義的。當(dāng)觸發(fā)了源碼的變更以后,這個(gè)系統(tǒng)的各個(gè)組件可以自動(dòng)的去構(gòu)建,然后更新到“倉庫”,在通過Docker Compose組裝起來。只要遵循了這套標(biāo)準(zhǔn)化的流程,系統(tǒng)不會(huì)區(qū)分開發(fā)環(huán)境,測(cè)試環(huán)境,運(yùn)營(yíng)環(huán)境。所有的東西,就只有一個(gè)環(huán)境;這個(gè)環(huán)境,是唯一的、可定義的。
在實(shí)踐這條原則時(shí),需要遵循以下幾條規(guī)范:
需要有唯一的源碼庫,并保證任何的變更都是在源碼托管庫中進(jìn)行
通過Dockerfile來構(gòu)建鏡像而非通過運(yùn)行中的容器來打包鏡像
通過配置來定義容器之間的連接關(guān)系而非手動(dòng)的部署
新原則3:應(yīng)該使用服務(wù)化存儲(chǔ)
The Twelve-Factor 有一條原則是“把后端服務(wù)(backing services)當(dāng)作附加資源”,后端服務(wù)是指程序運(yùn)行所需要的通過網(wǎng)絡(luò)調(diào)用的各種服務(wù),如數(shù)據(jù)庫(MySQL,CouchDB)、消息/隊(duì)列系統(tǒng)(RabbitMQ,Beanstalkd)、SMTP 郵件發(fā)送服務(wù)(Postfix)以及緩存系統(tǒng)(Memcached)。這些都是作為“資源”來對(duì)待,目的是為了保證模塊之間的松耦合。
作為一個(gè)系統(tǒng)中最重要的角色,存儲(chǔ)模塊當(dāng)然必不可少。存儲(chǔ)有很多種類:塊存儲(chǔ)、對(duì)象存儲(chǔ)、數(shù)據(jù)庫存儲(chǔ)、緩存。傳統(tǒng)上,我們接觸比較多的是塊存儲(chǔ)。在Cloud Native的理念下,一個(gè)系統(tǒng)中,所有的組成實(shí)體都可以服務(wù)化。有事務(wù)型的服務(wù),也有存儲(chǔ)型服務(wù)。微服務(wù)之間是一種松散耦合的關(guān)系。服務(wù)和服務(wù)之間,是沒有任何耦合關(guān)系的,只有調(diào)用關(guān)系。當(dāng)一個(gè)服務(wù),需要存儲(chǔ)數(shù)據(jù)怎么辦?一種方案是把數(shù)據(jù)存在在服務(wù)內(nèi)部,這樣勢(shì)必導(dǎo)致了服務(wù)存在狀態(tài),從而限制了服務(wù)的橫向擴(kuò)展的能力。前面一節(jié),我們提到了一個(gè)重要原則是,事務(wù)型服務(wù)盡量保證是無狀態(tài)的。所以當(dāng)一個(gè)事務(wù)型服務(wù)需要存儲(chǔ)數(shù)據(jù)時(shí),應(yīng)該是將數(shù)據(jù)存儲(chǔ)到另外一個(gè)存儲(chǔ)型服務(wù)中,通過存儲(chǔ)型服務(wù)提供的標(biāo)準(zhǔn)接口和協(xié)議讀取或者寫入數(shù)據(jù)。在云上我們通常使用的對(duì)象存儲(chǔ),或者云端的數(shù)據(jù)庫,就是這種服務(wù)化的存儲(chǔ)方式。
使用服務(wù)化存儲(chǔ),可以帶來三個(gè)方面的好處:
將存儲(chǔ)和邏輯處理分離,讓系統(tǒng)能夠自動(dòng)化的重構(gòu)出來
統(tǒng)一存儲(chǔ),不需要單獨(dú)考慮服務(wù)內(nèi)部存儲(chǔ)的容錯(cuò)、備份等機(jī)制
做到事務(wù)型服務(wù)無狀態(tài),便于橫向擴(kuò)展
總結(jié)
The Twelve-Factor APP作為網(wǎng)絡(luò)應(yīng)用開發(fā)的最佳實(shí)踐原則,的確具有強(qiáng)大的生命力。每一條原則都是應(yīng)用開發(fā)的珠璣。但是技術(shù)總是不停的發(fā)展,在云的時(shí)代,所有的應(yīng)用都會(huì)遷移到云端,完全基于云的架構(gòu)設(shè)計(jì)和開發(fā)模式需要一套全新的理念去承載。這個(gè)時(shí)候,Cloud Native的思想應(yīng)運(yùn)而生。在Cloud Native時(shí)代,The Twelve-Factor 的核心思想依然璀璨,但是應(yīng)該隨著這種新的理念去延伸、發(fā)展。文章提到的三條新原則,也正是The Twelve-Factor 的延伸。未來,隨著Cloud Native 思想在開發(fā)中使用越來越廣泛,一定會(huì)延伸出更多的實(shí)踐的原則。
資料附:Cloud Native時(shí)代12新要素
從一個(gè)代碼庫部署到多個(gè)環(huán)境——一個(gè)代碼庫,包括生產(chǎn)環(huán)境軟件包,確保了單一的信任源,從而保證了更少的配置錯(cuò)誤和更強(qiáng)的容錯(cuò)和復(fù)原能力。 依賴管理是聲明式的——云平臺(tái)根據(jù)這些聲明管理依賴,確保云應(yīng)用所需的庫和服務(wù)。 配置信息保存在環(huán)境中——環(huán)境變量是一種清楚、容易理解和標(biāo)準(zhǔn)化的配置方法,特別適合用不同編程語言編寫的無狀態(tài)應(yīng)用的使用。 將后臺(tái)服務(wù)視為附加的資源——將每一種資源都視為一種遠(yuǎn)程的資源,應(yīng)用因此具有容錯(cuò)和復(fù)原能力,因?yàn)樗环矫嬉缶幋a時(shí)就要考慮資源不可用的情況,另外一方面也增強(qiáng)微服務(wù)方法的好處。 區(qū)分構(gòu)建、發(fā)布和運(yùn)行階段——Cloud Native應(yīng)用的構(gòu)建流程把大部分發(fā)布配置挪到開發(fā)階段,包括實(shí)際的代碼構(gòu)建和運(yùn)行應(yīng)用所需的生產(chǎn)環(huán)境配置。 作為無狀態(tài)進(jìn)程運(yùn)行——盡量保持應(yīng)用棧每一層的輕量級(jí),保證Cloud Native基礎(chǔ)設(shè)施的速度和效率。 通過端口綁定對(duì)外暴露服務(wù)——Cloud Native應(yīng)用的服務(wù)接口優(yōu)先選擇 HTTP API 作為通用的集成框架。 通過添加無狀態(tài)進(jìn)程實(shí)現(xiàn)橫向擴(kuò)展——強(qiáng)調(diào)無狀態(tài)、無共享的設(shè)計(jì),這意味著依賴底層平臺(tái)就能實(shí)現(xiàn)橫向擴(kuò)展,不需要技術(shù)難度高的多線程編碼。 快速地啟動(dòng),優(yōu)雅地關(guān)停——假設(shè)任何進(jìn)程隨時(shí)都能啟動(dòng)和關(guān)停。 開發(fā)、預(yù)發(fā)布和生產(chǎn)環(huán)境運(yùn)行同樣的應(yīng)用和依賴配置——由于強(qiáng)調(diào)自動(dòng)化和在每個(gè)階段使用同一個(gè)云平臺(tái),如果每個(gè)人用同樣的服務(wù)器配置,那么“應(yīng)用在我這里是可以的”就意味著在其他人或者環(huán)境那里也是可以的。 日志輸出到標(biāo)準(zhǔn)輸出,方便日志聚合和事件響應(yīng)——當(dāng)日志是由云平臺(tái)而不是應(yīng)用包含的庫處理時(shí),日志處理機(jī)制必須保持簡(jiǎn)單。 臨時(shí)任務(wù)作為短時(shí)進(jìn)程運(yùn)行——在Cloud Native中,管理任務(wù)也是一個(gè)進(jìn)程,而不是特別的工具;同樣重要的是,管理任務(wù)的進(jìn)程不應(yīng)使用秘密的 API 或者內(nèi)部機(jī)制。作者簡(jiǎn)介
劉永峰,騰訊云高級(jí)產(chǎn)品經(jīng)理,布道師,十余年的產(chǎn)品及研發(fā)管理經(jīng)驗(yàn)。國(guó)內(nèi)最早一批從事可信計(jì)算研究的探索者。曾就職于中興通訊,負(fù)責(zé)流媒體Server后臺(tái)架構(gòu)設(shè)計(jì),Linux內(nèi)核相關(guān)的研究。2011年起加入騰訊,一直從事公有云的產(chǎn)品設(shè)計(jì),云計(jì)算市場(chǎng)趨勢(shì)分析和研究,云計(jì)算技術(shù)的推廣與普及。在技術(shù)和產(chǎn)品領(lǐng)域均具有豐富的行業(yè)經(jīng)驗(yàn)。目前主要關(guān)注Docker,微服務(wù),Cloud Native, 企業(yè)云化趨勢(shì)等相關(guān)領(lǐng)域。