從lamp到高可用的web架構的演進
本文受網際網路架構大會中美團、滴滴等網際網路公司架構演進的啟發,並結合自己的實踐和實驗,從巨集觀的角度講述從簡單lamp(linux apache mysql php)到高可用web架構的一步步迭代過程。
下面的內容主要是從單一業務的角度考慮的,假設業務的複雜性不變,只有使用者量和併發訪問量的不斷增加。
簡單的lamp架構
最原始的web架構,一個httpd、php-fpm、mysql就可以執行一個B/S結構的系統或者站點。對於小併發量站點,httpd、php-fpm和mysql的結合是完全沒有問題的。
迭代1:使用nginx做負載均衡
先看一下為啥要用nginx做負載,看看httpd的三種工作模式。
httpd有三種多程序處理模型(MPM, multi-processing module),分別是:
- prefork,多程序I/O模型,每個程序響應一個請求,預設模型;有一個主程序,主要用來生成和回收n個子程序,建立套接字,不響應請求;多個子work程序,每個子程序處理一個請求;系統初始時,預先生成多個空閒程序,等待請求,最大不超過1024個;
- worker,複用的多程序I/O模型,多程序多執行緒,有一個主程序,生成m個子程序,每個子程序負責生個n個執行緒,每個執行緒響應一個請求。同時併發響應請求m*n個請求。
- event,事件驅動模型(worker模型的變種)。有一個主程序,生成m個子程序,每個程序直接響應n個請求,併發響應請求數為m*n個。httpd-2.4版本之後才有event的穩定版。
httpd的3工作模型可以很好的滿足需求,且httpd在處理動態請求時,具有很高的穩定性。但是受系統資源的限制,httpd能夠接受的請求數量也是有限制的,於是引入nginx做負載均衡伺服器,並使用nginx的ip_hash機制進行路由,這樣就可以靈活地擴充httpd服務了,部署結構如下圖所示,
迭代2:動靜態頁面分離
httpd在處理動態請求時具有較高的穩定性,而nginx在處理純靜態資源,如js/css/png等有獨特的優勢,因此可以考慮,用nginx處理靜態資源,用httpd處理動態資源,實現web站點的動靜分離。對於靜態資源,nginx直接響應,對於動態資源轉發給後端的httpd伺服器。
迭代3:使用功能更完善的負載軟體:haproxy
nginx常用於靜態資源和反向代理代理的伺服器,在做負載時對會話保持功能沒有haproxy完善。因此可以考慮,讓nginx專門做靜態資源伺服器,代理功能由haproxy來承擔。
對於後端的nginx伺服器,由於是無狀態的,可以使用輪詢的機制實現負載均衡。同時由於此時nginx的伺服器是無狀態的,可以靈活的擴充套件nginx伺服器。
對於後端的httpd伺服器,由於需要保持會話資訊,使用haproxy的cookie保持的機制來保證一個使用者的會話被轉發到同一臺伺服器上。
迭代4:使用keepalive保證haproxy高可用
引入keepalive來保證haproxy的高可用性。
迭代5:使用redis叢集實現session共享
每個httpd伺服器都有一個會話資訊,若一臺伺服器宕機,即使使用了haproxy的cookie保持機制,也不能保證使用者的會話資訊不丟失。
一個可行的解決方法是,session共享。就是將所有httpd的session資訊專門的儲存起來,即使httpd宕機,使用者的會話資訊任然不會丟失。
這裡採用CODIS來儲存各個httpd的session資訊,CODIS就是一個redis的一個分散式叢集。
架構迭代到這,你可能已經發現,nginx和httpd此時都是無狀態的,隨意的停止某一臺nginx或者httpd對web服務是無影響的。
說到無狀態,這裡可以擴充套件一下。既然是無狀態了,那我們就可以使用Docker來替換在虛擬機器或者伺服器上部署nginx和httpd,只需根據需求建立對應數量的Docker容器即可。比如,網站的靜態資源比較多,我們就可以動態的新增nginx伺服器,新增的方式就是啟動一個docker容器。
無狀態也是微服務設計的規則之一,目的就是充分利用容器的靈活性,使系統可以靈活的擴充套件。
迭代6:用mysql主從複製和中介軟體實現讀寫分離
當httpd數量足夠時,mysql可能就會出現瓶頸了。從高可用的角度,可以使用mysql的主從複製方式,來保證資料的安全和資料庫的高可用性。從負載均衡的角度,可以考慮使用中介軟體實現讀寫分離。
迭代7:使用分散式檔案系統
靜態資源的安全性和訪問的效能瓶頸也會是一個問題,這裡可以考慮使用分散式檔案系統、物件儲存等方案,來保證靜態資源的快速訪問和完整性。
迭代8:使用cdn加速
當站點的訪問跨區域時,即使架構再完善,也敵不過網聯網的延遲,因此,對於動態資源,如圖片、CSS、JS檔案,可以考慮使用區域的CDN加速,從而提高站點的響應速度。
體會
最後再分享一張圖片。
做這個分享的目的,就是希望可以把我知道的東西連線起來形成一個體系,分散的叫資訊,能夠串起來的才叫知識!
這個架構真正用起來也許會有問題,但是最起碼有了基本的輪廓!歡迎大家一起交流學習。