基於apache實現tomcat集羣的負載均衡

概述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

wKioL1XupQCg_y6hAABw3pq4sOU122.jpg

實驗環境: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服務。訪問測試:

wKiom1XntzPi1szAAAC-3V3PpFY844.jpg


wKioL1XnuXmAshD-AADJmZAczBE810.jpg


狀態頁面:

wKioL1XnuiTArO66AAJv1jRuGIY653.jpg

配置完成後其自動實現了後端服務器健康狀態的檢測,某臺服務器故障以後,可實時完成故障轉移。


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的狀態信息頁面功能更強大,能夠在頁面中對後端主機進行各屬性的配置。

wKioL1XnyR3R5pr9AAO1w_swfI4228.jpg


wKiom1XnxyryjobSAAF6qyBhhc0502.jpg

能夠設置ProxySet stickysession=JSESSIONID將同一客戶端請求定向至同一臺後端服務器來維持session。根據我的的配置,貌似這個參數只能配置在全局段的proxy段中,且BalancerMember後面還須要添加route參數,才能生效。

<proxy balancer://lbcluster>

.......

 ProxySet stickysession=JSESSIONID 

</proxy>

在負載均衡過程當中,若是後端一個節點下線,則本來代理至該服務器的請求將調度至其餘節點,這時用戶的session將損壞。能夠關閉nofailover(nofailover = Off)不進行失效轉移,可以保證節點從新上線後,用戶可以訪問到原來的session。

.................^_^

相關文章
相關標籤/搜索