掌握可擴(kuò)展和可維護(hù)應(yīng)用程序:12-Factor應(yīng)用程序開發(fā)的全面指南
1*vhxOhTuKSyuuAKu-nUQ5SA.jpeg
在今天的快節(jié)奏世界中,軟件開發(fā)人員需要?jiǎng)?chuàng)建可擴(kuò)展、可維護(hù)和適應(yīng)性強(qiáng)的應(yīng)用程序。12-Factor應(yīng)用程序方法論是一組最佳實(shí)踐,可以幫助開發(fā)人員實(shí)現(xiàn)這些目標(biāo)。
本文深入探討了12個(gè)因素,詳細(xì)解釋了它們的重要性以及如何將它們應(yīng)用到您自己的應(yīng)用程序中。通過遵循這些原則,您可以創(chuàng)建更可靠、更高效且更易于管理的軟件。
1. 代碼庫
這個(gè)因素可能是最廣為人知、最簡單的12個(gè)因素之一,但它對(duì)開發(fā)過程有著重大影響。將所有代碼放在一個(gè)地方允許團(tuán)隊(duì)中的每個(gè)人都從同一個(gè)真相源工作。這簡化了跟蹤變更、協(xié)作和沖突避免。
擁有單一的代碼庫有許多好處。以下是一些例子:
- 更容易跟蹤變更: 當(dāng)所有代碼都在一個(gè)地方時(shí),很容易看到誰做了什么變更以及何時(shí)做的。這對(duì)于調(diào)試和故障排除可能有幫助。
- 最小化代碼沖突: 當(dāng)多人在同一代碼上工作時(shí),他們可能會(huì)進(jìn)行沖突的更改。擁有單一的代碼庫有助于避免這種情況,因?yàn)榇_保每個(gè)人都在同一版本的代碼上工作。
- 促進(jìn)協(xié)作: 當(dāng)每個(gè)人都從同一個(gè)代碼庫工作時(shí),更容易進(jìn)行協(xié)作和分享想法。這可能導(dǎo)致更好的代碼和更高效的開發(fā)過程。
0*QYUcsDdE0q6LhCnr.jpeg
如果您有微服務(wù)架構(gòu)的經(jīng)驗(yàn),您可能會(huì)想知道為什么在那里不遵循這一做法。然而,事實(shí)并非如此。在微服務(wù)架構(gòu)中,每個(gè)服務(wù)都是一個(gè)獨(dú)立的應(yīng)用程序,因此每個(gè)服務(wù)都必須符合12-Factor開發(fā)原則。這就是為什么我們?yōu)槊總€(gè)服務(wù)單獨(dú)創(chuàng)建存儲(chǔ)庫的原因。
2. 依賴關(guān)系
即使是剛剛?cè)腴T的開發(fā)人員,也可能對(duì)庫依賴性有所了解。有許多用于不同需求的庫可供選擇,這就是為什么我們通常會(huì)不加思考地安裝它們,而不知道它可能帶來的混亂。
這個(gè)因素強(qiáng)調(diào)了明確聲明和隔離依賴關(guān)系的重要性。這意味著您應(yīng)該指定應(yīng)用程序依賴的庫和包的確切版本。您還應(yīng)該隔離依賴項(xiàng),以確保它們不會(huì)相互影響。
0*z7NYskfvg-CDZDlQ.jpeg
明確聲明和隔離依賴關(guān)系的重要性有幾個(gè)原因。
- 首先,它使跟蹤依賴關(guān)系的變更變得更容易。 如果更改依賴項(xiàng)的版本,您需要確保應(yīng)用程序仍然正常工作。通過明確聲明依賴關(guān)系,您可以輕松查看已進(jìn)行的更改以及它們對(duì)應(yīng)用程序的影響。
- 其次,明確聲明依賴關(guān)系使部署應(yīng)用程序變得更容易。 在部署應(yīng)用程序時(shí),您需要確保所有依賴項(xiàng)都可用。通過明確聲明依賴關(guān)系,您可以確保部署包含了所有必要的依賴項(xiàng)。
- 第三,明確聲明依賴關(guān)系使調(diào)試應(yīng)用程序變得更容易。 如果應(yīng)用程序不起作用,您需要能夠跟蹤問題。通過明確聲明依賴關(guān)系,您可以輕松看到哪些依賴關(guān)系涉及到問題。
最近的Log4j漏洞是管理依賴關(guān)系重要性的很好示例。Log4j是一款廣泛使用的日志記錄庫,被許多應(yīng)用程序使用。該漏洞允許攻擊者在使用Log4j的系統(tǒng)上執(zhí)行任意代碼。如果受影響的應(yīng)用程序的開發(fā)人員管理了他們的依賴關(guān)系并更新了Log4j到最新/安全版本,這種情況本可以避免的。
3. 配置
將配置設(shè)置存儲(chǔ)在環(huán)境變量中是一種增強(qiáng)安全性、靈活性和可移植性的關(guān)鍵實(shí)踐。在代碼中硬編碼配置值可能會(huì)使應(yīng)用程序變得僵化且容易受到安全風(fēng)險(xiǎn)的威脅。通過將配置集中在環(huán)境變量中,您可以輕松地更改設(shè)置,而無需修改代碼。這使您的應(yīng)用程序更具靈活性和可移植性,并有助于提高安全性。
以下是存儲(chǔ)配置設(shè)置在環(huán)境變量中的好處的更詳細(xì)解釋:
安全性: 環(huán)境變量是一種在代碼之外存儲(chǔ)配置數(shù)據(jù)的方式。這對(duì)于存儲(chǔ)敏感信息,如密碼和API密鑰,可以提供保護(hù),以便不會(huì)暴露給公眾。
將API密鑰和密碼存儲(chǔ)在環(huán)境變量中相對(duì)安全,即使在現(xiàn)在,它仍然被廣泛使用,但還有更安全的選項(xiàng)可用。以下是存儲(chǔ)API密鑰和密碼的不同方式,從不安全到最安全:
- 將它們直接存儲(chǔ)在代碼中: 這是最不安全的選項(xiàng),因?yàn)槿魏慰梢栽L問您的代碼的人都將能夠訪問您的API密鑰和密碼。隨著環(huán)境層次結(jié)構(gòu)的提升,這將使您的代碼無法使用。
- 將它們存儲(chǔ)在環(huán)境變量中: 這是一種更安全的選項(xiàng),因?yàn)榄h(huán)境變量不存儲(chǔ)在代碼中,只有運(yùn)行的應(yīng)用程序才能訪問它們。但是,如果應(yīng)用程序代碼被破壞或環(huán)境變量文件被意外共享,環(huán)境變量可能會(huì)被公開。
- 將它們存儲(chǔ)在磁盤上的文件中: 這可以比將它們存儲(chǔ)在環(huán)境變量中更安全,因?yàn)槟梢栽O(shè)置文件權(quán)限以限制誰可以訪問文件。但是,如果文件未正確保護(hù),它們?nèi)匀豢赡軙?huì)被公開。
- 將它們存儲(chǔ)在對(duì)象存儲(chǔ)中: 對(duì)象存儲(chǔ),如AWS S3和Google Cloud Storage,比將文件存儲(chǔ)在磁盤上更安全。對(duì)象存儲(chǔ)可以加密,并且可以使用IAM策略限制訪問。
- 使用秘密管理器來存儲(chǔ)它們: 秘密管理器,如AWS Secrets Manager和GCP Secret Manager,是存儲(chǔ)API密鑰和密碼的最安全選項(xiàng)。秘密管理器使用加密和其他安全措施來保護(hù)您的秘密。
最后三個(gè)選項(xiàng)相對(duì)類似,因?yàn)樗鼈兌际褂眉用芎推渌踩胧﹣肀Wo(hù)您的秘密。它們之間的主要區(qū)別在于它們的管理方式。對(duì)象存儲(chǔ)由云提供商管理,而秘密管理器通常由使用它們的應(yīng)用程序或組織管理。人們也經(jīng)常使用像AWS/GCP秘密管理器這樣的提供商管理的秘密管理器。
最終,最適合您的選項(xiàng)將取決于您的具體需求和要求以及您的組織數(shù)據(jù)政策。如果您需要以安全的方式存儲(chǔ)敏感信息,那么我建議使用秘密管理器。
- 靈活性: 環(huán)境變量可以輕松更改,這使得將您的應(yīng)用程序適應(yīng)不同的環(huán)境變得容易。例如,您可以使用環(huán)境變量指定數(shù)據(jù)庫連接字符串、端口號(hào)或配置文件的位置。
- 可移植性: 環(huán)境變量與語言和平臺(tái)無關(guān),因此可以與任何應(yīng)用程序一起使用。這使得將您的應(yīng)用程序部署到不同的環(huán)境中變得容易。
4. 后備服務(wù)
現(xiàn)代應(yīng)用程序通常依賴于外部服務(wù),如數(shù)據(jù)庫、緩存系統(tǒng)和消息隊(duì)列。第四個(gè)因素要求我們將這些服務(wù)視為附加資源。這意味著您的應(yīng)用程序應(yīng)該使用配置設(shè)置連接到這些服務(wù),而不是將它們硬編碼到代碼中。
這種解耦使您具有很大的靈活性。您可以輕松更換或擴(kuò)展這些服務(wù),而無需更改應(yīng)用程序的代碼庫。這對(duì)于云原生應(yīng)用程序非常重要,因?yàn)樗鼈兺ǔ?huì)動(dòng)態(tài)部署和擴(kuò)展。
0*iuE-UVATJWbuTXtV.jpeg
以下是這在實(shí)踐中可能如何工作的示例。假設(shè)您的應(yīng)用程序使用數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)。第四因素將指定您不應(yīng)該將數(shù)據(jù)庫連接字符串硬編碼到應(yīng)用程序的代碼中。相反,您應(yīng)該將連接字符串存儲(chǔ)在配置文件中。當(dāng)應(yīng)用程序啟動(dòng)時(shí),它將從配置文件中讀取連接字符串并連接到數(shù)據(jù)庫。
這樣,如果需要更改應(yīng)用程序使用的數(shù)據(jù)庫,只需更新配置文件即可。您不需要對(duì)應(yīng)用程序的代碼庫進(jìn)行任何更改。
雖然這個(gè)示例非常簡單,但在構(gòu)建其他人將用作平臺(tái)的系統(tǒng)時(shí),您將能夠充分利用這個(gè)原則。確切地說,是使用這個(gè)原則的人才能從中受益,因?yàn)樗鼈兛梢韵哪腁PI的人。
5. 構(gòu)建、發(fā)布、運(yùn)行
這個(gè)因素被認(rèn)為是今天正在開發(fā)的任何現(xiàn)代服務(wù)的標(biāo)準(zhǔn)實(shí)踐,它規(guī)定應(yīng)用程序的構(gòu)建、發(fā)布和運(yùn)行階段應(yīng)該嚴(yán)格分開。構(gòu)建階段將您的代碼轉(zhuǎn)換為可執(zhí)行的構(gòu)件,發(fā)布階段將這些構(gòu)件與配置組合在一起,運(yùn)行階段啟動(dòng)應(yīng)用程序。
這種分離確保您的應(yīng)用程序可以在任何環(huán)境中部署和運(yùn)行,而不受底層基礎(chǔ)設(shè)施的限制。它還使自動(dòng)化部署過程變得更容易,這有助于提高一致性和可重復(fù)性。
雖然這是一個(gè)常見的做法,但經(jīng)常被忽視的一件事是構(gòu)建和發(fā)布步驟的分離。這種分離對(duì)于創(chuàng)建合理的部署和回滾過程非常重要。
當(dāng)代碼合并并進(jìn)行測試時(shí),生成的鏡像或二進(jìn)制文件應(yīng)存儲(chǔ)在可以在以后發(fā)布和部署中檢索的存儲(chǔ)庫/工廠中。這種分離可以實(shí)現(xiàn)更簡單、更少錯(cuò)誤的開發(fā)周期。
在較小規(guī)模或開發(fā)周期的早期,代碼和基礎(chǔ)設(shè)施的更改緊密耦合,可能不需要這種分離。但隨著應(yīng)用程序的增長和成熟,分離這些問題變得越來越重要。
以下是一些在應(yīng)用程序中實(shí)現(xiàn)第五因素的具體示例:
- 使用像Jenkins這樣的構(gòu)建工具自動(dòng)化構(gòu)建過程。這將有助于確保構(gòu)建過程是可重復(fù)的和一致的。
- 使用配置管理工具,如AWS的SSM或OCP的Config Map,來管理應(yīng)用程序的配置。這將有助于將配置與代碼分開。
- 使用像Docker這樣的容器化工具將應(yīng)用程序及其依賴項(xiàng)打包到容器中。這將有助于使您的應(yīng)用程序具有可移植性和可擴(kuò)展性。
- 最后,不要忘記將這些Docker鏡像存儲(chǔ)在工廠中。
6. 進(jìn)程
這個(gè)因素的重點(diǎn)是使您的應(yīng)用程序無狀態(tài),這意味著您的應(yīng)用程序不應(yīng)在內(nèi)存或磁盤上存儲(chǔ)任何數(shù)據(jù)。這使它們比有狀態(tài)進(jìn)程更可伸縮和容錯(cuò)。
可伸縮性是指應(yīng)用程序處理不斷增加的流量的能力。無狀態(tài)進(jìn)程可伸縮,因?yàn)樗鼈兛梢暂p松復(fù)制。當(dāng)流量增加時(shí),您只需添加更多的無狀態(tài)進(jìn)程來處理負(fù)載。
任何系統(tǒng)面臨的伸縮性問題數(shù)量都是管理和存儲(chǔ)狀態(tài)的問題。這對(duì)于以軟件即服務(wù)模式擴(kuò)展非常重要。這也與有界上下文的概念非常吻合,有界上下文確保每個(gè)系統(tǒng)都應(yīng)該管理其存儲(chǔ)層,如果其他系統(tǒng)需要訪問該數(shù)據(jù),應(yīng)該通過一個(gè)有良好文檔的API來訪問它。
容錯(cuò)性是指應(yīng)用程序在某些組件失敗時(shí)仍然能夠繼續(xù)運(yùn)行。無狀態(tài)進(jìn)程容錯(cuò),因?yàn)樗鼈儾灰蕾囉谌魏喂蚕頎顟B(tài)。如果一個(gè)無狀態(tài)進(jìn)程失敗,其他進(jìn)程可以繼續(xù)運(yùn)行而不中斷。
如果您還沒有注意到,這個(gè)因素是REST API的基礎(chǔ)。
0*gAMmnbTGJKBI_B9w.jpeg
7. 端口綁定
第七個(gè)因素主張使用明確定義的端口來導(dǎo)出服務(wù)。這使應(yīng)用程序之間的通信更容易,也使管理員更容易管理應(yīng)用程序。
這個(gè)因素已經(jīng)成為標(biāo)準(zhǔn)做法很長時(shí)間了,沒有什么特別的變化。此外,許多容器化標(biāo)準(zhǔn)、代理和負(fù)載均衡器已經(jīng)強(qiáng)制執(zhí)行了這個(gè)因素。
主要思想是每個(gè)應(yīng)用程序都應(yīng)該有一個(gè)特定的端口映射。
這意味著每個(gè)應(yīng)用程序都應(yīng)該在特定端口上監(jiān)聽傳入的請(qǐng)求。端口號(hào)可以用于傳達(dá)有關(guān)應(yīng)用程序的信息,例如它提供的服務(wù)類型。例如,Web服務(wù)器可能在端口80上監(jiān)聽請(qǐng)求,而SSH服務(wù)器可能在端口22上監(jiān)聽請(qǐng)求。
0*31lCtHojS36AKQMb.jpeg
8. 并發(fā)性
第八因素主張使用并發(fā)性來處理不斷增加的負(fù)載。在這個(gè)上下文中,并發(fā)性是指應(yīng)用程序能夠同時(shí)運(yùn)行多個(gè)實(shí)例。
無狀態(tài)應(yīng)用程序是實(shí)現(xiàn)最大可伸縮性的最佳類型的應(yīng)用程序。您可以輕松地將所有這些進(jìn)程分組到負(fù)載均衡器下。例如,在電子商務(wù)應(yīng)用程序中,所有訂單服務(wù)將分組到一個(gè)負(fù)載均衡器下,而產(chǎn)品服務(wù)將分組到另一個(gè)負(fù)載均衡器下。
0*-4_ZY8fJtpJp7zOp.jpeg
我確定您已經(jīng)注意到了每個(gè)因素中越來越多的冗余,這是因?yàn)橐粋€(gè)因素是前一個(gè)因素的擴(kuò)展或建立在其上。
9. 可丟棄性
要理解可丟棄性,想象一下能夠替換應(yīng)用程序中的故障部分而不必關(guān)閉整個(gè)應(yīng)用程序。這將使您能夠在發(fā)生問題時(shí)保持應(yīng)用程序的平穩(wěn)運(yùn)行??焖賳?dòng)和優(yōu)雅的關(guān)閉對(duì)于應(yīng)用程序的穩(wěn)健性至關(guān)重要。
這是一個(gè)重要的因素,通常在需要時(shí)被忽視。啟動(dòng)檢查對(duì)于確保系統(tǒng)正在運(yùn)行和正常運(yùn)行非常重要。健康檢查確保系統(tǒng)保持在這種狀態(tài)或從輪換中移除。
0*whae5tSZTQZrU54I.jpeg
我經(jīng)常看到關(guān)閉過程沒有受到同樣的關(guān)注。人們經(jīng)常說它是“相對(duì)復(fù)雜且難以正確執(zhí)行”的,或者“如果我們不干凈地執(zhí)行它,因?yàn)橄到y(tǒng)不會(huì)幸存,所以它無關(guān)緊要
”。這個(gè)說法是不正確的。第九因素的一個(gè)重要部分是確保關(guān)閉過程干凈且完全,以便應(yīng)用程序可以在必要時(shí)迅速啟動(dòng)和關(guān)閉。
10. 開發(fā)和生產(chǎn)的平等性
這個(gè)因素主張您的開發(fā)和生產(chǎn)環(huán)境應(yīng)該盡可能相似。這可以通過使用相同的工具、相同的配置和相同的設(shè)置來實(shí)現(xiàn)。
0*XLrJ4s8HrOi9i9uk.jpeg
通過保持這種相似性,您可以確保在開發(fā)、測試和生產(chǎn)環(huán)境之間更輕松地移動(dòng)應(yīng)用程序。這也有助于避免“在我的機(jī)器上可以工作”的問題,因?yàn)殚_發(fā)和生產(chǎn)環(huán)境之間的差異可能導(dǎo)致應(yīng)用程序在一個(gè)環(huán)境中運(yùn)行良好,但在另一個(gè)環(huán)境中失敗。
在實(shí)際實(shí)現(xiàn)中,開發(fā)和生產(chǎn)環(huán)境不會(huì)完全相同,因?yàn)樗鼈兊哪繕?biāo)和需求不同。但是,它們應(yīng)該盡可能相似,以確保平滑的部署和運(yùn)行。
11. 日志
在這個(gè)因素中,我們強(qiáng)調(diào)了記錄的重要性。應(yīng)用程序應(yīng)該生成詳細(xì)的日志,以便在發(fā)生問題時(shí)進(jìn)行故障排除和診斷。
日志記錄是一種關(guān)鍵的監(jiān)視和故障排除工具。通過查看日志,您可以了解應(yīng)用程序的狀態(tài)、性能和問題。在生產(chǎn)環(huán)境中,有一個(gè)可靠的日志記錄系統(tǒng)非常重要。
0*FXByK4kn-xHrzx_O.jpeg
以下是一些關(guān)于日志記錄的最佳實(shí)踐:
- 記錄足夠的信息: 確保您的日志包含足夠的信息,以便在發(fā)生問題時(shí)進(jìn)行故障排除。這可能包括錯(cuò)誤消息、異常堆棧跟蹤、請(qǐng)求/響應(yīng)數(shù)據(jù)等。
- 結(jié)構(gòu)化日志記錄: 將日志記錄為結(jié)構(gòu)化數(shù)據(jù),而不是純文本。這使得日志更容易分析和查詢。
- 中心化日志記錄: 使用中心化的日志記錄工具,如ELK堆棧(Elasticsearch、Logstash和Kibana)或Splunk,將所有應(yīng)用程序的日志記錄到一個(gè)位置。
- 周期性地清理日志: 避免日志文件過大,定期清理舊日志,或?qū)⑺鼈儦w檔到長期存儲(chǔ)中。
12. 管理進(jìn)程
最后一個(gè)因素強(qiáng)調(diào)了管理應(yīng)用程序進(jìn)程的重要性。這包括啟動(dòng)、停止和擴(kuò)展進(jìn)程。管理進(jìn)程是確保應(yīng)用程序穩(wěn)定運(yùn)行的關(guān)鍵部分。
0*OUbq8KmZ7504tKtc.jpeg
管理進(jìn)程通常需要一些自動(dòng)化工具,以確保它們可以輕松地啟動(dòng)和停止。這可能包括使用容器編排工具(如Kubernetes或Docker Swarm)來自動(dòng)化進(jìn)程的部署和擴(kuò)展。
確保您的應(yīng)用程序具有良好的管理進(jìn)程是非常重要的,因?yàn)樗梢詼p輕運(yùn)維工作的負(fù)擔(dān),確保應(yīng)用程序在需要時(shí)能夠擴(kuò)展以滿足負(fù)載。
總結(jié)
12-Factor應(yīng)用程序方法論提供了一組最佳實(shí)踐,可幫助開發(fā)人員構(gòu)建可擴(kuò)展、可維護(hù)和高效的應(yīng)用程序。這些因素涵蓋了應(yīng)用程序的各個(gè)方面,從代碼庫和依賴關(guān)系管理到配置、構(gòu)建、發(fā)布和運(yùn)行。
通過遵循這些原則,您可以創(chuàng)建更穩(wěn)健、更具可維護(hù)性和可擴(kuò)展性的應(yīng)用程序,同時(shí)提高了開發(fā)和運(yùn)維的效率。無論您是在開發(fā)單體應(yīng)用程序還是構(gòu)建云原生微服務(wù),這些因素都是非常有價(jià)值的。
希望這篇文章能夠幫助您更好地理解12-Factor應(yīng)用程序方法論,并在自己的項(xiàng)目中應(yīng)用這些最佳實(shí)踐。