架構是一個比較宏觀的概念,是控制、管理代碼層面實現這一面更好地工做的過程。接下來請先看看幾個版本的架構示意圖。html
如上圖所示,理論上單個Tomcat併發容量是200~300左右,通過優化後的最多500。雖然單機Tomcat開發部署簡單,但出點故障就不行了,例如出現單點故障後應用服務就不能夠訪問了。前端
如上圖所示,提供備用11.4 IP,當IP請求來的時候進行IP輪詢,第一個請求走12.3,第二個請求走11.4,下一個請求又走12.3依次輪詢。這樣不只解決了單點故障的問題,容量也提高了。但仍是存在一些缺點,例如:java
此架構圖咱們在瀏覽器和Tomcat之間加了請求分發工具和負載均衡設備。將請求入口集中在nignx下管理,用nignx的反向代理/負載均衡的典型算法,隨機將請求分發到不一樣的Tomcat。外網僅暴露一個接口,而Tomcat沒有暴露到外網,上面的所遇到的問題也獲得了比較好的解決。但這樣的架構離天衣無縫還差的很遠,由於請求分發、負載均衡的設備只設置了一臺,只要存在單臺,那麼單點故障也會存在。並且這是一個重要節點,負責一切請求,一旦出故障,全部服務不可用。因此就衍生了下一個架構.nginx
雙機熱備,解決了負載均衡的單機BUG問題。可是對外同一時刻只有一個在服務,一個負責請求,另一個隨時待命,每隔一段時間作一次心跳檢測負載均衡是否都存活。假如其中一個掛了,就要把虛擬IP改到另一個負載均衡設備(Nginx),這樣就能夠繼續提供服務了,體現了高可用性。web
這樣的架構算是還比較滿意,但有存在的缺點:算法
接下來咱們一塊兒來看看一套比較完善的方案數據庫
這一套方案是基於雙機熱備 + DNS輪詢,在DNS供應商作些手腳,戶輸入域名經過瀏覽器訪問DNS服務器,獲得一個虛擬IP,經過虛擬IP進入相應的雙機熱備份,下一個請求來了,就經過輪詢,用下一個虛擬IP又進入了另一個虛擬IP對應的雙機熱備份。apache
最後,在實際開發中這一套方案能夠承受起幾百萬的訪問量,但仍是以實際壓力測試和單點故障測試數據爲準。單機Tomcat跑一個應用的美好時代一去不復返,但一個成熟的產品一天24小時都要不停機運行。後端
F5(硬件設備)實現瀏覽器
優勢:很是快,可靠性高,併發量大
缺點:成本高,不方便,最致命的是不能將動態請求和靜態請求分離
缺點:不能將動態請求和靜態請求分離(不多用)
優勢:可靠性高,能夠動靜請求分離
缺點:效率低
簡介:這是一種反向代理軟件,反響代理:將龐大的Tomcat服務器的IP隱藏,真正在工做的是Nginx(即服務器隱藏了,找了個代理),正向代理:即隱藏用戶IP。
優勢:很是快,可靠性高併發量大,更重要的是能夠實現動態請求和靜態請求分離
負載均衡所存在的問題:session ID會發生變化
原理:Nginx 動靜分離簡單來講就是把動態跟靜態請求分開,不能理解成只是單純的把動態頁面和靜態頁面物理分離。嚴格意義上說應該是動態請求跟靜態請求分開,能夠理解成使用Nginx 處理靜態頁面,Tomcat、 Resin 出來動態頁面。
測試軟件:jemeter
步驟:
1.建立一個簡單的Servlet工程,打包成war並部署到Tomcat
ServletDemo類
test.jsp
2.下載jemeter
網址:https://jmeter.apache.org/dow... 解壓而後bin目錄下雙擊jmeter.bat.
3.添加線程組並填寫參數
4.添加Http請求並填寫參數
5.添加監聽想要查看的選項
6.簡單servlet項目測試結果:
圖形結果圖
察看結果樹
聚合報告結果
7.超多條線程演示
測試過程當中能夠偷偷查看一下任務管理器的數據由於線程數高了有些時候會致使電腦卡頓。
最後來看一下6000條線程下的聚合報告
當線程數很高的時候,Tomcat承受不聊了(受業務影響),其中Error表明錯誤率,Throughput表明Tomcat的吞吐量。因此說Tomcat承受能力是有限的。
若是有興趣你能夠到的Tomcat安路徑下servlet.xml修改一些配置繼續測試。固然也能夠經過這裏進行一些相關優化。
地址:http://nginx.org/ 找stable version版的下載,儘可能不要下載最新的
複製Tomcat並修改能夠修改的端口(文件在conf的server.xml)。同時分別對應兩個Tomcat的學習項目作個標記,好比第一臺tomcat訪問成功的界面顯示「Hello,Tomcat 1 shide 」,第二臺同理。這裏記錄一下我第二臺Tomcatserver.xml的端口修改,以防時回查時忘記。
8005→8015 8080→8090 8009→8019 8443→8453
在文件中添加兩個東西
1. upstream test-service{ server localhost:8080; server localhost:8090; } # upstream表示上游服務器,test-service填的是服務器集羣名,這裏取test-service。 2. proxy_pass http://test-service; # 意思是隻有test-service下面的tomcat才能經過個人反向代理。
在瀏覽器輸入上一篇文章的項目訪問路徑:http://localhost/test_war/test
首先會看到下圖狀況:
刷新一下結果以下圖
發現每刷新一次瀏覽器Nginx就將請求發送到另外一個Tomcat,這體現出了負載均衡的輪詢算法。接下來就介紹幾種常見的負載均衡算法。
很公平的原則,即每次過來的請求都會分配到相應的tomcat,你們一次排隊各入各的位置。若是沒位置了又從頭開始。
經過過必定範圍的隨機數來分發請求給相應的tomcat.當請求量很大時,接近輪詢。
經過請求來源的IP計算相應的hashCode來分發給相應的Tomcat,只要IP不發生變更,請求分發的Tomcat也就固定了。
在輪詢的基礎上增長權重,好比,如今是tomcat1,tomcat2,此時tomcat2加權重4,那麼輪詢的順序即tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2。
跟加權輪詢相似同樣的作法。好比,tomcat1,tomcat2,此時tomcat2增長權重爲4,那麼tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2,那麼tomcat隨機分發的時候分發的概率就增大。
根據後端服務器當前的鏈接狀況,動態的選取當前積壓鏈接數最少的一臺服務器來處理當前請求。
Nginx負載均衡實戰回顧,咱們採用了輪詢以及另外幾種常見的負載均衡算法實現了Nginx的效果,接下來咱們分別對兩個Tomcat稍微改造一下。
操做:在界面上顯示session ID
啓動Tomcat和nginx並輸入路徑結果以下圖,刷新界面以後會發現請求會分發到另外一個tomcat上,sessionId也會發生變化,再刷回到tomcat1的時候sessionId也會發生變化。因此這就出現了sessionId不一致的問題,大部分系統是要求用戶登陸的,因爲session的問題會致使用戶登錄以後每一次請求均可能要從新登陸,顯然用戶體驗極差!!!
Tomcat)之間進行session同步
即應用服務器Tomcat之間session同步共享,可是應用服務器自己能力有限,再加session同步會帶來網絡開銷。(具體操做百度:N個tomcat之間實現Session共享)。
基於(輪詢 和 源地址哈希)算法(適合通常)
要設置ip hash算法(修改Nginx的conf文件:ip_hash ) 請求定位到同一臺應用服務器,不切換tomcat。
修改以後重啓nginx訪問界面,多刷新幾遍看看session是否會發生變化?
很顯然session沒有發生變化,同個瀏覽器內打開新標籤訪問路徑也是同一個session。這方案雖然解決的session問題,可是不容災了。由於若是定位到的那臺應用服務器掛了,那麼用戶是沒法訪問的。
外置集中管理session(主流,其實就是相似單點登陸)
利用NoSQL數據庫、Redis 實現session外置集中管理,將用戶每次登陸以後的sessionId保存到NoSQL數據庫或者Redis中,sessionid是能夠標識一個用戶的,咱們能夠用用戶的燈登陸信息(帳號密碼、時間戳)生成一個token並設置加密、解密,用戶登陸以後將token存到tomcat外面,須要用到session的時候就到外置的集中管理中取,爲了請求能分發到相應用服務器,從外置集中管理中取token校驗便可。這樣就解決的session共享問題。
簡單理解:動態請求是要訪問數據庫並進行後端服務操做的,而靜態資源(HTML,JavaScript,CSS,img等文件)與後臺應用分開部署,提升用戶訪問靜態代碼的速度,下降對後臺應用訪問。
項目改造
1.在tomcat1(我這裏沒有改,把8.5看成是1了)的webappstest_war下建立static文件夾並添加一張圖
2.在jsp界面引用這張圖片
3.啓動tomcat 1並訪問效果以下圖
4.把靜態資源文件放在nginx的html下並修改nginx.conf文件
這裏要注意請求的路徑必須和tomcat的下面一致
location ~ \.(gif|jpg|jpeg|png|bmp|swf)$ { root html; }
而後重啓nginx並訪問界面還會看到原來的界面。
剛開始架構圖那裏所提到的負載均衡的雙機熱備的存活檢測方案其實就是keepalive這個玩意,官網只提供Linux版本的,弄起來仍是比較麻煩的,要想深刻了解的仍是百度咯。
這裏貼上心跳檢測原理圖
主要是中間這個玩意,左右兩邊的主備nginx設備綁定到同一個Keepalive,Keepalive會根據上游請求的虛擬ip轉發給主Nginx,定時檢測主Nginx是否存活,否就立馬將ip轉到備用的Nginx。
1.輪詢(默認)
每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。
2.weight
指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。
3.ip_hash
每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題
4.fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
5.按訪問的url的hash結果來分配請求,使每一個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
所謂四層就是基於ip+端口的負載均衡;
七層就是基於URL等應用層信息的負載均衡;
同理,還有基於MAC地址的二層負載均衡和基於IP地址的三層負載均衡;
換句話說,二層負載均衡會經過一個虛擬MAC地址接收請求,而後在分配到真實的MAC地址,三層負載均衡會經過一個虛擬IP地址接收請求,而後再分配到真實的IP地址,四層經過虛擬IP+端口接收請求,而後再分配到真實的服務器;
七層經過虛擬機的URL或主機名接受請求,而後再分配到真實的服務器。
優缺點 :
七層負載均衡也稱爲「內容交換」,也就是主要經過文中的正真有意義的應用層內容,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。
以常見的TCP爲例,負載均衡設備若是要根據真正的應用層內容再選擇服務器,只能先代理最終的服務器和客戶端創建鏈接(三次握手)後,纔可能接收到客戶端發送的真正應用層內容的報文,而後再根據報文中的特定字段,再加上負載均衡設備設置的服務器選擇方式,,決定最終選擇的內部服務器,負載均衡設備在這種狀況下,更相似於一個代理服務器,負載均衡和前端的客戶端以及之後端的服務器會創建TCP鏈接,因此從這個技術原理上來看,七層負載均衡對負載均衡的設備要求更高,處理能力、精確率更加友好。