一個合理的生產環境的 Web 應用程序應該是什麼樣子的

好的工具的產生使開發與部署變得十分容易,做爲一個曾經的雲服務從業人員,鼓勵你們擁抱雲服務。擁抱這些現成的技術棧。php

這是我在 stephenmann.io 上看到的一篇文章,對於 Web 應用程序架構演進的過程講解的十分通俗易懂,因此就把它翻譯了出來。數據庫

一個合理的生產環境的 Web 應用程序應該是什麼樣子的

原載:stephenmann.io緩存

譯者:展小白安全

一個產品的規劃可能會是迎合最廣泛的需求,可是不少狀況客戶但願解決具體的問題,這些問題可能將程序變得無限複雜,就必須提出有效的解決方案。服務器

在過去的經驗教訓中,一些工程師傾向於深刻了解各項技術,足以解決任何問題。對於有着良好溝通的團隊,這是很是好的。這些綜合的知識有效的填補了團隊我的的薄弱點。但對於行業或者經驗不足的工程師團隊,這些幾乎是不可能的。網絡

若是你是在一個薄弱的技術團隊,而後從頭開始構建和部署整個 Web 應用程序,你可能很快意識到要深刻了解每項技術,是很難的一件事情。架構

業界其實已經提供了不少旨在解決這些問題的方案:Web 託管服務(Beanstalk,AppEngine 等),容器管理服務(Kubernetes, ECS 等)以及其它不少解決方案。一旦你啓動並運行它們,即可以很好的正常進行工做,這種解決方案很是好,由於它規避了啓動和運行 Web 程序過程當中大量複雜的操做,並且最終目的是爲了使程序正常工做。負載均衡

這裏可能須要下功夫的是,在你決定用哪一種方案時,你須要更多的瞭解這些解決方案。工具

在這篇文章中,將介紹一個不靠譜的系統到具備合理可靠性的系統的過程。這裏不會介紹每一部分的具體細節,而是經過演進的過程,讓你擁有在什麼時候應該採用哪些決策的良好背景。性能

入門

最基本的你須要購買一臺服務器,好比能夠從亞馬遜購買中配的服務器。

你知道你的程序須要用戶登陸,你須要存儲用戶信息。所以你須要一個數據庫。因爲預算有限,直接在你的服務器上進行建立。最終獲得的架構以下:

這應該足夠了,事實上,使用這個架構,能夠保障你的程序運行很長時間而沒有瓶頸。此時,你可能天天只須要處理 10 次訪問請求。其實一個最低配的服務器已經足夠了,可是你的公司可能對業務持增加態度,因此選擇了中配的服務器。

如今,你將有價值的業務數據存儲在實例中的數據庫中,若是服務器發生故障,或者實例被刪除,極可能致使數據丟失,這是很可怕的。你應該確保數據備份到外部存儲。好比:S3 服務。因此讓咱們設置它。你應該經過每隔一段時間恢復一次備份的方式來確保它正常運行。

你的架構應該以下所示:

你已經提升了數據庫的可靠性,那麼你決定經過對服務器進行負載測試來檢驗是否能夠應對大規模的流量訪問。一切彷佛進展順利,直到 500 錯誤出現,繼而是 404,因此你要排查是什麼緣由形成的。

但實際上,你並不知道是什麼緣由致使的,由於你把日誌寫到了控制檯,並無寫入到日誌文件中。你看到該進程並無運行,所以你假設是這個緣由致使了 404。

你能夠經過建立 systemd 運行 Web 服務器服務來解決自動啓動的問題,並解決你的日誌記錄問題。而後再進行新一輪的負載測試,以確保解決了全部的問題。

再一次,你看到了 500 錯誤,慶幸的是沒有 404,你檢查日誌看是哪裏出錯了。你發現數據庫的鏈接池已經飽和,該鏈接池設置了 10 個鏈接的限制。你更新了限制,重啓數據庫,而後再次運行負載測試。一切順利。因此你決定對你的網站進行推廣。

發佈日

哇!你的服務很受歡迎,在 30 分鐘內就得到了 5000 次的點擊,你看到有評論進來。他們怎麼說?

我訪問 404 了,因而我檢查我存儲的地址是否正確,居然換地址了,若是有人須要,這是新的連接:……

……

什麼也沒有顯示,也許是由於我禁用了 JavaScript,可是,誰會須要 2MB 那麼大的 JS 文件 ……

……

大家的主頁須要 4s 才能加載,並且訪問到的是離我很遠的一個地區的地址,另外,爲何要加載 2MB 的 JS 文件?

因而你拼命的進行了優化,你在服務器經過 Nginx 設置了跳轉你應用程序的反向代理,你將靜態文件進行了剝離,上傳到了 S3,這是頗有效的,你能夠經過 CDN 幫助加速你網站在不一樣地區的訪問。

如今,你已經解決了當前的問題,那麼你能夠經過訪問服務器查看日誌。你發現 SSH 鏈接很是慢,通過一番檢查,你發現你的日誌文件已經耗盡了你的磁盤空間,這會使你的進程崩潰並阻止它再次啓動。你建立更大的磁盤存儲日誌,而且設置 logrotate 防止日誌文件再次變得如此巨大。

性能問題

幾個月過去了,你的用戶數持續增加,你的網站開始變得很慢。你在監控中注意到,這種狀況彷佛只發生在午夜到中午之間。因爲變慢開始和結束的時間比較固定,你猜想應該是服務器上的定時任務形成的。你檢查 crontab 意識到你在午夜安排了備份任務。果真,你的備份過程須要持續 12 個小時,而且致使數據庫超載,致使了站點訪問明顯拖慢。

你以爲應該在從庫進行數據庫的備份,可是你記得,你並無建立從庫,因此你須要建立一個。在同一臺服務器運行從庫沒有太大的意義,所以,你決定對服務器進行擴展,建立了兩個新的服務器:一個用於 master 數據庫,另外一個用於 slave 數據庫。你將備份改成依據從庫運行。

發展團隊

一切都很平穩,運行了一段時間。幾個月過去了。你擴充了開發團隊,其中一位新的開發人員爲了檢查一個錯誤,致使了生產服務器的故障。客戶把錯誤歸咎到了你沒有對生產測試環境進行區分。你以爲說的有道理,你是個虛心學習而且有追求的人,你把此次故障看作是一次學習的機會。

如今是到了構建規範的開發部署流程的時候了:分期開發,測試,而後部署。幸運的是,一開始你創建了良好的基礎架構,所以這變得很容易。由於你從第一天起,就良好的踐行了持續交付,你能夠輕鬆的在一個新的分支進行構建。

業務部門但願推出 2.0 版本,但並無具體的業務需求,可是你仍是去作了。你以爲是時候進行一次性能的改造。你的 Web 服務器的運行如今已經接近峯值的利用率,所以你決定對流量進行負載均衡。而亞馬遜 ELB 使你很容易上手。與此同時你以爲你的架構圖應該是這樣的:

另外還能夠經過 Redis 等作一些緩存策略。相信你的優化可以承擔更大的負載,因此你再次對你的網站進行了大力推廣,不出所料,流量飆升,但運行很穩定。

一切看起來都那麼好,直到你須要去檢查日誌。這花費了你一個小時,由於要檢查 12 臺服務器(每一個環境有 4 臺服務器)。那是一件麻煩事,幸運的是,你如今已經賺了足夠的錢能夠實現 ELK 堆棧(ElasticSearch,LogStash,Kibana)。新的架構圖:

如今,你能夠再次閱讀你的日誌了,你發現了一些奇怪的狀況。裏面充滿了:

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 或 WordPress,因此很使人擔心。你在數據庫服務器上注意到相似的可疑日誌,你想怎麼把他們暴露在公網上了。因此是時候進行公網和本地訪問的隔離了。

再次,你檢查了日誌,雖然仍然可能被黑客攻擊,可是僅限於負載均衡服務器上的 80 端口,而你的應用服務器,數據服務器和 ELK 堆棧再也不暴露在公網上。你能夠輕鬆許多了。

雖然對日誌進行了集中式的記錄管理,可是還不得不手動檢查日誌。這時候使用服務器提供商的監控,設置磁盤、CPU 和 網絡報警,以便在達到 80% 的使用率時經過郵件等途徑通知你,是個不錯的選擇。

一路順風

開玩笑,沒有哪一個程序的運行是一路順風的,總有事情會發生,幸運的是,你有不少工具能夠處理這些問題。

如今,咱們已經構建了一個可擴展的 Web 應用程序,包括備份,回滾,集中式日誌記錄管理,監控和警報。能夠告一段落了,由於下面的改變每每取決於特定應用的需求。

業界提供了許多託管選項,能夠爲你處理大部份內容。你能夠依靠 Beanstalk,AppEngine,GKE,ECS 等而不是本身構建全部這些服務。大多數這些服務都會自動設置合理的權限,負載均衡,子網等。能夠確保你的站點能夠長時間運行。

瞭解這些平臺提供的功能以及何時使用它們是很是有用的,這樣,你能夠根據你的須要輕鬆選擇平臺。一旦你在相關平臺上運行了你的程序,你應該瞭解這些工具的工做原理,這是很重要的,有助於在遇到問題時,快速解決問題。

結尾

這篇文章省略了不少細節,不包括如何自動建立基礎架構,如何配置服務器。不包括任何開發環境的建立,如何實踐持續交付,如何執行部署和回滾。不包括網絡安全,私密共享或最小權限原則。它不涵蓋不可變基礎架構,無狀態服務以及遷移的重要性。其實每一個主題均可以獨立開闢一篇文章。

本文的主要目的是提供一個合理的生產環境的 Web 應用程序應該是什麼樣子的。

感謝你的閱讀!


關注公衆號「展白說」,獲取更多有價值的信息。

相關文章
相關標籤/搜索