apache+tomcat負載均衡

yuanyuan_186發表於2016-05-01

 

(黎明你好原創作品,轉載請註明)

2.1 Tomcat連結方式

        首先我們先介紹一下為什麼要讓http server與Tomcat之間進行連線。事實上Tomcat本身已經提供了HTTP服務,該服務預設的埠是8080,裝好tomcat後通過8080埠可以直接使用Tomcat所執行的應用程式,你也可以將該埠改為80。既然Tomcat本身已經可以提供這樣的服務,我們為什麼還要引入Apache或者其他的一些專門的HTTP伺服器呢?原因有下面幾個:

        1. 提升對靜態檔案的處理效能。

        2. 利用Web伺服器來做負載均衡以及容錯。

        3. 無縫的升級應用程式。

        這三點對一個web網站來說是非常之重要的,我們希望我們的網站不僅是速度快,而且要穩定,不能因為某個Tomcat當機或者是升級程式導致使用者訪問不了,而能完成這幾個功能的、最好的HTTP伺服器也就只有apache的http server了,它跟tomcat的結合是最緊密和可靠的。

        預設情況下,Tomcat在server.xml中配置了兩種聯結器:

        第一個聯結器監聽8080埠,負責建立HTTP連線。在通過瀏覽器訪問Tomcat伺服器的Web應用時,使用的就是這個聯結器。

        第二個聯結器監聽8009埠,負責和其他的HTTP伺服器建立連線。在把Tomcat與其他HTTP伺服器整合時,就需要用到這個聯結器。

        兩種埠可以同時開,也可以開一個。例如我們使用apache通過ajp進行負載均衡配置時,可以關掉tomcat的http8080埠以防止可以被單獨訪問。

        Web客戶訪問Tomcat伺服器上JSP元件的兩種方式如圖:

 

 

        使用http方式,配置檔案

Java程式碼  收藏程式碼
  1. <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />  
  2. <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">  

        使用ajp方式,配置檔案

Java程式碼  收藏程式碼
  1. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />  
  2. <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">  

 

2.2 mod_proxy

        mod_proxy_balancer是apache httpd自帶的負載平衡支援。其優點可以根據實際的執行時機器的環境來決定負載均衡的策略。實現Session在node上進行共享傳遞。

 

2.2.1 載入so庫

Java程式碼  收藏程式碼
  1. #mod_proxy_blancer  
  2. LoadModule proxy_module modules/mod_proxy.so  
  3. LoadModule proxy_ajp_module modules/mod_proxy_ajp.so    
  4. LoadModule proxy_ftp_module modules/mod_proxy_ftp.so   
  5. LoadModule proxy_http_module modules/mod_proxy_http.so   
  6. LoadModule proxy_connect_module modules/mod_proxy_connect.so  
  7. LoadModule proxy_balancer_module modules/mod_proxy_balancer.so  

 

2.2.2 http方式

Java程式碼  收藏程式碼
  1. <Proxy balancer://mycluster>  
  2.     BalancerMember http://127.0.0.1:8080 loadfactor=3  
  3.     BalancerMember http://127.0.0.1:7080 loadfactor=3  
  4.     ProxySet lbmethod=byrequests  
  5. </Proxy>  
  6. ProxyRequests Off  
  7. ProxyPass /test balancer://mycluster/ stickysession=JSESSIONID nofailover=Off  
  8. ProxyPassReverse /test balancer://mycluster/    

 

        實現負載均衡的原理為:假設Apache接收到http://127.0.0.1 /test請求,由於該請求滿足ProxyPass條件(其URL字首為“/"),該請求會 被分發到後臺某一個BalancerMember。譬如該請求可能會轉發到http://127.0.0.1:8080/進行處理。當第二個滿足條件的URL請求過來時,該請求可能會被分發到另外一臺BalancerMember,譬如,可能會轉發到 http://127.0.0.1:7080/如此迴圈反覆,便實現了負載均衡的機制。

        loadfactor表示:後臺伺服器負載到由Apache傳送請求的權值,該值預設為1,可以將該值設定為1到100之間的任何值。以上面的配置為例,進行4此請求時,則有3次連續的這樣請求被負載到BalancerMember為http://127.0.0.1:8080/的伺服器;有1次被負載到BalancerMember為http://127.0.0.1:7080/的伺服器。

        lbmethod表示:負載載均衡策略。 

        lbmethod=byrequests 按照請求次數均衡(預設) 

        lbmethod=bytraffic 按照流量均衡 

        lbmethod=bybusyness 按照繁忙程度均衡(總是分配給活躍請求數最少的伺服器)

        ProxyPass表示:所有的test請求都會重定向到balancer://mycluster/處理。balancer是內建負載。

        ProxyPassReverse表示:反向代理,也就是將所有的請求反向代理到負載均衡後的應用url路徑中。

        stickysession表示:進行Session複製使用。

 

2.2.3 AJP方式

        tomcat提供了ajp協議和httpd通訊。當不想tomcat的8080埠開放時,可以使用此方式,配置檔案:

Java程式碼  收藏程式碼
  1. <Proxy balancer://mycluster>  
  2.     BalancerMember ajp://127.0.0.1:8009 loadfactor=2 route=tomcat1  
  3.     BalancerMember ajp://127.0.0.1:7009 loadfactor=2 route=tomcat2  
  4.     ProxySet lbmethod=byrequests  
  5. </Proxy>  
  6. ProxyRequests Off  
  7. ProxyPass /test balancer://mycluster/ stickysession=JSESSIONID nofailover=Off  
  8. ProxyPassReverse /test balancer://mycluster/    

 

2.2.4 熱備份

        熱備份的實現很簡單,只需新增 status=+H 屬性,就可以把某臺伺服器指定為備份伺服器:

        此時請求總是流向 8080這個url ,一旦8080掛掉, Apache會檢測到錯誤並把請求分流給7080。Apache會每隔幾分鐘檢測一下8080的狀況,如果8080恢復,就繼續使用8080。

Java程式碼  收藏程式碼
  1. <Proxy balancer://mycluster>  
  2.     BalancerMember http://127.0.0.1:8080  
  3.     BalancerMember http://127.0.0.1:7080 status=+H   
  4.     ProxySet lbmethod=byrequests  
  5. </Proxy>  
  6. ProxyRequests Off  
  7. ProxyPass /test balancer://mycluster/ stickysession=JSESSIONID nofailover=Off  
  8. ProxyPassReverse /test balancer://mycluster/    

 

2.2.5 虛擬主機

        配置檔案

Java程式碼  收藏程式碼
  1. <VirtualHost *:80>    
  2.     ServerAdmin limingnihao@iteye.com  
  3.     ServerName localhost    
  4.     ServerAlias localhost    
  5.     <Proxy balancer://mycluster>  
  6.         BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=tomcat1  
  7.         BalancerMember ajp://127.0.0.1:7009 loadfactor=1 route=tomcat2  
  8.         ProxySet lbmethod=bytraffic  
  9.     </Proxy>  
  10.     ProxyRequests Off  
  11.     ProxyPass /test balancer://mycluster/ stickysession=JSESSIONID nofailover=Off    
  12.     ProxyPassReverse /test balancer://mycluster/    
  13.     ErrorLog "logs/error.log"    
  14.     CustomLog "logs/access.log" common    
  15. </VirtualHost>  

 

2.2.6 監控功能

        可新增以下配置,可以檢視監控頁面。通過訪問:http://127.0.0.1/balancer-manager。

配置檔案

Java程式碼  收藏程式碼
  1. <Location /balancer-manager>     
  2.     SetHandler balancer-manager   
  3.     Order Allow,Deny  
  4.     Allow from all   
  5. </Location>  

 

2.3 mod_jk

        Tomcat提供了專門的JK外掛來負責Tomcat和HTTP伺服器的通訊。應該把JK外掛安置在對方的HTTP伺服器上。當HTTP伺服器接收到客戶請求時,它會通過JK外掛來過濾URL,JK外掛根據預先配置好的URL對映資訊,決定是否要把客戶請求轉發給Tomcat伺服器處理。例如預先配置好所有"/*.jsp"形式的URL都由Tomcat伺服器來處理

        Tomcat提供了不同的JK外掛的實現模組。常用的JK外掛有:

        與Apache HTTPD伺服器整合:mod_jk.so

        與Windows IIS伺服器整合:isapi_redirect.dll

 

2.3.1 Workers.properties

        Workers實際上屬於Tomcat的連結器(Connector),代表了一個Tomcat例項,這個例項代表了由某種web伺服器來執行 servelet程式。舉例來說,我們可以使用某個伺服器,例如apache 來把servelet請求轉遞Tomcat程式(worker)來進行後臺處理。

        這樣我們就可以通過配置多個 Worker,讓不同的請求能夠被不同的Worker處理,這些Worker可以提供不同的開發環境,使得所有開發者可以共享一個伺服器而每個人都擁有自己的Worker。

        想要提供負載平衡,只要在同一臺機器上執行多個Tomcat Worker並且能夠在這些Worker之間分佈Web請求。

        Tomcat Workers都定義在一個叫做workers.properties屬性檔案之中,並且workers的說明告訴應該如何使用它們。

 

2.3.1.1 全域性配置項

指令 預設 說明
worker.list ajp13 由逗號分離開的worker名稱列表.
worker.maintain 60 輔助連線池保持間隔,以秒為單位。

 

2.3.1.2 連結指令

 

可配置一個通用的,然後每個work進行繼承。

指令 預設 說明
type ajp13 指定Tomcat伺服器 與Apache之間的通訊協議
host localhost Tomcat主機名或 IP 地址。
port 8009 Tomcat偵聽埠號。AJP13的預設埠是8009.
socket_connect_timeout socket_timeout*1000 套接字超時時間(毫秒為單位)。
socket_keepalive false 在未啟用的連線中傳送KEEP_ALIVE資訊(傳送間隔時間依賴於作業系統的設定,一般為120秒)
ping_mode -

探測tomcat的狀態策略。

C(content):連結模式,最後一次連結判斷是否超時。connect_timeout定義時間。若未定義使用ping_timeout。

P(prepost):請求模式,通過每次請求判斷是否超時。prepost_timeout定義時間。若未定義使用ping_timeout。

I(interval):間隔模式,定期檢測連結是否超時。connection_ping_interval間隔時間。ping_timeout超時時間。

A:以上所有的探測策略都將開啟。

connection_pool_size   JK會維護多個長連線做為一個池。它被用來設定每個WebServer(Apache)子程式的最大連線數。
connection_pool_minsize (pool+1)/2 連線池中維護最小的連線數。
connection_pool_timeout 0 在連連池中維護的非活動連線連續多少秒後被釋放。如果為0,則不釋放。
connection_acquire_timeout retries*retry_interval 獲取接連的超時。
lbfactor 1 負載平衡器權值

 

 

2.3.1.3 負載均衡設定

指令 預設 說明
balance_workers   逗號分隔的worker列表
sticky_session true 負載噴發採用Session貼上機制,按SessionID噴發請求。為了保障同一SessionID的請求被分發到同一臺伺服器上。
sticky_session_force false 如果為True, SessionID並不合法時則返回500錯誤,否則,丟掉Session並轉發到另外的機器上。

 

 

2.3.1.4 例項

Java程式碼  收藏程式碼
  1. # Define two status worker:  
  2. # - jk-status for read-only use  
  3. # - jk-manager for read/write use  
  4. worker.list=jk-status  
  5. worker.jk-status.type=status  
  6. worker.jk-status.read_only=true  
  7.   
  8. worker.list=jk-manager  
  9. worker.jk-manager.type=status  
  10.   
  11. # We define a load balancer worker  
  12. # with name "balancer"  
  13. worker.list=balancer  
  14. worker.balancer.type=lb  
  15. worker.balancer.error_escalation_time=0  
  16. worker.balancer.max_reply_timeouts=10  
  17. worker.balancer.sticky_session=true  
  18. worker.balancer.sticky_session_force=true    
  19.   
  20. # Now we add members to the load balancer First member is "tomcat1", most attributes are inherited from the template "worker.template".  
  21. worker.balancer.balance_workers=tomcat1  
  22. worker.tomcat1.reference=worker.template  
  23. worker.tomcat1.host=127.0.0.1  
  24. worker.tomcat1.port=8009  
  25. worker.tomcat1.activation=A  
  26.   
  27. # Second member is "tomcat2", most attributes are inherited from the template "worker.template".  
  28. worker.balancer.balance_workers=tomcat2  
  29. worker.tomcat2.reference=worker.template  
  30. worker.tomcat2.host=127.0.0.1  
  31. worker.tomcat2.port=7009  
  32. worker.tomcat2.activation=A  
  33.   
  34. # Finally we put the parameters  
  35. worker.template.type=ajp13  
  36. worker.template.socket_connect_timeout=5000  
  37. worker.template.socket_keepalive=true  
  38. worker.template.ping_mode=A  
  39. worker.template.ping_timeout=10000  
  40. worker.template.connection_pool_minsize=0  
  41. worker.template.connection_pool_timeout=600  
  42. worker.template.reply_timeout=300000  
  43. worker.template.recovery_options=3  

 

2.3.2 uriworkermap.properties

Java程式碼  收藏程式碼
  1. /*.do=balancer  
  2. /*.jsp=balancer  
  3.   
  4. #/*.gif=balancer  
  5. #/*.jpg=balancer  
  6. #/*.png=balancer  
  7. #/*.css=balancer  
  8. #/*.js=balancer  
  9. #/*.htm=balancer  
  10. #/*.html=balancer  
  11. #/*.txt=balancer  
  12.   
  13.   
  14. # Optionally filter out all .jpeg files inside that context  
  15. # For no mapping the url has to start with exclamation (!)  
  16.   
  17. !/servlets-examples/*.jpeg=lb  
  18.   
  19. #  
  20. # Mount jkstatus to /jkmanager  
  21. # For production servers you will need to  
  22. # secure the access to the /jkmanager url  
  23. #  
  24. /jk-manager=jk-manager  
  25. /jk-status=jk-status  

 

 

2.3.3 httpd.conf

        需要在中新增httpd的配置檔案中載入jk的配置檔案。

Java程式碼  收藏程式碼
  1. # 載入jk配置檔案  
  2. #Include conf/mod_jk.conf  

 

2.3.4 mod_jk.conf

Java程式碼  收藏程式碼
  1. # a versioned file name.  
  2. LoadModule jk_module modules/mod_jk_2.2_32.so  
  3. <IfModule jk_module>  
  4.     JkWorkersFile conf/workers.properties  
  5.     JkLogFile logs/mod_jk.log  
  6.     JkLogLevel info  
  7.     JkShmFile logs/mod_jk.shm  
  8.     # JkOptions +RejectUnsafeURI  
  9.     # JkStripSession On  
  10.     JkWatchdogInterval 60  
  11.     <Location /jk-status>  
  12.         # Inside Location we can omit the URL in JkMount  
  13.         JkMount jk-status  
  14.         Order deny,allow  
  15.         Deny from all  
  16.         Allow from 127.0.0.1  
  17.     </Location>  
  18.     <Location /jk-manager>  
  19.         # Inside Location we can omit the URL in JkMount  
  20.         JkMount jk-manager  
  21.         Order deny,allow  
  22.         Deny from all  
  23.         Allow from 127.0.0.1  
  24.     </Location>  
  25.     JkMountFile conf/uriworkermap.properties  
  26. JkMount /* balancer  
  27.     # JkUnMount /myapp/static/* *  
  28.     # JkUnMount /myapp/images/* balancer  
  29.     # SetEnvIf REQUEST_URI "\.(htm|html|css|gif|jpg|js)$" no-jk  
  30.     # SetEnvIf Request_URI "/transactions/" JK_REPLY_TIMEOUT=600000  
  31.     # SetEnvIf Request_URI "/reports/" JK_REPLY_TIMEOUT=0  
  32. </IfModule>  

 

 

2.3.5 編譯Linux版本JK

        在linux自行編譯jk時,需要以下步驟:

        1.解壓tomcat-connectors-1.2.37-src.tar.gz

        2.指定httpd的apxs檔案。他會自動將mod_jk.do生成到httpd的modules下。

Java程式碼  收藏程式碼
  1. ./configure --with-apxs=/opt/apache/httpd/bin/apxs  

 

2.4 Session同步方式

2.4.1 sticky模式

        前端balancer可實現sticky模式的session同步功能。利用負載均衡器的sticky模式的方式把所有同一session的請求都傳送到相同的Tomcat節點。這樣不同使用者的請求就被平均分配到叢集中各個tomcat節點上,實現負載均衡的能力。這樣做的缺點是沒有災難恢復的能力。一旦一個節點發生故障,這個節點上所有的session資訊全部丟失;同一使用者同一session只和一個webServer互動,一旦這個webserver發生故障,本次session將丟失,使用者不能繼續使用。

 

2.4.2 複製模式

        利用Tomcat session複製的機制使得所有session在所有Tomcat節點中保持一致。當一個節點修改一個session資料的時候,該節點會把這個 session的所有內容序列化,然後廣播給所有其它節點。這樣當下一個使用者請求被負載均衡器分配到另外一個節點的時候,那個節點上有完備的 session資訊可以用來服務該請求。這種做法的問題是對session哪怕有一點點修改,也要把整個sessions資料全部序列化 (serialize),還要廣播給叢集中所有節點,不管該節點到底需不需要這個session。這樣很容易會造成大量的網路通訊,導致網路阻塞。一般採 用這種方式,當Tomcat節點超過4個時候,整個叢集的吞吐量就不能再上升了;

        此方式是通過tomcat本身提供的功能,只需要修改server.xml檔案

        (1)修改Engine節點資訊: <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

        (2)去掉<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> 的註釋符

        (3)web.xml中增加 <distributable/>

 

2.5 Linux部署常見問題

        1.Failed to lookup provider 'shm' for 'slotmem': is mod_slotmem_shm loaded??

        載入mod_slotmem_shm.so就可以了。

 

        2.BalancerMember Can't find 'byrequests' lb method

        三種模式,需要載入三個so:

        mod_lbmethod_bybusyness.so

        mod_lbmethod_byrequests.so

        mod_lbmethod_bytraffic.so


http://limingnihao.iteye.com/blog/1934548

相關文章