通俗易懂的生產環境Web應用架構介紹

weixin_34377065發表於2019-02-26

前言

看見一篇非常通俗易懂且適合新手閱讀的Web應用架構文章,我將其手工翻譯了出來,分享給大家。

也可以去閱讀英文原文,標題為,貼出連結:

stephenmann.io/post/whats-…

英文標題為:

What's in a Production Web Application?

正文

在我職業生涯的早期,我曾在一家工作內容為構建Web內容管理系統的公司工作。他們的產品幫助營銷部門可以自己管理網站的內容,而不是依靠開發人員來管理網站。該產品幫助他們的客戶降低了運營成本,並幫助我學習如何構建Web應用程式。

雖然產品本身有一個非常普通的用途,但其客戶缺傾向於使用它來解決非常特殊的問題。這些問題以各種眼花繚亂的方式將對產品的要求推到了極限,並且要求該產品必須提供解決方案。在這種環境中工作了十多年,讓我對生產環境下的Web應用程式有了全面的瞭解,其中一些我們將在本文中討論。

這些年我學到的經驗之一是,對於開發Web應用程式,個別工程師傾向於非常深入地瞭解他們感興趣的東西,對於不感興趣但必要的元件缺只學習皮毛,這其實是非常“危險”。這對於具有良好溝通的工程師團隊來說非常有效,因為這些組合知識將重疊以填補任何個人的侷限。然而,這對於獨立工程師或者在這方面經驗不足的團隊,就顯得“危險”。

如果你是在這樣的環境中開始,然後開始從頭開始構建和部署整個Web應用程式,你可能很快就會理解我說的“危險”的意思。

業界已經提供了許多旨在解決這個問題的解決方案:託管Web應用程式(Beanstalk,AppEngine等),託管容器管理(Kubernetes,ECS等等)以及許多其他解決方案。一旦你啟動並執行它們,它們就可以正常工作,我認為它們在解決問題方面做得很好。它們隱藏了啟動和執行Web應用程式所需的大量複雜性,並且它們傾向於“剛好能工作”。

不幸的是,當它不是“剛好能工作”,或者當你需要完成一些特殊的業務時,你可能會發現自己會希望更多地瞭解那個不祥的黑盒子。

在這篇文章中,我將採用一個不可靠的系統,並將其演變為具有合理可靠性的系統。沿途的每一步都將使用現實中會遇到的問題作為進入下一步的目的。我沒有討論一個最終設計的每一部分,而是使用這種增量方法有助於讀者瞭解自己的需求,以及自己目前處於哪一步。我們將從頭開始構建託管Web應用程式託管服務所提供的基本結構,並希望能夠詳細介紹每個部分存在的意義。

讓我們開始

讓我們假設你有一年500美元的託管預算,因此你決定從Amazon AWS租用一臺t2.medium伺服器。 在撰寫本文時,每年僅花費約400美元。

你事先知道你需要設計登入系統,並且你需要儲存使用者資訊,因此你需要一個資料庫。 由於預算有限,讓我們在我們唯一的伺服器上託管它。 最終得到的結構如下:

在這裡插入圖片描述

看起來足夠了,哈哈。 事實上,它可能會穩定工作很長一段時間。因為你網站的體量還很小。 此時,你可能每天最多隻能處理10次訪問。 一個小例項可能已經足夠了,但由於你對公司的發展持樂觀態度,因此你使用t2.medium例項做出了不錯的選擇。

你的業務價值儲存在該資料庫中,因此非常重要。你應該確保就算該伺服器發生故障,不會導致你的資料丟失。所以最好去確保下你沒有將資料庫內容儲存在臨時磁碟上,不然的話,如果例項被刪除,你將丟失所有資料。這會非常可怕。

此外,你還應確保將備份轉到外部儲存。AWS S3似乎是一個放置這些的好地方,它相對便宜,所以讓我們設定它。而且你肯定應該通過每隔一段時間做一次資料備份來測試它是否正常工作。

你的結構現在應該如下所示:

在這裡插入圖片描述

在這時,你已經提高了資料庫的可靠性,接下來,你想通過對伺服器執行負載測試來為可能到來的大規模的黑客新聞流量(譯者注:原文為Hacker News,一個資訊源資訊網站)峰值做好準備。一切似乎進展順利,直到500錯誤開始出現,然後是404流,所以你要調查弄清楚發生了什麼。

事實證明,你沒有任何線索來得知網站崩潰到底是因為什麼原因,因為你把日誌寫到控制檯,而沒有將控制檯輸出傳遞到日誌檔案中。你還看到該程式未執行,因此你預設了這就是你獲得404的原因。你臉上的緊張情緒稍稍緩解了點,並且慶幸還好自己沒有直接將你的網站登記到Hacker News上。

你建立了一個執行Web伺服器的systemd服務來保證你的服務會在崩潰後自動重啟。此外,你最終解決了日誌記錄問題。然後你執行另一個負載測試,以確保你已經解決了所有問題。

你又看見了500錯誤(幸好沒有404),你檢查日誌以檢視出錯的地方。你發現資料庫連線池已經飽和,該連線池設定為10。你更新了引數,重新啟動資料庫,然後再次執行負載測試。一切順利,所以你決定在Hacker News上推廣你的網站。

釋出日

臥槽!!!(譯者注:Great Scott!!!諺語)你的服務大受歡迎。你進入了Hacker News的頭條。你在30分鐘內獲得5,000次點選,你看到評論湧入了進來。來看看他們怎麼說?

我得到了404,所以我必須檢查頁面的存檔版本。如果有人需要,這是連結:...

媽的空白頁啊!我禁用了Javascript,為什麼網站作者會覺得我會取讀取你的2 MB Javascript檔案 ...

你的主頁需要4秒鐘才能載入。我居住在澳大利亞,Traceroute顯示伺服器託管在德克薩斯州的某個地方。另外,為什麼你的網頁需要2 MB的Javascript?

在混亂中,你被迫在伺服器上設定了Nginx作為應用程式的反向代理,並將其配置為伺服器靜態404頁面。 還將靜態檔案推送到AWS S3,這樣做是為了讓CloudFront CDN能夠起作用,來減少澳大利亞使用者的訪問時間。

在這裡插入圖片描述

這時候你已經解決了當前的問題,這之後,你可以隨時訪問伺服器並檢視日誌。 但你慢慢發現,你的SSH連線非常遲鈍。經過檢查,你發現你的日誌檔案已經完全耗盡了你的磁碟空間,這會使你的程式崩潰並阻止它再次啟動。你建立一個更大的磁碟並在其上掛載日誌。 你還設定了滾動日誌來防止日誌檔案再次變得非常巨大。

效能問題

幾個月過去了。你的使用者群在慢慢增長。你的網站開始變慢。你在CloudWatch監控中注意到,這似乎只發生在中午和晚上。由於變慢的開始和結束時間每天都相同,你猜測這是由於伺服器上的計劃任務造成的。你檢查了你的crontab,看見了你自己在午夜安排了一份工作:備份資料庫。果然,你的備份需要12個小時,並且備份程式使資料庫過載了,導致了網站訪問極慢。

發現了這個問題後,你決定新建一個從資料庫,並在從資料庫上執行備份。 所以你建立了一個從資料庫。在同一臺伺服器上執行從資料庫沒有多大意義,你決定,是時候擴充套件了!你建立兩個新伺服器:一個用於master資料庫,另一個用於slave資料庫。 你將備份更改為在從屬資料庫中定時執行。

在這裡插入圖片描述

組建團隊

一切都執行平穩了一段時間,幾個月過去了,你聘請了一個更大的開發團隊,其中一位新開發人員發現了一個bug,這個bug會導致生產伺服器的崩潰。此位程式設計師覺得是由於開發環境與生產不同導致的。他說的話有些道理,你聽起來覺得很對,所以你決定把這個問題解決。

你構建了更多不同的環境:Staging,QA和生產環境。幸運的是,你從寫這個專案第一天開始就搭建了自動基礎架構,因此環境的增加很容易。並且從第一天起,你就使用了良好的持續交付機制,因此你可以輕鬆地從管道構建新分支。

在這之後,營銷部門希望推出v2.0版本。你不確定v2.0版本是什麼,但無論如何你還是決定做了。是時候準備另一次流量的飆升了。在Web伺服器上執行的服務已經接近伺服器的峰值利用率,因此你決定開始對流量進行負載平衡。亞馬遜ELB能夠讓你輕鬆上手。在這個時候,你還發現部落格文章中的分層圖表應該從上到下而不是從左到右顯示圖層。:)

在這裡插入圖片描述

你再次將你的網站釋出到Hacker News。 它撐住了巨大的流量,取得了極大的成功!

這一切似乎都很棒,直到有一天,你去檢查了你的日誌。 這時你才發現,檢查一次日誌,需要一個小時,因為要檢查12臺伺服器(每個環境中有4臺伺服器),這顯得很麻煩。幸運的是,你的公司現在已經賺了足夠的錢來實現ELK堆疊(ElasticSearch,LogStash,Kibana),你構建了一個ELK環境並將它用在了所有環境中。

在這裡插入圖片描述

這樣一來,你可以輕鬆地檢視日誌了,你發現,有很多奇怪的東西混在了日誌裡。

GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
複製程式碼

你根本沒執行過任何PHP有關的服務,這非常令人擔憂。 你注意到資料庫伺服器上也有類似的可疑日誌,現在你很想問自己為什麼將它們的埠暴露在了外網上,是時候區分公共和私人子網了。

在這裡插入圖片描述

OK,你又開始檢查你的日誌。黑客還是可以攻擊你,但現在它們僅限於負載均衡器上的埠80,因為你的應用程式伺服器,資料庫伺服器和ELK堆疊不再暴露在網際網路上,這下你舒坦了。

儘管進行了集中式日誌記錄,但你還是不得不通過手動檢查日誌來發現中斷。 你可以使用Amazon CloudWatch設定磁碟,CPU和網路警報,以便在達到80%容量時向你傳送電子郵件。還能說什麼,簡直完美。

一帆風順

開玩笑!沒有一帆風順的事情,總有事情會出錯。幸運的是,你有很多工具可以更輕鬆地處理這些問題。

我們構建了一個可擴充套件的Web應用程式,包括備份,回滾,集中式日誌記錄,監控和警報。這是一個很好的總結時刻,因為這裡的增長往往取決於特定應用的需求。

業界提供了許多託管選項,可以為你處理大部分內容。你可以依靠Beanstalk,AppEngine,GKE,ECS等,而不是自己構建所有這些服務。大多數這些服務都會自動設定合理的許可權,負載均衡器,子網等。他們需要花費很多麻煩才能使應用程式快速啟動並執行,這樣可以確保你的站點長時間執行所需的可靠性。

無論如何,我認為了解這些平臺提供的功能以及提供它們的原因是有用的。它可以根據你自己的需求更輕鬆地選擇平臺。一旦你在平臺上執行了所有東西,你就已經弄清楚了這個工具的這些重要方面是如何工作的。當出現問題時,有助於瞭解你擁有解決問題的必要工具。

總結

這篇文章跳過了很多細節問題。它不包括如何自動建立基礎結構,如何配置伺服器或如何配置伺服器。它不包括如何建立開發環境,如何設定連續交付管道,或如何執行部署或回滾。它不包括網路安全,祕密共享或最小特權原則。它不包括不可變基礎架構或無狀態伺服器或遷移的重要性。這些主題中的每一個都需要自己的帖子。

本文的目的主要是提供一個合理的生產Web應用程式應該是什麼樣子的高階概述。 未來的帖子可以參考這個並擴充套件它。

感謝你的閱讀!

編者注:編輯:不要使用文章中出現過的具體數值作為你服務的引數設定。

相關文章