1. 程式人生 > >Web應用系統性能調優思路

Web應用系統性能調優思路

    當一個Web應用的使用者量增大以至於單個節點無法承擔訪問壓力時,我們首先需要對程式碼進行優化,檢視程式碼中是否有記憶體洩漏,是否有資源沒有關閉,是否有演算法可以優化等等,另外我們需要優化資料庫,是否是查詢效能低,可以建立索引等。當代碼層面的問題我們都處理過之後,下面就需要考慮系統架構了。

    我們首先要做的就是資料庫與Web應用分離。資料庫伺服器使用者提供資料庫服務,而Web伺服器僅僅對外提供Web服務。這個時候,如果Web伺服器的訪問壓力依然很大,我們可以使用Nginx來進行動靜分離,靜態資源直接走Nginx,動態介面再轉發給Tomcat來進行處理。這樣可以大大提高Tomcat的吞吐量。如果依然壓力過大,就需要考慮Web服務的叢集問題,也就是Tomcat的叢集問題。

    Tomcat叢集就是由多個伺服器中部署Tomcat應用(一臺伺服器可以部署一個或多個Tomcat),多個Tomcat上部署同一個Web應用。使用者就可以嘗試訪問多個Tomcat來緩解壓力。當然,讓使用者選擇伺服器的方式畢竟是不好的,第一是使用者選擇具有不確定性,可能很多人都選擇第一個伺服器,這樣就會造成第一個伺服器的壓力過大,而叢集中其他的伺服器浪費,第二使用者的體驗度不好。那麼不讓使用者選擇,又能均勻的分攤到每臺伺服器,我們該怎麼辦呢?這個時候負載均衡就出現了。

    所謂的負載均衡就是在眾多的Tomcat前面再加一臺伺服器,這個伺服器不做具體的業務操作,僅僅是接收使用者的請求,然後將使用者請求均勻的分攤到對外提供服務的Tomcat中。Web服務的叢集第一層負載均衡我們一般使用Nginx,Nginx提供了強大的路徑匹配規則。當用戶訪問我們的網站時,首先到達的是Nginx,然後由Nginx根據相應的負載均衡演算法選擇指定的Tomcat,然後由Nginx來訪問Tomcat並由Nginx來給使用者響應結果。但這種方式是有一定的問題的。

    第一個是所有的訪問都會走Nginx,會造成Nginx節點的訪問壓力大。對於這個問題,雖然看上去壓力會比較大,但實際上處理的資訊並不多,因此不會很大。如果確實壓力比較大怎麼辦呢,我們可以使用lvs或者硬體裝置F5來做負載均衡。lvs的dr模式可以非常輕鬆的解決這個問題。具體的dr模式這裡不過多的解釋,就是請求來的時候走lvs節點,資料返回的時候直接由真實提供服務的機器來返回資料,不走lvs節點。這樣就大大降低了負載均衡節點的壓力。

    第二個是如果一旦Nginx節點宕機,那麼整個服務都不能對外提供服務。這個問題涉及到了Ha(High available),可以通過keepalived進行心跳探測,一旦伺服器宕機立馬切換為備用節點。

    第三個是session同步問題,我們知道http是無狀態的,為了表示一次會話,引入了session,在這裡不深入session的原理,我們知道,每次會話都會產生一個session儲存到服務端,我們也就是根據session來做一些驗證,比如使用者登入等等。如果使用了多臺伺服器叢集,比如我們第一次請求了第一個機器,做了登入,第二次負載均衡裝置給我們路由到了第二臺機器,那麼session是存到了第一臺機器上,第二臺機器依然不認為登入,這就造成了問題。解決這個問題的關鍵就在於需要將叢集中的多個tomcat看成一個,然後提供一個公共的場所來儲存session。這就是共享session。如何來做到共享session呢?我們可以把session存到資料庫中,然後來請求就到資料庫中去檢索。這樣是比較耗費效能的,另外session不用一段時間需要銷燬,使用資料庫來處理需要來使用定時任務,依然不是很方便。這個時候我們可以使用記憶體資料庫Redis,它可以為我們提供方便的讀寫。

    Redis是一個記憶體資料庫,儲存的是鍵值對的形式。這樣就把session從tomcat維護放到了有Redis來維護了。Redis本身具有鍵過期的功能,因此可以通過設定鍵過期時間來解決session超時的問題。另外大家都覺得使用Redis來管理Tomcat的Session比較好,因此早已有大牛把功能都實現,因此,我們只需要下載響應的包,放到Tomcat中,並進行簡單的配置,Tomcat的Session就可以放到Redis中了。

    這樣對於一個Nginx + Tomcat + Redis架構也就完成了。