1. 程式人生 > >Apache負載均衡與Spring Session

Apache負載均衡與Spring Session

Apache web伺服器配置

安裝Apache並啟動Apache服務

Apache是一個web應用容器,和tomcat,iis等是一類軟體,除了普通web容器的功能,Apache還可以配置反向代理,實現web伺服器的負載均衡。這裡先示範如何通過Apache建立一個普通的web應用。通過apache官網下載apache,我下載的是Apache2.4解壓版,所以還要手動配置一下。

  1. 配置安裝目錄
    這裡寫圖片描述
    在apache的安裝目錄中找到conf資料夾,其中有一個httpd.conf檔案,開啟這個檔案,在大約38行的位置配置一下apache的安裝目錄。

  2. 安裝並啟動服務
    進入命令列介面,執行指令httpd -k install -n Apache2.4。注意,如果上一步安裝目錄配置不正確,這裡會提示找不到目錄。
    這裡寫圖片描述


    安裝成功後,右鍵“計算機”->”管理”->”服務和應用程式”->”服務”,檢視服務是否安裝成功,安裝成功後還要手動啟動服務。
    這裡寫圖片描述

  3. 配置web應用的相關屬性
    首先是ServerName,也就是訪問web應用時用的域名,這裡用localhost:80:
    這裡寫圖片描述
    然後是配置web應用所在目錄:
    這裡寫圖片描述
    這裡使用了預設的目錄htdocs,可以將自己的web應用放到這個目錄下,這個目錄自身已經包含一個html檔案:
    這裡寫圖片描述

4.訪問web應用,如果修改過配置檔案,需要在命令列中使用httpd -k restart重啟一下伺服器。
這裡寫圖片描述

Apache反向代理配置與負載均衡

反向代理與正向代理相對,所謂正向代理,就是多個使用者給自己的瀏覽器設定一個代理伺服器,這樣代理伺服器就和多個客戶端瀏覽器繫結,所有這些使用者傳送的請求都會先經過瀏覽器包裝成目標地址為代理伺服器的請求,這樣就可以繞過一些訪問限制。反向代理是指通過配置代理伺服器,使代理伺服器與多個web伺服器繫結,然後僅對使用者提供代理伺服器的域名,代理伺服器根據配置的對映關係將使用者的訪問轉發到不同的web伺服器中,這些web應用往往屬於同一個系統,用來負載均衡,分流使用者的請求。配置反向代理只需要兩部,第一步為配置載入模組,第二部為配置對映。

載入模組

開啟httpd.conf,分別找到如下兩行,並將#註釋去掉,這樣Apache就會載入相關模組

#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPass                  /proxy2 http://target2:port/url
ProxyPass                  /proxy3 http://target3:port/url
......

負載均衡

上面反向代理的作用是可以將一個地址/proxyX對映到另一個址

http://targetX:port/url,這種對映關係是一對一的,實際應用中可能更多的是出於隱藏地址和網路安全方面的作用。負載均衡在反向代理的基礎上,可以實現一對多的地址對映,這裡“一”是統一的共使用者訪問的地址,“多”是多個完全相同的web應用,使用者通過統一的地址訪問應用,Apache根據負載均衡演算法決定將使用者的請求分配給哪一個web應用伺服器,實現負載均衡的效果。

下面是一個配置例項:

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so

<Proxy "balancer://mycluster">  
BalancerMember http://localhost:8080/firstapp
BalancerMember http://localhost:8080/secondapp
</Proxy>   
ProxyPass "/proxy" "balancer://mycluster" 
ProxyPassReverse "/proxy" "/firstapp"
ProxyPassReverse "/proxy" "/secondapp"
ProxyPassReverseCookiePath "/firstapp" "/proxy"
ProxyPassReverseCookiePath "/secondapp" "/proxy" 

可以看到,與反向代理不同的是,這裡將地址對映到了”balancer://mycluster”,BalancerMember即為後臺的web應用。Apache根據配置的負載均衡演算法(注意第2行我們載入了byrequest型別的演算法,它將按照BalancerMember宣告的順序轉發使用者的http請求),將請求轉發給BalancerMember,這裡firstapp和secondapp都是完全相同的web應用,這樣就減輕了單臺web伺服器的壓力,而對使用者來說這一切都是透明的。

session共享問題

當使用負載均衡時會有session共享的問題。我們知道,web容器的session是通過向cookie中新增sessionid達到有狀態的效果的。
使用反向代理時,假設:
使用者第一次訪問的地址是http://localhost/proxy/a.html ,該請求被Apache轉發到http://target:port/url/a.html ,web伺服器target1查詢sessionid發現沒有,則新建一個session,並把sessionid隨響應報文一併傳送回去。
當用戶再次訪問localhost時,如http://localhost/proxy/a.html ,瀏覽器會在請求報文中新增相同的sessionid,但此時報文被轉發到了另一臺web應用伺服器target2,target2中查詢後發現不存在這個sessionid,這就出現了錯誤。

Spring Session配置

Spring Session是解決多web伺服器session共享的一個開源方案,通過Spring Session可以解決上面提到的問題。Spring Session的介紹這裡不再重複,網上可以查到。這裡主要利用官網的下載的sample結合Apache驗證一下效果。

執行一個sample

官方的原始碼中有寫好的sample,我們可以直接拿來體驗一下,注意,這個sample並沒有整合Apache反向代理。

  1. 搭建專案,選擇httpsession-xml這個demo,
    這裡寫圖片描述
    在eclipse中建立一個專案,伺服器使用tomcat,並將demo中的內容複製過去,注意需要引用的第三方包
    這裡寫圖片描述

  2. 安裝redis資料庫,我安裝的是ms提供的window64位版,安裝完服務會自動啟用,不必手動配置。

  3. 執行專案
    這裡寫圖片描述
    這個程式的作用就是設定並檢視session的值,這個session是經過Spring Session定義的,不是tomcat自己的session 。下面,我們還是用這個sample,但是會整合Apache反向代理。

整合Apache反向代理與Spring Session

  1. 在tomcat的釋出目錄下建立兩個專案,firstapp和secondapp,這兩個專案的內容是一模一樣的,都是上面httpsession-xml這個sample的內容。建立完後啟動tomcat。
    這裡寫圖片描述

  2. 在Apache的httpd.config中設定對映
    這裡寫圖片描述
    注意ProxyPassReverseCookiePath這條設定,由於tomcat可以在同一域名下建立多個web應用,所以瀏覽器在傳遞sessionid時並不能僅靠域名選擇要上傳的cookie,還需要域名後的一級路徑。當用戶第一次訪問站點時,站點返回的資訊包含cookie(包含sessionid),域名,一級路徑,瀏覽器將cookie(包含sessionid)和域名/一級路徑對應起來,當用戶再次訪問相同的域名/一級路徑時會上傳這個cookie。使用反向代理時,web伺服器返回的一級路徑和域名都是web伺服器而非Apache中對映的那個,比如使用者第一次訪問http://localhost/proxy/index.jsp ,web伺服器返回的一級路徑為/firstapp
    這裡寫圖片描述,這樣當用戶再次訪問http://localhost/proxy/index.jsp 時瀏覽器不會上傳cookie ,因為瀏覽器將cookie繫結到了localhost/firstapp上了,所以我們要設定ProxyPassReverseCookiePath,將web伺服器返回的一級路徑進行轉換。
    這裡寫圖片描述

3.訪問http://localhost/proxy/index.jsp , 設定一個session值
這裡寫圖片描述
可以看到Apache將請求轉發到了firstapp(這裡我把sample裡的jsp檔案改了一下<title>標籤,用來區分返回的是哪一個頁面,實際應用中多個web應用的內容是完全相同的) ,我設定了一條session,key:proxy value:1
接下來點選“Set Attribute”按鈕,請求會被提交到http://localhost/proxy/session(這是一個servlet)
這裡寫圖片描述
可以看到雖然這次請求的是另一個web應用secondapp,但是它卻獲得了剛才firstapp設定的session值,這是因為Spring Session將session儲存在獨立的Redis資料庫中而不是web容器內,這就實現了session共享。

最後是一幅圖總結內容:
這裡寫圖片描述