1. 程式人生 > >利用Nginx+Tomcat搭建高效能負載均衡伺服器叢集

利用Nginx+Tomcat搭建高效能負載均衡伺服器叢集

當網站或應用的持續的執行帶來訪問不斷增加,伺服器承受的壓力也不斷增加,進而引發出伺服器記憶體消耗越來越大,執行和響應越來越慢... 甚至出現卡頓或嚴重時出現宕機現象,屌絲般的個人或初創公司又不想花錢,怎麼辦呢?搭建叢集伺服器來應付不斷增大的訪問量是不錯的選擇,而且大大降低成本,目前來看是非常不錯的選擇,最近在網上看一篇牛人寫文章(見後面連線),不知能真否建立如文所說的,於是今天下午就嘗試搭建核實一下,利用 Nginx+Tomcat 搭建高效能負載均衡伺服器叢集,果然結果成功了,很不錯,以下就記錄一下實現的整個過程,跟大家分享一下;

一,環境和工具準備;

1,window系統環境;
2,Nginx下載

,到官網 http://nginx.org/en/download.html 下載Stable version(穩定版),俺用 1.14.0 版本;
3,Tomcat下載,到官網 http://tomcat.apache.org 下載合適相應版本,俺下載 Tomcat8,儘量下那種可以指令碼啟動的綠色版 ;

二,目標;

對不同client端的請求,經過 Nginx 伺服器,根據一定的配置把各個請求按不同的權重設定轉發給叢集中的不同伺服器,實現高效能負載均衡 Tomcat web伺服器群集;

三,搭建步驟;

1,下載 tomcat8,解壓到某個地方,如Tomcat8_Group_Server01,複製一份改資料夾名稱Tomcat8_Group_Server02

,如圖

2,修改這兩個Tomcat的啟動埠,分別為18080和28080,下面以修改第一臺Tomcat 01為例,開啟Tomcat的conf目錄下的server.xml,如下圖:

用記事本或notepad文字編輯工具開啟,修改相關埠,共三處,見紅色下劃線,

同樣方式,修改Tomcat8_Group_Server02的修改如下,

同時為了區別看到啟動的是不同的 Tomcat 伺服器,分別對兩個tomcat下的 webapps\ROOT\index.jsp 稍作修改,用記事本或notepad文字編輯工具開啟,見如下紅框增加內容,


3,修改完兩個tomcat配置後,然後分別啟動,以 Tomcat 01 為例,進入bin目錄下,DOS執行或雙擊 startup.bat 檔案啟動,如下;


啟動 Tomcat 01 後如下圖,

同樣方式,啟動 Tomcat 02 後如下圖,

到此,兩個完全獨立的 Tomcat 伺服器 01 和 02 已經建立並執行起來了;

用記事本或notepad文字編輯工具開啟 Nginx 應用下的檔案 conf\nginx.conf 配置檔案,如下圖,


修改配置為如下,配置很關鍵注意細節

#user  nobody;
worker_processes  1;  #工作程序的個數,一般與計算機的cpu核數一致  

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;  #單個程序最大連線數(最大連線數=連線數*程序數)
}

http {
    include       mime.types;
    #副檔名與檔案型別對映表  
	
    default_type  application/octet-stream;
    #預設檔案型別 

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on; 
    # 開啟高效檔案傳輸模式,sendfile指令指定nginx是否呼叫sendfile函式來輸出檔案,對於普通應用設為 on,
    # 如果用來進行下載等應用磁碟 IO重負載應用,可設定為off,以平衡磁碟與網路I/O處理速度,
    # 降低系統的負載。注意:如果圖片顯示不正常把這個改成off。
	
    #tcp_nopush     on;

    keepalive_timeout  65;
    #長連線超時時間,單位是秒

    gzip  on; 
    #啟用Gizp壓縮  
	
    #伺服器的叢集定義,關鍵 
    upstream  myGroupServer.com {  #伺服器叢集名字  
        #ip_hash;	#此處不啟用是為了看到不同的群集伺服器
        #當不啟用ip_hash可以看到訪問按設定的權重隨機轉發到不同的群集伺服器,
        #出現的問題是如果訪問在某伺服器已經登入,當每次重新整理後重新訪問(路由改變)有可能被轉發到另一群集伺服器上,這導致在該新伺服器上出現未登入的情況;
        #當啟用ip_hash可以解決登入session丟失假象的問題(確保訪問過程中路由不改變),因同一IP來源訪問經ip_hash演算法後都會轉發到相同的某個集伺服器上,
        #出現的問題同一IP都會訪問相同的某個群集伺服器,對使用者來說可能出現僅有一個伺服器的假象,並且如果正好該群集伺服器司機,請求則重轉發到另一伺服器;
		
        server    127.0.0.1:18080  weight=1; 		
        server    127.0.0.1:28080  weight=2; 			
	    #server   127.0.0.1:38080  weight=2; 
	    #叢集伺服器列表,每個伺服器配置weight是權重的意思,權重越大,分配的概率越大。 		
	    #假設虛擬配置一個不存在的群集伺服器(如上埠38080),出現的問題是nginx同樣會把請求按指定的權重隨機轉發到該不存在的伺服器上,		
        #並嘗試連線,直到連線達到keepalive_timeout設定時間,如果還沒有連線上則按新一輪把請求重新轉發,如果連上某個群集伺服器則響應請求,
	    #如果都沒連上超時了則返回5xx錯誤;
    }

    #當前的Nginx的配置  
    server {
        listen 80;
	    #監聽預設的web 80 埠,可以改成其他埠
		
        server_name localhost;
	    # 當前服務的域名

        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        #如下location配置請求轉發控制,關鍵
        location / {
            proxy_set_header Host $host;  
            #反向代理伺服器把請求頭的host改為跟來源處一樣,如果不設定則就跟proxy_pass指令值一樣,會引起URL錯誤或丟失等問題, 關鍵
            
            proxy_set_header X-Forwarded-For $remote_addr;
            #如果存在多級反向代理需要設定該指令,這個值是經過代理之後的前一個代理 $remote_addr值(一般即IP),如第三級代理儲存第二級代理IP,關鍵

            proxy_pass http://myGroupServer.com;  
	        #對本伺服器請求 localhost:80 將轉發到名為 myGroupServer.com 的群集處理,關鍵
			
            proxy_redirect  default;
	        #指令作用是對傳送給客戶端的URL進行修改,
	        #使用 default 引數,將根據location和proxy_pass引數的設定來決定
        }
	
        
		# 靜態頁面資源處理, 
		location /www/ {
			root data; 		
			#相對路徑,相對nginx安裝目錄下的data為根目錄,work ok
			
			#root E:/J2EEServer01/nginx-1.14.0/data;	
			#也可指定絕對路徑,如window系統下,注意是/分隔符,work ok
			
			index index.htm index.html;
			#指定預設頁面,如果匹配路徑沒有指定頁面名稱,則會從index的配置中查詢名稱,再找不到則報錯
		}
		# 靜態頁面資源處理,對www開頭的URL會對映到本伺服器的 /data 目錄下,例如:
		# http://localhost:80/www/pages/page01.html 會對映到本伺服器的 /data/www/pages/page01.html
		# 即 root 配置的路徑加上URL中匹配部分起的直到結尾,即為伺服器的真實路徑
		
		
		# 靜態圖片資源處理, 
		location /images {
			#root data;
			#相對路徑,相對nginx安裝目錄下的data為根目錄,work ok
			
			root E:/J2EEServer01/nginx-1.14.0/data;
			#也可指定絕對路徑,如window系統下,注意是/分隔符,work ok
			
			index index.jpg index.gif index.png;
			#指定預設圖片名稱,如果匹配路徑沒有指定圖片名稱,則會從index的配置中查詢名稱,再找不到則報錯
		}
		# 靜態圖片資源處理,對images開頭的URL會對映到本伺服器的 /data 目錄下,例如:
		# http://localhost:80/images/news/newspic.jpg 會對映到本伺服器的 /data/images/news/newspic.jpg
		# 即 root 配置的路徑加上URL中匹配部分起的直到結尾,即為伺服器的真實路徑
			
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html        
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
			index  50x.html 50x.htm; #預設頁面列表
        }
    }
	
}

location 配置規則

1、“ =”字首的指令嚴格匹配這個查詢。如果找到,停止搜尋。 
2、所有剩下的常規字串,匹配最精確的(一般最長的那個)。如果這個匹配使用^〜字首,搜尋停止。 
3、正則表示式,在配置檔案中是從上往下匹配的 
4、如果第3條規則產生匹配的話,結果被使用。否則,如同從第2條規則被使用 
特殊情況: 
兩種情況下,不需要繼續匹配正則 location : 
( 1 ) 當普通 location 前面指定了“ ^~ ”,特別告訴 Nginx 本條普 通 location 一旦匹配上,則不需要繼續正則匹配。 
( 2 ) 當普通location 恰好嚴格匹配上 ,不是最大字首匹配,則不再繼續匹配正則

可以測試nginx配置語法是否正確,DOS下檢測命令:nginx -t  (預設驗證:conf\nginx.conf),也可以指定配置檔案路徑。

關鍵配置和其中請求轉發到群集中的伺服器時涉及的登入 session 問題,虛設不存在的伺服器(等同伺服器宕機)出現的問題,參見配置中的註釋,更多問題請參考相關文件和在實踐中自己摸索和總結... 到此,關鍵的 Nginx 負載均衡配置已經完成;

5,啟動 Nginx 伺服器,注意確保 80 埠別被其它應用佔用了,如下圖所示,

若果想停止nginx,dos環境執行命令:nginx -s stop 即可,如果不停止過載nginx,命令為:nginx -s reload,注意 Nginx 除了可以做請求轉發伺服器,還可以作為靜態資源伺服器,適當合理配置即可,這不在本文範圍內,僅提一下;

6,看效果,按 localhost:80 方式訪問,即按 Nginx 配置的方式訪問 Nginx 伺服器(注意不是直接訪問 Tomcat 01 或 02 伺服器),如下圖,


相同的地址,再重新整理一或幾次,如下圖,

也即當我按相同的 localhost:80 地址訪問 Nginx 伺服器時,我們發現有時看到的是群集中的 Tomcat 01 伺服器,再重新整理訪問地址,有時看到的是群集中的 Tomcat 02 伺服器,不斷的重新整理,我們發現 Tomcat02 伺服器出現概率是 Tomcat 01 伺服器的約兩倍,也即群集伺服器的權重設定,到此,我們發現通過 Nginx 伺服器,請求確實按 Nginx 的配置根據不同的權重值隨機轉發給群集中不同的Tomcat伺服器了,達到預期配置目標了;

四,總結;

怎麼樣?實現一個高效能的負載均衡叢集就這麼完成了。Nginx的功能如此強大,配置卻如此簡單,我們還有什麼理由拒絕它呢?這比我們動不動就十多萬至幾十萬人民幣的F5 BIG-IP、NetScaler等硬體負載均衡交換機廉價了不知多少。此外,大家別忘了Nginx不僅僅是一個反向代理伺服器,它本身也可以託管網站,作為Web伺服器,靜態資源伺服器,進行Http服務處理;