擴展您的 Web 應用程序:基本步驟
已發表: 2022-09-13為您的業務創建應用程序是不夠的,您需要優化它們。 一個有效的方法是規模化。 在本文中,您將了解代碼優化、架構優化以及如何構建可擴展的 Web 應用程序。
優化
Gearheart 建議問自己以下問題:
- 數據庫查詢是否最優(解釋分析、索引的使用)?
- 數據存儲是否正確(SQL 與 NoSQL)?
- 是否使用緩存?
- 對 FS 或數據庫沒有不必要的請求?
- 數據處理算法是最優的嗎?
- 環境設置是否最佳:Apache/Nginx、MySQL/PostgreSQL、PHP/Python?
這些問題中的每一個都可以在單獨的文章中討論,因此在本文的框架內詳細考慮它們顯然是多餘的。 重要的是要了解,在開始擴展應用程序之前,非常希望盡可能優化其工作 - 事實上,有可能根本不需要擴展。
縮放
假設您已經優化了您的應用程序,但它仍然無法處理負載。 在這種情況下,顯而易見的解決方案是將應用程序分佈在多個主機上,以便通過增加可用資源來提高應用程序的整體性能。 這種方法被正式稱為“縮放”應用程序。 更準確地說,可伸縮性是系統通過增加可用資源量來提高其性能的能力。
有兩種類型的可擴展性:垂直和水平。 垂直可擴展性意味著通過在一個節點(主機)中添加資源(CPU、內存、磁盤)來提高應用程序性能。 水平擴展是分佈式應用程序的典型特徵,意味著通過添加另一個節點來提高應用程序性能。
很明顯,最簡單的方法是簡單的硬件升級(處理器、內存、磁盤)——即垂直擴展。 此外,這種方法不需要對應用程序進行任何修改。 然而,垂直縮放很快達到了極限,之後開發人員和管理員別無選擇,只能切換到應用程序的水平縮放。
應用架構
大多數 Web 應用程序都是先驗分佈式的,因為它們的架構至少可以分為三層:Web 服務器、業務邏輯(應用程序)、數據(數據庫、靜態)。
這些層中的每一層都可以縮放。 因此,如果您的系統有一個應用程序和一個數據庫駐留在同一主機上,那麼第一步絕對應該將它們分開在不同的主機上。
瓶頸
在進行系統擴展時,首先要做的是確定哪一層是“瓶頸”,即比系統的其餘部分慢。 首先,您可以使用諸如 top (htop) 之類的普通實用程序來評估 CPU/內存消耗,並使用 df、iostat 來評估磁盤消耗。 但是,最好為單獨的主機提供戰鬥負載仿真(使用 AB 或 JMeter),您可以在其上使用 xdebug、oprofile 等實用程序分析應用程序。 您可以使用 pgFouine 之類的實用程序來識別狹窄的數據庫查詢(當然,最好根據來自戰鬥服務器的日誌來執行此操作)。
通常它取決於應用程序的體系結構,但通常最有可能成為瓶頸的候選者是數據庫和代碼。 如果您的應用程序處理大量用戶數據,則瓶頸很可能是靜態存儲。
數據庫擴展
如上所述,現代應用程序的瓶頸通常是數據庫。 它的問題通常分為兩類:性能和需要存儲大量數據。
您可以通過將數據庫劃分為多個主機來減少數據庫的負載。 它們之間存在同步的嚴重困難,可以通過實現同步或異步複製的主/從方案來解決。 對於 PostgreSQL,您可以使用 Slony-I 進行同步複製,使用 PgPool-II 或 WAL (9.0) 進行異步複製。 為了解決讀寫請求拆分的問題,以及平衡slave之間的負載,可以配置一個特殊的數據庫訪問層(PgPool-II)。
在關係數據庫的情況下存儲大量數據的問題可以通過分區(PostgreSQL 中的“分區”)或通過將數據庫部署在分佈式數據庫(如 Hadoop DFS)上來解決。
您可以在關於配置 PostgreSQL 的優秀書籍中閱讀這兩種解決方案。
1.但是,對於存儲大量數據,最好的解決方案是分片,這是大多數NoSQL數據庫(例如MongoDB)的固有優勢。
2.此外,由於缺乏解析/優化查詢、檢查數據結構完整性等方面的開銷,NoSQL 數據庫通常比它們的 SQL 兄弟運行得更快。比較關係數據庫和 NoSQL 數據庫的主題也相當廣泛,值得單獨的文章。
3.另外值得注意的是Facebook的經驗,它使用MySQL沒有JOIN選擇。 這種策略允許他們更輕鬆地擴展數據庫,同時將負載從數據庫轉移到代碼,如下所述,代碼比數據庫更容易擴展。
代碼縮放
- 擴展代碼的複雜性取決於您的主機需要多少共享資源來運行您的應用程序。 它只是會話,還是需要共享緩存和文件? 無論哪種方式,首先要做的是在具有相同環境的多個主機上運行應用程序的副本。
- 接下來,您需要在這些主機之間設置負載/請求平衡。 您可以在 TCP (HAProxy)、HTTP (nginx) 或 DNS 上執行此操作。
- Gearheart 提到,下一步是使靜態文件、緩存和 Web 應用程序會話在每個主機上都可用。 對於會話,您可以使用通過網絡工作的服務器(例如,Memcached)。 作為緩存服務器,當然可以在不同的主機上使用相同的 Memcached。
- 靜態文件可以通過 NFS/CIFS 或使用分佈式 FS(HDFS、GlusterFS、Ceph)從一些共享文件存儲中掛載。
還可以將文件存儲在數據庫中(例如,Mongo GridFS),從而解決可用性和可伸縮性問題(考慮到 NoSQL 數據庫的可伸縮性問題是通過分片解決的)。
另外值得注意的是,部署到多個主機的問題。 如何確保用戶通過單擊“更新”不會看到不同版本的應用程序? 在我看來,最簡單的解決方案是從配置負載均衡器(網絡服務器)中排除未更新的主機,並在進行更新時按順序打開它們。 您還可以通過 cookie 或 IP 將用戶綁定到特定主機。 如果更新需要對數據庫進行重大更改,最簡單的方法是暫時關閉項目。