概述html
Tomcat是一個徹底功能的HTTP服務器,可以獨立完成接收客戶端請求,處理請求,而後封裝響應報文響應客戶端。可是Tomcat的併發響應能力並不強,因此每每使用httpd或nginx服務器用於在前端接收客戶端請求,而後將請求調度至後端多個Tomcat節點。本文介紹的是利用httpd做爲反向代理服務器,實現Tomcat的負載均衡。
前端
httpd鏈接後端的Tomcat服務器,須要啓用對應的模塊。可以實現該功能的有兩個模塊:mod_proxy,mod_jk。mod_proxy是新出的模塊,只有在apache 2.2及以後的版本上纔可使用,可是相對於mod_jk模塊,它能夠提供更豐富的功能和安全性。
java
實現過程node
拓補圖:
linux
實驗環境:nginx
httpd:192.168.1.116web
Tomcat node1:192.168.1.106算法
Tomcat node2:192.168.1.127apache
在Tomcat node1和node2上安裝JDK和tomcat,完成環境變量的配置(192.168.1.106和192.168.1.127上完成)。vim
安裝jdk:
[root@node1 ~]# rpm -ivh jdk-7u9-linux-x64.rpm [root@node1 ~]# cd /usr/java/ [root@node1 java]# ll total 4 lrwxrwxrwx 1 root root 16 Sep 1 07:56 default -> /usr/java/latest drwxr-xr-x 10 root root 4096 Sep 1 07:56 jdk1.7.0_09 lrwxrwxrwx 1 root root 21 Sep 1 07:56 latest -> /usr/java/jdk1.7.0_09
在/usr/java目錄下有個latest連接文件指向最新的JDK。配置環境變量時直接使用此路徑。
配置環境變量:
[root@node1 ~]# vim /etc/profile.d/java.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin:$PATH ################################# [root@node1 ~]# . /etc/profile.d/java.sh
安裝tomcat:
[root@node1 ~]# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/
環境變量配置:
[root@node3 local]# cd /usr/local [root@node3 local]# ln -sv apache-tomcat-7.0.42/ tomcat `tomcat' -> `apache-tomcat-7.0.42/' [root@node1 ~]# vim /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=$CATALINA_HOME/bin:$PATH #################################### [root@node1 ~]# . /etc/profile.d/tomcat.sh
爲tomcat提供服務腳本:
#!/bin/sh # Tomcat init script for Linux. # # chkconfig: 2345 96 14 # description: The Apache Tomcat servlet/JSP container. # JAVA_OPTS='-Xms64m -Xmx128m' JAVA_HOME=/usr/java/latest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME case $1 in start) exec $CATALINA_HOME/bin/catalina.sh start ;; stop) exec $CATALINA_HOME/bin/catalina.sh stop;; restart) $CATALINA_HOME/bin/catalina.sh stop sleep 2 exec $CATALINA_HOME/bin/catalina.sh start ;; *) echo "Usage: `basename $0` {start|stop|restart}" exit 1 ;; esac
在代理服務器上編譯安裝apache2.4(192.168.1.116上)。
首先安裝apr和apr-util:
[root@www ~]# tar xf apr-1.5.0.tar.bz2 [root@www ~]# cd apr-1.5.0 [root@www apr-1.5.0]# ./configure --prefix=/usr/local/apr-1.5.0 [root@www apr-1.5.0]# make && make install ######################################### [root@www ~]# tar xf apr-util-1.5.3.tar.bz2 [root@www ~]# cd apr-util-1.5.3 [root@www apr-util-1.5.3]# ./configure --prefix=/usr/local/apr-util-1.5.3 --with-apr=/usr/local/apr-1.5.0/ [root@www apr-util-1.5.3]# make && make install
安裝httpd-2.4:
[root@www ~]# tar xf httpd-2.4.9.tar.bz2 [root@www ~]# cd httpd-2.4.9 [root@www httpd-2.4.9]# yum install pcre-devel -y [root@www httpd-2.4.9]# ./configure --prefix=/usr/local/apache --sysconfdir=/etc/httpd --e nable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-apr=/usr/l ocal/apr-1.5.0/ --with-apr-util=/usr/local/apr-util-1.5.3/ --enable-mpms-shared=all --with-m pm=event --enable-proxy --enable-proxy-http --enable-proxy-ajp --enable-proxy-balancer --enable-lbmethod-heartbeat --enable-heartbeat --enable-slotmem-shm --enable-slotmem -plain --enable-watchdog [root@www httpd-2.4.9]# make && make install
在編譯時須要添加這幾個參數來啓用對應的模塊:--enable-proxy --enable-proxy-http --enable-proxy-ajp --enable-proxy-balancer,最後的幾個參數用於實現httpd與後端tomcat之間的信號傳遞實現對其健康狀態的檢測。
安裝完成以後啓動服務查看對應的模塊是加載:
[root@www ~]# httpd -D DUMP_MODULES | grep proxy proxy_module (shared) ..... proxy_http_module (shared) ..... proxy_ajp_module (shared) proxy_balancer_module (shared)
httpd基於mod_jk模塊實現負載均衡
httpd能夠經過2種協議鏈接tomcat:http,ajp。tomcat啓動以後默認會監聽在2個端口:8080,8009。8080用於接收http請求,8009則用於接收ajp請求。mod_jk模塊僅支持使用ajp協議鏈接後端的tomcat。
因爲mod_jk模塊出現的較早,httpd默認不包括該模塊,須要經過apache的apxs函數編譯該模塊,安裝至apache的模塊目錄下。如果直接使用yum安裝的httpd,須要安裝httpd-devel以提供apxs函數。
在代理服務器節點上安裝mod_jk模塊(192.168.1.116上),tomcat-connectors-1.2.40-src.tar.gz即爲其源碼包。
[root@www ~]# tar xf tomcat-connectors-1.2.40-src.tar.gz [root@www ~]# cd tomcat-connectors-1.2.40-src/native/ [root@www native]# ./configure --with-apxs=/usr/local/apache/bin/apxs [root@www native]# make && make install
編輯配置文件,httpd-jk.conf默認在extra目錄下沒有,須要本身建立:
[root@www ~]# vim /etc/httpd/extra/httpd-jk.conf LoadModule jk_module modules/mod_jk.so #加載mod_jk模塊 JkWorkersFile /etc/httpd/extra/workers.properties #定義後端每一個tomcat實例的特性 JkLogFile logs/mod_jk.log #指定mod_jk模塊的日誌文件 JkLogLevel error #記錄日誌的級別(info, error, debug) JkMount /* lbcluster #將全部路徑代理至lbcluster這個worker JkMount /status/ stat #狀態信息頁
上述的配置參數中,jkWorkersFile用於指定保存了後端各個Tomcat工做屬性定義的配置文件。該配置文件的文件名一般是workers.properties,該文件中每個tomcat實例視爲一個worker,在apache啓動時mod_jk會讀取該配置文件的信息獲取每一個worker的配置信息。
workers.properties文件的配置格式:
worker.list = < a comma separated list of worker names >
worker. <worker name> .<property> = <property value>
worker.list爲worker列表,worker.<worker name>.<property>定義各個worker的名稱和屬性。
編輯workers.properties:
[root@www ~]# vim /etc/httpd/extra/workers.properties worker.list = lbcluster,stat worker.TomcatA.type = ajp13 #type指定worker的工做機制(定義一個tomcat實例) worker.TomcatA.host = 192.168.1.106 #host指定tomcat實例所在主機 worker.TomcatA.port = 8009 #port指定鏈接tomcat實例上的端口 worker.TomcatA.lbfactor = 5 #lbfactor指定該worker的權重 worker.TomcatB.type = ajp13 worker.TomcatB.host = 192.168.1.127 worker.TomcatB.port = 8009 worker.TomcatB.lbfactor = 5 worker.lbcluster.type = lb worker.lbcluster.method = B #指定調度的算法(根據負載狀況進行調度) worker.lbcluster.sticky_session = 0 #是否啓用sticksession worker.lbcluster.balance_workers = TomcatA, TomcatB worker.stat.type = status #用於顯示各worker的工做狀態
其中type屬性可定義3種工做機制:
ajp13 #定義一個tomcat實例
lb #用於負載均衡場景中,此worker包括多個tomcat實例
status #用於顯示各個worker工做狀態的特使worker
上述配置中定義了2個tomcat實例:TomcatA和TomcatB,lbcluster這個worker包括了這兩個tomcat實例,根據httpd-jk.conf中的定義(JkMount /* lbcluster)所用的請求都將使用定義的算法調度至TomcatA和TomcatB。實現負載均衡的算法有3種,默認爲「R」,根據用戶的請求個數進行調度,「T」根據已發送給各tomcat的流量進行調度,「B」根據負載狀況進行調度。
若將文件中的worker.lbcluster.sticky_session = 0改成1,則將實現session綁定,同一客戶端的全部後續請求都將直接調度至第一個訪問的worker。
在httpd的主配置文件中包含上述完成的配置文件:
[root@www ~]# vim /etc/httpd/httpd.conf ..... Include /etc/httpd/extra/httpd-jk.conf
從新加載服務:
[root@www ~]# httpd -t Syntax OK [root@www ~]# service httpd reload
上述的配置都在httpd節點上完成,而後在後端tomcat節點上添加對應的虛擬主機和測試頁面:
在Tomcat node1和node2上:
[root@node1 tomcat]# vim conf/server.xml ..... <Host name="www.xiaoxiao.com" appBase="/tomcat/webapps" unpackWARs="true" autoDeploy="true"> <Context path="/web" docBase="web"/> </Host> ###################################### [root@node1 ~]# cd /tomcat/webapps/ [root@node1 webapps]# mkdir web/WEB-INF/{classes,lib} -pv
在實現負載均衡時,若一個節點上有多個tomcat實例,這是須要在engine段加上jvmRoute參數,其值爲httpd節點上/etc/httpd/extra/workers.properties中對應的worker name。例如:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="a"> <Engine name="Catalina" defaultHost="localhost" jvmRoute="b">
node1上的測試頁面:
[root@node1 web]# vim index.jsp <%@ page language="java" %> <html> <head><title>Tomcat node1</title></head> <body> <h1><font color="blue">Tomcat node1</font></h1></p> </body> </html>
node2上的測試頁面:
[root@node2 web]# vim index.jsp <%@ page language="java" %> <html> <head><title>Tomcat node2</title></head> <body> <h1><font color="red">Tomcat node2</font></h1></p> </body> </html>
配置完成後啓動tomcat服務。訪問測試:
狀態頁面:
配置完成後其自動實現了後端服務器健康狀態的檢測,某臺服務器故障以後,可實時完成故障轉移。
httpd基於mod_proxy模塊實現負載均衡
mod_proxy模塊支持經過http和ajp協議鏈接後端的tomcat。
在httpd節點上,配置httpd的全局段:
<proxy balancer://lbcluster> BalancerMember ajp://192.168.1.106:8009 loadfactor=1 route=a#指定後端服務器及權重(loadfactor) BalancerMember ajp://192.168.1.127:8009 loadfactor=1 route=b ProxySet lbmethod=bytraffic #調度使用的算法 #ProxySet stickysession=JSESSIONID #是否啓用sticksession </proxy>
若使用http協議:
<proxy balancer://lbcluster1> BalancerMember http://192.168.1.106:8080 loadfactor=1 route=a BalancerMember http://192.168.1.127:8080 loadfactor=1 route=b #ProxySet stickysession=JSESSIONID ProxySet lbmethod=bytraffic </proxy>
在httpd節點上配置虛擬機:
[root@www httpd]# vim extra/httpd-vhosts.conf <VirtualHost *:80> ServerName www.xiaoxiao.com #虛擬主機名稱 ProxyVia Off #在響應報文中是否添加via首部,用於代表這是通過哪一個主機代理獲得的響應 ProxyRequests Off #關閉正向代理(正反向代理不該該同時啓用) ProxyPreserveHost On #代理將請求報文的host首部信息發送給後端服務器 ProxyPass / balancer://lbcluster/ #將請求代理至lbcluster包含的後端服務器 ProxyPa***everse / balancer://lbcluster/ <Location /status> #啓用狀態頁面 SetHandler balancer-manager Proxypass ! #指定此路徑不進行代理 Require all granted </Location> <Proxy *> Require all granted </Proxy> <Location / > Require all granted </Location> </VirtualHost>
在定義負載均衡的集羣時,經常使用的參數有lbmethod(調度算法),maxattempts(故障轉移次數),nofailover(是否失效轉移),stickysession(用於保持session)。這些參數能夠定義在全局段的proxy段中,以下:
<proxy balancer://lbcluster>
.......
ProxySet lbmethod=bytraffic
ProxySet stickysession=JSESSIONID
</proxy>
也能夠定義在banlancer://或ProxyPass後面。
lbmethod可以指定的算法有3種:
byrequests #根據權重進行輪詢
bytraffic #基於流量和權重進行調度
bybusyness #基於後端服務器的當前負載進行調度
在主配置文件中包含虛擬主機的配置文件,註銷mod_jk的配置文件:
Include /etc/httpd/extra/httpd-vhosts.conf #Include /etc/httpd/extra/httpd-jk.conf
後端的tomcat按照上一個案例進行配置,而後重啓httpd服務:
[root@www ~]# httpd -t Syntax OK [root@www ~]# service httpd reload
測試結果與上述一致,不一樣的是mod_proxy的狀態信息頁面功能更強大,能夠在頁面中對後端主機進行各屬性的配置。
能夠設置ProxySet stickysession=JSESSIONID將同一客戶端請求定向至同一臺後端服務器來維持session。根據我的的配置,貌似這個參數只能配置在全局段的proxy段中,且BalancerMember後面還須要添加route參數,才能生效。
<proxy balancer://lbcluster>
.......
ProxySet stickysession=JSESSIONID
</proxy>
在負載均衡過程當中,若是後端一個節點下線,則本來代理至該服務器的請求將調度至其餘節點,這時用戶的session將損壞。能夠關閉nofailover(nofailover = Off)不進行失效轉移,可以保證節點從新上線後,用戶可以訪問到原來的session。
.................^_^