由Tomcat入手LVS+Nginx集羣

相信學過javaEE的都做過幾個web項目,將項目打包爲war文件(或者直接在eclipse中),在Tomcat中發佈即可通過瀏覽器訪問。寫這篇文章,爭取表達最通俗的意思,由這個過程引到集羣的概念,整明白現在用的幾個熱門的技術是做什麼的,不求具體及其原理,包括LVS、Nginx、Keepalived、memcached。

(我也是剛起步學習,將現在的理解整理爲一篇文章,略顯淺顯,如果有共同學習的讀來可以當做入門,先明白這些東西是什麼、有什麼用,之後再去查閱更專業的資料。如果有地方理解錯誤,也請大佬們指正~)

Tomcat

我們剛開始學習web時,肯定接觸tomcat比較多,以tomcat作爲搭載一個web
項目應用的服務器。客戶端向服務端發送Request,服務器端處理後返回Response。
在這裏插入圖片描述


現出現情況一:
在一個時刻,同時1000個用戶向服務器請求資源

情況分析:Tomcat的抗併發量在百數量級,就是說來幾個百併發訪問還可以應付一下,1000個併發來了,一個Tomcat肯定應付不過了,導致響應極慢甚至服務器崩潰。這就是接下來要考慮的抗併發問題


一昧的去提升服務器的硬件性能成本太高,況且Tomcat本身的也不是專門的抗併發服務,稱爲瓶頸。既然縱向提高單臺服務器的性能有侷限性,那爲何不橫向的增加服務器的數量呢?

假設我們準備10臺完全相同的服務器,讓這1000個用戶在這一個時刻去分散到不同的服務器訪問資源,那麼平均每臺服務器僅需處理100的併發量,對Tomcat來說是綽綽有餘的。
在這裏插入圖片描述

看來這是一個解決方案。但再想,這個方案無疑是給用戶增加了不必要的工作,需要去選擇訪問哪一臺。既然做的是服務,用戶纔是一切,給用戶帶來了不變是致命的;服務器當然也是如此。用戶要的就是在瀏覽器輸入網址,給我相應的信息就好了,後端多麼複雜,不關用戶的事。

既然選擇用哪一臺服務器的工作不能留給客戶端,那不妨還是把鍋丟給服務端。自然而然,可以想到,把這幾臺服務器放在一個內網當中,再另外做一個面向用戶的服務,專門來“暗地裏指揮”用戶請求去向哪一臺服務器。這個服務一方面面向客戶端拉客,另一方面安排服務器接客。
在這裏插入圖片描述至此,這就成了一個簡單的負載均衡集羣。中間的服務器就叫做負載均衡服務器,後面的幾個Tomcat實際就是集羣中的真實服務器。而負載均衡的服務也不用我們自己開發,在linux系統內核中已經集成了這個功能,也就是LVS(Linux Virtual Server)

LVS(Linux Virtual Server)


我們常用的負載均衡可分爲四層負載均衡和七層負載均衡,這涉及到了網絡的知識,第四層爲網絡層,第七層爲應用層。簡單來講,四層負載均衡是指這個服務僅僅看到四層的東西(即源IP、目標IP、端口等)依此來安排負載;七層則是看到了七層的東西(即uri等,也就是我們學java所接觸的http協議那一套)來安排負載。

LVS可以實現四層負載均衡。

LVS是Linux內核自帶的功能服務,就是說在它是集成在linux系統內的,裝上系統配置配置就能用。

LVS有三種工作模式(即整體上是怎麼實現負載均衡的,幾種方式各有優劣)

  • NAT(地址轉換方式)
  • DR(直接路由方式)
  • TUN(隧道方式)

LVS還是多種調度策略(即用個什麼算法去分配RS)

LVS的工作的大體流程可以概括爲:
LVS工作在四層,與TCP協議打交道,客戶端發出的HTTP包前會有TCP包,將包發給LVS,LVS會根據配置的調度策略,選擇一個RS,處理一下TCP包,扔出去,讓RS收到去拆開看HTTP包,處理請求。對於NAT模式,是將TCP包的目標IP改成RS的IP,還需同樣處理RS返回來的包;對於DR模式,同NAT模式的處理方式,但不用處理RS返回來的包,RS中配置了一個隱藏的VIP,可以直接返回給客戶端,但LVS要與RS集羣在一個局域網內;對於TUN模式,是將這個包作爲內容封裝爲一個新的TCP包發給RS。

(以上不展開了,大體知道LVS是做什麼就好,具體可以再查找其他的資料)

下面用
LB(Load Balance)表示負載均衡
RS(Real Server)表示真實服務


現在我們的項目成了下面的樣子:
在這裏插入圖片描述到這肯定會有疑問,LVS也是做一個服務器,大量的併發來了後,它怎麼不崩。原因很簡單,LVS只是工作在四層的TCP包,根據配置,處理一下這個包,扔出去就行了;因此它的坑併發能力高的很。

但還有一點缺陷:


現出現情況二:
用戶使用的時候,經常退到登錄界面,提示沒有登錄

情況分析:這個原因很清楚了,因爲做成了Tomcat的集羣,用戶每一次訪問,可能並不是同一臺服務器,因此session就成了一個問題


對於這個,Tomcat倒是給出了一個解決方案,Tomcat自身就可以配置存放及拿取SessionID的地方,默認是本地內存中。我們只要改一下Tomcat的配置,將所有的RS的SessionID保存在同一個地方不就可以了。

在網絡中,不妨保存在同一臺服務器上。但再想,sessionID可是每一次請求都有去取一次的,如果將它保存在數據庫或是文件中,通過IO拿取,勢必會浪費很多時間。

這就引出接下來要出場的memcached

memcached

memcached可以理解爲存在內存裏的數據庫。

只有在某一臺服務器安裝memcached,並配置所有的Tomcat的sessionID保存路徑都爲這一臺服務器的memcached中,每次client的訪問,Tomcat的存取Session都通過這臺服務器,上面的問題不就解決了嗎。

當然,memcached的用處遠不止解決session問題。在這不再深入。

現在整個集羣變成了如下的樣子:
在這裏插入圖片描述


現出現情況三:
LVS服務器因爲某種原因崩了
或者某臺RS因爲某種原因崩了

情況分析:
雖然LVS的抗併發問題不大,但是保證不了這臺服務器不出問題,萬一LVS服務器出現硬件故障宕機或者其他原因崩了,即使所有的RS都正常工作也無濟於事了。因爲LVS這一個節點造成了整個集羣的癱瘓,當然是不合適的。
同樣,某臺RS崩了,LVS若不及時得知消息,還不斷的讓這臺RS出來接客,必定影響用戶體驗。
這就引出了接下來要解決的單點故障問題,實現高可用。


很容易想到,一臺LVS崩了,再找一臺頂上去唄。但這臺頂包的LVS服務器應該和原來的服務器保持完全一致才行。這就是要爲LVS搞一個主備模型。正牌正常工作時,備胎在一邊候者,正牌有情況不在,備胎馬上頂上,爲了讓客戶有完全一樣的體驗,備胎時時刻刻要跟正牌學習,做到和正牌完全一樣;當正牌回來了,備胎可以一腳踢開了。這就是主備機工作的方式。

一臺RS崩了,那就把這臺剔除掉,等恢復了再加進來唄。

整個的這一個過程也不用我們自己開發相應的程序,現有很成熟的軟件供我們使用,即Keepalived

Keepalived

keepalived與LVS配套使用,可以看做LVS的一個“管家”,管理LVS的配置、開關、同步主備機,更重要的是實現一個LVS集羣的高可用。

假設有兩臺LVS服務器,每個LVS服務器上都請這麼一個管家(安裝一個keepalived),其中一個keepalived將自己的LVS配爲主機,另一個配爲備機。那麼LVS安心幹活就是了,剩餘的問題處理交給各自的keepalived管家。(下面稱主機的keepalived爲主K,備機的爲備K)

主K比較忙,一方面要定時向備K發送LVS的健康狀態廣播,就是告訴備K你先老老實實的,我們家LVS還正常幹着活呢;另一方面,主K要定時向集羣RS發送請求,驗證每臺RS的健康狀況(都收到響應碼200就是存活,這叫心跳檢測),並將宕機的RS剔除,不再使用,當能收到200了(即修復了),再添加進來。

備K就很輕鬆了,定時收一下主K發來的健康報告,如果沒有收到,說明主機宕機,馬上安排自家的LVS要出來幹活了。這個安排的過程是keepalived基於VRRP協議(虛擬路由協議)實現的IP偏移,說白了就是將自己的IP改爲主機的IP,這樣訪問主機的請求自然就來了備機。當主機修復後,備K會重新收到主K發來的健康報告,則再將IP改回來即可。

現在這個集羣變成了下面這樣:
在這裏插入圖片描述現在的結構,能很多程度的解決併發問題及單點故障問題。但這個項目繼續做大做強,又出現新的問題。


現出現情況四:
項目做到了很大,把整個項目放在一臺服務器上,Tomcat扛不動了
即使少量的併發訪問,服務器也運作不快

情況分析:這種情況難免發生,首先可以考慮不是有Tomcat,另選一個更強大的Web應用服務器,但這治標不治本,因爲項目理論上可以無限增大,但服務器卻也就那麼多。因此要從項目本身下手。


這時,應考慮能不能把項目細分,每個Tomcat只搭載整個項目的一部分,通過客戶端的請求類型,來判斷去訪問那個Tomcat。

這就是所謂的面向服務開發。

訪問一個網頁,一般都會有圖片、文字等多種信息的呈現,假設把將視頻、音樂、圖片、文字分別放在集羣中不同的Tomcat上
在這裏插入圖片描述
因爲集羣是在一個內網中的,我們不可能讓客戶端根據自己的需求,重定向來拿相應的信息(就是不可以直接訪問RS),因此,我們還可以搞一個聯繫RS的服務,來代替客戶端從RS集羣中拿取數據。即客戶端向這個服務器發送請求,這個服務器會分析需要什麼(假如需要一段視頻和一段文字),就將請求轉發給視頻和文字的Tomcat,等待兩個Tomcat響應後,再把響應轉發給客戶端。這樣的服務器叫做反向代理服務器。(對比翻牆用的代理服務器,是請求一個服務器代替客戶端去拿數據;而這的反向代理服務器,是代理RS集羣,從內網向客戶端響應數據,其實都差不多一個意思)

能夠充當這個反向代理服務器的,就是所謂的Nginx

Nginx

先拋開剛纔的LVS,現在的集羣成了:
在這裏插入圖片描述看到這裏,這個框架的弱點仍然是Nginx結點的併發問題和單點故障

對於Nginx的抗併發能力,官方給出的是5w併發量,即輕輕鬆鬆處理5w的併發訪問。對比tomcat,之所以有這麼大抗併發,主要原因有兩個,一是Nginx只做請求和響應的轉發而沒有業務邏輯處理,大部分的時間花在與其他計算的I/O上;而是Nginx的I/O採用的是單線程或少線程、異步非阻塞的模式(Tomcat是一個連接一個線程,同步阻塞的模式),避免了打開I/O通道等待數據傳輸的過程(僅僅是在數據傳到了,再來接收即可),極大的縮短了線程調度和I/O處理的時間。

對應Nginx的單點故障,仍然可以用keepalived解決,這裏爲了畫圖方便先不加上了。


現出現情況五:
客戶端趕巧在都是訪問了視頻資源
這是Nginx將1000條併發訪問都轉給了視頻Tomcat
這個Tomcat還是會崩

情況分析:這又成了最開始的tomact併發問題


面對這個問題,首先想到當然要有負載均衡技術,再在Nginx和RS直接添加LVS顯得太繁雜。強大的Nginx已經爲我們考慮好了,它自身就帶有七層負載均衡的功能。同樣配置一下就可以用了。則整個集羣變爲了
在這裏插入圖片描述因此,Nginx實際可作爲一個反向代理服務器,同時具有七層服務均衡的能力。


現出現情況六:
現在的併發量再一次提升,超過了5w,Nginx的效率也到了瓶頸

情況分析:不說了,再把LVS揉進來就是了


在這裏插入圖片描述
這裏LVS採用了DR的模式,讓Nginx將響應直接發給client。
到此,這個集羣基本成熟,下一篇將整理一下用虛擬機搭出這個集羣的過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章