我們公司最近正在開始為擁有大用戶群的客戶構(gòu)建應(yīng)用程序。這意味著我們需要摒棄傳統(tǒng)的服務(wù)器設(shè)置,開始擴(kuò)展服務(wù)器,以便一次性處理數(shù)百個(gè)請求。這要求我了解傳統(tǒng)服務(wù)器設(shè)置與目前更加現(xiàn)代的方法之間的區(qū)別。
向云進(jìn)發(fā)
回想 “舊” 時(shí)代(整整 20 年前),向操作中添加更多服務(wù)器空間涉及到讓某人安裝硬件,然后讓人們?yōu)槟S護(hù)該硬件。不僅購買和維護(hù)硬件需要成本,服務(wù)器上的物理空間也需要成本。考慮到每個(gè)服務(wù)器都僅擁有有限的空間,增長太快可能帶來問題。
如今,只需單擊幾次鼠標(biāo),就可以在云中獲得一個(gè)服務(wù)器:基本上講,其他人會負(fù)責(zé)為您維護(hù)硬件的問題,您可以在千里之外配置您的新硬件。您還可以添加許多的服務(wù)器,無需占用任何額外的空間。這使得擴(kuò)展變得比過去容易得多。
傳統(tǒng)設(shè)置
傳統(tǒng)設(shè)置包括一個(gè)托管您應(yīng)用程序的服務(wù)器和一個(gè)單獨(dú)的數(shù)據(jù)庫服務(wù)器。此設(shè)置通常非常適合小項(xiàng)目以及不需要擴(kuò)展的項(xiàng)目。有時(shí),過度優(yōu)化您的設(shè)置并沒有意義。我們公司以這種方式托管著許多項(xiàng)目。
“我們正在將一些較大的項(xiàng)目遷移到更現(xiàn)代的基礎(chǔ)架構(gòu),該基礎(chǔ)架構(gòu)會讓我們的應(yīng)用程序能夠優(yōu)雅地?cái)U(kuò)展。”
構(gòu)建可擴(kuò)展的基礎(chǔ)架構(gòu)
我們正在使用可擴(kuò)展的基礎(chǔ)架構(gòu)創(chuàng)建可擴(kuò)展的應(yīng)用程序。抱著成為更優(yōu)秀的開發(fā)場所的想法,我們決定遵循 Heroku 的 “12 因素(Twelve-Factor)應(yīng)用程序” 方法,該流程是專為構(gòu)建 SaaS(軟件即服務(wù))應(yīng)用程序而設(shè)計(jì)的。簡言之,該流程通過保持各部分分離,幫助您確保您的應(yīng)用程序容易擴(kuò)展。您應(yīng)能夠取出組合中的某一部分,無需擔(dān)心會毀壞所有部分。換句話說,您的資源不應(yīng)過度彼此依賴,以至于移動或更改一個(gè)組件會毀壞您的基礎(chǔ)架構(gòu)。
12 因素應(yīng)用程序方法很容易理解。不是我們的所有項(xiàng)目都符合該方法,但我們會努力讓項(xiàng)目盡可能符合該方法。談到擴(kuò)展,請?zhí)貏e注意有關(guān)可處置性的因素 9:通過快速啟動和優(yōu)雅的關(guān)閉實(shí)現(xiàn)最高的健壯性。
最佳實(shí)踐
您可以嘗試優(yōu)化所有部分,或者可高效地使用時(shí)間,努力實(shí)現(xiàn)容易實(shí)現(xiàn)的目標(biāo),讓您的應(yīng)用程序與該方法有 80% 相符。我們領(lǐng)先的基礎(chǔ)架構(gòu)工程師喜歡 80/20 方法:20% 的工作實(shí)現(xiàn) 80% 的目標(biāo)。這一節(jié)將介紹一些可幫助您接近想要實(shí)現(xiàn)的目標(biāo)的簡單方法。讓我們看看一些例子。
1. 設(shè)置負(fù)載平衡
場景 A:您的網(wǎng)頁登上了 Reddit 的頭版,您突然獲得了異常高的流量。您會怎么做?
這時(shí)有一個(gè)負(fù)載平衡器并 讓一些服務(wù)器保持運(yùn)行可能有所幫助??梢詫⒇?fù)載平衡器視為空中交通指揮員。它接受所有傳入的流量,并將其定向到可處理它的服務(wù)器。它也知道,如果一臺服務(wù)器宕機(jī),那么不應(yīng)朝該方向發(fā)送任何流量。也可以將負(fù)載平衡器視為一個(gè)黑匣子:您不需要擔(dān)憂負(fù)載平衡如何 完成,只需放心地相信它將 會完成。新傳入的流量不會到達(dá)宕機(jī)的服務(wù)器,因?yàn)樨?fù)載平衡器會將新流量定向到可以處理它的服務(wù)器。
場景 B:一次自然災(zāi)難襲擊了整個(gè)東海岸。您的應(yīng)用程序?qū)绾畏磻?yīng)?
如果即將出現(xiàn)這種情況,那么應(yīng)該一切正常,因?yàn)槟鷷诓煌目捎眯詤^(qū)域運(yùn)行服務(wù)器,對吧?您的負(fù)載平衡器會知道您在東海岸的所有服務(wù)器都已單擊,然后它會開始將流量發(fā)送到西海岸的服務(wù)器。
2. 保持不同的環(huán)境看起來一樣
我們公司有 4 個(gè)不同的環(huán)境:本地、開發(fā)、暫存和生產(chǎn)。我們嘗試保持它們彼此盡可能相似。這可以預(yù)防在各個(gè)階段發(fā)生任何可能歸咎于環(huán)境變量的問題。例如,您一定不要依靠在生產(chǎn)環(huán)境中無法訪問的開發(fā)環(huán)境中的任何資源。
3. 使用無狀態(tài)服務(wù)器
作為一條規(guī)則,不要將您需要訪問的信息存儲在 Web 應(yīng)用程序的服務(wù)器中。服務(wù)器的每個(gè)副本看起來都應(yīng)該是相同的,而且您不需要將信息從一個(gè)服務(wù)器復(fù)制到下一個(gè)服務(wù)器。理想情況下,您已經(jīng)創(chuàng)建了應(yīng)用程序的服務(wù)器鏡像,能夠使用該鏡像建立其他許多服務(wù)器。讓您的數(shù)據(jù)庫與應(yīng)用服務(wù)器分開。
4. 經(jīng)常停止您的服務(wù)器
應(yīng)急訓(xùn)練有時(shí)看起來可能很傻,但熟能生巧。至關(guān)重要的是,每個(gè)人都應(yīng)該知道在發(fā)生緊急情況時(shí)如何應(yīng)對,實(shí)際練習(xí)過實(shí)際發(fā)生緊急情況時(shí)如何做。發(fā)生火災(zāi)時(shí),人們可能知道他們應(yīng)該前往緊急出口,但您不希望他們在實(shí)際發(fā)生火災(zāi)時(shí)忘記緊急出口是什么樣的。
服務(wù)器問題也是如此。您可能認(rèn)為您已做好應(yīng)對最糟的情況的準(zhǔn)備,但除非您知道在服務(wù)器宕機(jī)時(shí)系統(tǒng)將如何應(yīng)對,否則您就沒有做好應(yīng)對不是您導(dǎo)致的服務(wù)器宕機(jī)情況的準(zhǔn)備。這正是使用無狀態(tài)服務(wù)器至關(guān)重要的原因。不要過度依賴您的服務(wù)器 —經(jīng)常關(guān)閉它們。您應(yīng)能夠停止并恢復(fù)服務(wù)器,而不害怕您將毀壞什么東西。
您希望能夠確信,一些服務(wù)器在晚上發(fā)生宕機(jī)時(shí),系統(tǒng)將在您能夠在早上解決問題之前正常運(yùn)行。
5. 集中精力解決瓶頸
瓶頸需要您確定是什么實(shí)際導(dǎo)致您的應(yīng)用程序變慢。您不想盲目地追查可能不是實(shí)際問題的因素;查找最大的瓶頸并花時(shí)間嘗試修復(fù)這些問題。
我們公司使用了 Django,所以我們喜歡使用 Django Debug Toolbar 來確定是什么實(shí)際減緩了我們的運(yùn)行速度。運(yùn)行減慢可能是由不必要地頻繁查詢數(shù)據(jù)庫等操作導(dǎo)致的。消除瓶頸,可能對確保您的應(yīng)用程序更高效地執(zhí)行有很大幫助。
6. 運(yùn)行后臺任務(wù)
如果您可將一些任務(wù)推遲到以后,可考慮使用后臺任務(wù)。例如,您可能需要執(zhí)行一次很耗資源的 API 調(diào)用,所以您不需要立即向用戶返回信息。我們使用 Celery Task Queue 來管理我們可推遲到以后執(zhí)行的任務(wù)。有時(shí)我們不需要用戶獲得即時(shí)反饋,所以只要可能,我們就會將該任務(wù)延后到我們能對它給予應(yīng)得的關(guān)注時(shí)運(yùn)行。
7. 盡可能緩存
如果您有一個(gè)提供大量靜態(tài)內(nèi)容的網(wǎng)站,緩存無疑會加快您網(wǎng)站的反應(yīng)速度。反復(fù)訪問您的網(wǎng)站的用戶只需加載新的內(nèi)容。如果自他們上次訪問您的網(wǎng)站以來,內(nèi)容沒有多大改變,那么加載將會很快。
可以采用多種緩存方式:瀏覽器緩存和使用內(nèi)容分發(fā)網(wǎng)絡(luò) (CDN),后者能提供具有高可用性和高性能的內(nèi)容。您可以設(shè)置資源的有效期,所以一個(gè)不錯的想法是在不常更改的資源上設(shè)置較長的有效期,頻繁更改的資源則相反。例如,徽標(biāo)圖像可能很少發(fā)生更改,而您的 HTML 網(wǎng)頁則會非常頻繁地更改。基本上講,緩存有助于提高性能,且無需更改您的硬件。
8. 設(shè)置自動擴(kuò)展
您現(xiàn)在只需單擊一個(gè)按鈕即可建立新的服務(wù)器。由于擁有如此輕松地建立和銷毀服務(wù)器的能力,所以您可以確保您始終擁有足夠的服務(wù)器來處理您嘗試處理的流量。您甚至可以將服務(wù)器設(shè)置為在高流量期間運(yùn)行,在低流量期間消失。如果知道用戶模式,您可以在任何時(shí)候增加和減少服務(wù)器數(shù)量。
9. 讓整個(gè)團(tuán)隊(duì)都參與進(jìn)來
團(tuán)隊(duì)的每個(gè)人都可以從某種程度上幫助提高性能和擴(kuò)展。每個(gè)人都可以出一份力,幫助確保團(tuán)隊(duì)更輕松地實(shí)施保護(hù)措施,確保您的應(yīng)用程序能夠處理峰值流量或一直很高的流量。
確保團(tuán)隊(duì)的每個(gè)人詢問正確的問題。例如,某些特性是真的需要還是錦上添花?
10. 花時(shí)間執(zhí)行測試
一定要在建立的時(shí)間表中給基礎(chǔ)架構(gòu)測試留出時(shí)間。不是所有功能從一開始就能順利運(yùn)行。您需要對應(yīng)用程序執(zhí)行壓力測試,需要在生產(chǎn)環(huán)境中檢查您的應(yīng)用程序。如果時(shí)間表中沒有安排對應(yīng)用程序進(jìn)行擴(kuò)展測試的時(shí)間,那么您可能會發(fā)現(xiàn)需要延誤工作才能修復(fù)的重大問題。
11. 考慮容器
我們公司正計(jì)劃采用一種更現(xiàn)代的 Web 應(yīng)用程序處理方法。在理想情況下,我們希望將基礎(chǔ)架構(gòu)更換為使用容器。
在聽到容器時(shí),我腦海里想到的第一件事是,容器與虛擬機(jī)之間有何區(qū)別。對我而言,它們聽起來很相似。事實(shí)證明,容器能比虛擬機(jī)更好地保持了應(yīng)用程序的可擴(kuò)展性。它們類似于虛擬機(jī),但它們沒有大量的重復(fù)硬件。我們現(xiàn)在可以運(yùn)行單個(gè) Linux 實(shí)例,在其上建立容器,讓所有容器都共享同一個(gè)操作系統(tǒng)。所以容器似乎是更加輕量的、具有更高成本效益的應(yīng)用程序擴(kuò)展解決方案。
結(jié)束語
盡管這些實(shí)踐可能無法預(yù)防所有問題,但它們會幫助您在開始構(gòu)建應(yīng)用程序時(shí)考慮到擴(kuò)展功能,讓您為需要處理數(shù)千萬個(gè)用戶的時(shí)刻打好基礎(chǔ)。
要確保您正在朝建立高度可擴(kuò)展的應(yīng)用程序基礎(chǔ)架構(gòu)的方向而努力,您應(yīng)該采取以下行動:
使用一個(gè)負(fù)載平衡器。
使用自動擴(kuò)展功能。
不要害怕隨機(jī)停止您的服務(wù)器。
修復(fù)需要修復(fù)的問題,而不是修復(fù)您認(rèn)為應(yīng)該修復(fù)的問題。
確保您擁有測試應(yīng)用程序和修復(fù)任何問題所需的時(shí)間。