基於Apache和tomcat實現負載均衡

 一、環境準備

準備三臺主機,一臺提供httpd環境,另兩臺提供tomcat環境。css

 

主機規劃:html

 

主機名:httpd IP地址:192.168.200.112提供httpd服務前端

 

主機名:TomcatA IP地址:192.168.200.113提供tomcat服務java

 

主機名:TomcatB IP地址:192.168.200.114提供tomcat服務web

 

jdk與tomcat的安裝請參照博文: https://www.cnblogs.com/2567xl/p/11527015.html
apache

 

對tomcat的配置的說明:vim

 

以mod_jk的方式來實現反向代理tomcat,並實現負載均衡,httpd與tomcat的鏈接再也不是是http協議,而是採用ajp協議,在httpd與tomcat通訊時沒法查證是否能像http協議同樣能傳遞「Host 」主機頭,若是能,那tomcat就就能夠單獨配置一個虛擬主機來接收帶主機頭的請求,這樣就不用去更改tomcat的默認主機,如此客戶端就能夠只經過主機名來訪問咱們的站點,而不須要加上一個URI。但我在測試時沒有測試出ajp協議能傳遞主機頭,因此我修改了tomcat的默認主機指向咱們本身部署的站點。後端

 

1.一、修改tomcat默認網站主目錄及jvmRoute配置:centos

 

[root@TomcatA conf]# pwdapi

/usr/local/tomcat/conf

[root@TomcatA conf]# vim server.xml

<Host name="localhost" appBase="/tomcat/webapps"

            unpackWARs="true" autoDeploy="true">

            <Context path="" docBase="test" />

......

</Host>

#像以上修改後個人站點目錄就是在「/tomcat/webapps/test」這個目錄。

TomcatA 和 TomcatB 開啓的端口不能同樣

在集羣環境中必須在Engine容器中指定jvmRoute參數:

 

[root@TomcatA conf]# vim server.xml

<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcata">

#在TomcatB主機上也要設定jvmRoute。

1.二、準備咱們的應用:

 

JSP程序的目錄結構有其特有的格式,先來看一下默認的站點目錄的格式

 

[root@TomcatA webapps]# pwd

/usr/local/tomcat/webapps

[root@TomcatA webapps]# tree -L 2 -d

.

├── docs

│ ├── api

│ ├── appdev

│ ├── architecture

│ ├── config

│ ├── elapi

│ ├── funcspecs

│ ├── p_w_picpaths

│ ├── jspapi

│ ├── servletapi

│ ├── tribes

│ ├── WEB-INF

│ └── websocketapi

├── examples

│ ├── jsp

│ ├── servlets

│ ├── WEB-INF

│ └── websocket

├── host-manager

│ ├── p_w_picpaths

│ ├── META-INF

│ └── WEB-INF

├── manager

│ ├── p_w_picpaths

│ ├── META-INF

│ └── WEB-INF

├── ROOT

│ └── WEB-INF

└── test

可見每一個應用中都有一個WEB-INF這樣的一個目錄,此目錄下有一個web.xml文件,不用修改此文件,把WEB-INF這個目錄直接複製到新的應用目錄下,再把咱們的應用放進來就能夠了。

 

[root@TomcatA conf]# cp -r /usr/local/tomcat/webapps/ROOT/WEB-INF /tomcat/webapps/test/

[root@TomcatA conf]# vim /tomcat/webapps/test/index.jsp #以一個測試文件做爲個人項目

<%@ page language="java" %>

<html>

 <head><title>TomcatA</title></head>

 <body>

  <h1><font color="red">TomcatA </h1>

  <table align="centre" border="1">

   <tr>

    <td>Session ID</td>

  <% session.setAttribute("abc","abc"); %>

    <td><%= session.getId() %></td>

   </tr>

   <tr>

    <td>Created on</td>

    <td><%= session.getCreationTime() %></td>

   </tr>

  </table>

 </body>

</html>

[root@TomcatB conf]# ls /tomcat/webapps/test/

index.jsp WEB-INF

[root@TomcatB conf]# service tomcat restart #從新啓動tomcat便可生效

兩臺tomcat應用服務器都提供上邊一樣一個測試項目,只是index.jsp中的"TomcatA"更改爲「TomcatB」而已。

 

二、mod_jk配置

 

將 tomcat-connector 中的 mod_jk.so 拷貝到 apache/modules 下。

 

後端的tomcat準備好了,如今來看看前端的httpd中的mod_jk模塊的相應配置。

 

mod_jk是apache的一個單獨的項目,centos 6.4中默認yum源中的rpm包中沒有編譯此模塊,因此須要本身編譯安裝,編譯安裝也比較簡單,請參照:http://zhaochj.blog.51cto.com/368705/1641939

 

配置mod_jk主要有三個文件,mod_jk.conf、workers.properties、uriworkersmap.properties,這三個文件名字能夠自定義。

 

因httpd的主配置文件添加   include "/usr/local/apache/conf/mod_jk.conf"  ,因此上邊的mod_jk.conf會被加載進主配置文件中,這樣把功能性的模塊配置分隔開,可防止主配置文件過於冗長,以便於管理。

 

本身安裝編譯的Apache  就用本身的路徑  例如:/usr/local/apache/conf/mod_jk.conf

 

[root@httpd conf.d]# pwd

/etc/httpd/conf.d

[root@httpd conf.d]# vim mod_jk.conf

LoadModule jk_module modules/mod_jk.so

JkWorkersFile /etc/httpd/conf.d/workers.properties

JkMountFile /etc/httpd/conf.d/uriworkersmap.properties

JkLogFile logs/mod_jk.log

JkLogLevel warn #在調試時能夠把日誌級別設置爲info或debug

#JkMount /* lbcluster1

#JkMount /jkstatus stat

#workers.properties與uriworkersmap.properties兩個文件分別經過JkorkersFile和JkMonutFile兩個指令關聯起來,若是不想啓用uriworkersmap.properties這個文件,那直接在mod_jk.conf文件加「JkMount」這樣的指令便可,這個指使至關於使用proxy_mod模塊中的ProxyPass指令同樣。

[root@httpd conf.d]# vim workers.properties

#tomcata ,這裏定義tomcata主機

worker.tomcata.host=192.168.0.201

worker.tomcata.port=8009

worker.tomcata.type=ajp13

worker.tomcata.lbfactor=2

#tomcab ,這裏定義tomcatb主機

worker.tomcatb.host=192.168.0.202

worker.tomcatb.port=8010

worker.tomcatb.type=ajp13

worker.tomcatb.lbfactor=2

#定義主機權重

#balance ,定義集羣屬性

worker.list=lbcluster1,stat

worker.lbcluster1.type=lb

worker.retries=3

worker.method=R

worker.lbcluster1.sticky_session=0

#這裏定義session信息的粘滯、綁定,零表明不綁定,1表明綁定

worker.lbcluster1.balance_workers=tomcata,tomcatb

#monitor status ,定義狀態輸出於是

worker.stat.type=status

worker中各參數、屬性解釋:

 

workers.properties文件通常由兩類指令組成,一是mod_jk能夠鏈接的各worker名稱列表,二是每個worker的屬性配置信息。

 

語法爲:

 

worker.list = < a comma separated list of worker names > 即用逗號分隔的各worker的名稱(後端tomcat的JVMRoute名稱)

 

worker. <worker name> .<property> = <property value>

 

回想一下mod_jk這個模塊能實現哪些功能,能以ajp協議反向代理tomcat,能輸出一個監控模塊自己工做的監控頁面,還能實現負載均衡。因此根據其工做類型不一樣,worker有不一樣的工做類型,定義方式爲worker.<worker name>.type=<類型>,常見的類型就是上邊說的三種:

 

a)、ajp13,此類型表示當前worker爲一個運行着的Tomcat實例

 

b)、lb,lb即load balancing,專用於負載均衡場景中的woker,此worker並不真正負責處理用戶請求,而是將用戶請求調度給其它類型爲ajp13的worker

 

c)、status,用於顯示分佈式環境中各實際worker工做狀態的特殊worker,它不處理任何請求,也不關聯到任何實際工做的worker實例。

 

worker其它常見的屬性說明:

 

host:Tomcat 的worker實例所在的主機;

 

port:Tomcat 實例上AJP1.3鏈接器的端口;

 

connection_pool_minsize:最少要保存在鏈接池中的鏈接的個數;默認爲pool_size/2;

 

connection_pool_timeout:鏈接池中鏈接的超時時長;

 

mount:由當前worker提供的context路徑,若是有多個則使用空格格開;此屬性能夠由JkMount指令替代;

 

retries:錯誤發生時的重試次數;

 

socket_timeout:mod_jk等待worker響應的時長,默認爲0,即無限等待; 

 

socket_keepalive:是否啓用keep alive的功能,1表示啓用,0表示禁用;

 

lbfactor:worker的權重,能夠在負載均衡的應用場景中爲worker定義此屬性;

 

另外,在負載均衡模式中,專用的屬性還有:

 

balance_workers:用於負載均衡模式中的各worker的名稱列表,須要注意的是,出如今此處的worker名稱必定不能在任何worker.list屬性列表中定義過,而且worker.list屬性中定義的worker名字必須包含負載均衡worker。具體示例請參見後文中的定義。

 

method:能夠設定爲R、T或B;默認爲R,即根據請求的個數進行調度;T表示根據已經發送給worker的實際流量大小進行調度;B表示根據實際負載狀況進行調度。

 

sticky_session:在將某請求調度至某worker後,源於此址的全部後續請求都將直接調度至此worker,實現將用戶session與某worker綁定。默認爲值爲1,即啓用此功能。若是後端的各worker之間支持session複製,則能夠將此屬性值設爲0。

 

[root@httpd conf.d]# vim uriworkersmap.properties

/*=lbcluster1

/jkstatus=stat

!/*.jpg=lbcluster1

!/*.gif=lbcluster1

!/*.png=lbcluster1

!/*.bmp=lbcluster1

!/*.html=lbcluster1

!/*.htm=lbcluster1

!/*.css=lbcluster1

!/*.js=lbcluster1

#這個文件裏定義了向後轉發的規則,訪問網站根下的全部資源都交給集羣lbcluster1來處理,而一些靜態文件就httpd本地處理了。

最後從新啓動httpd服務,確認mod_jk模塊正確加載:

 

[root@httpd conf.d]# service httpd restart

[root@httpd conf.d]# tail /var/log/httpd/mod_jk.log

[Tue May 05 17:02:04.876 2015] [8161:140100989429728] [info] init_jk::mod_jk.c (3383): mod_jk/1.2.40 initialized

#先把日誌級別設置成info,能看到上邊的信息就證實mod_jk模塊已正確加載。

三、測試

 

經過訪問httpd(192.168.0.200)主機來測試看可否能訪問到咱們部署在TomcatA和TomcatB上的項目,

先是訪問到了TomcatA主機,再一刷新又訪問到了TomcatB主機,這是由於在workers.properties文件中的worker.lbcluster1.sticky_session的值是「0」,表示沒有啓用session綁定功能,若是咱們部署的部署只是供瀏覽,那沒什麼問題,若是站點是一個須要用戶登錄的站點,那被mod_jk分發到不一樣的的後端tomcat上時會要求用戶從新登錄的,因此在這種場景下應該設置成「1」,啓用session綁定功能。

 

四、總結

 

利用apache的mod_jk模塊實現tomcat的負載均衡時apache與tomcat的通訊是採用ajp協議,因此整個環境測試好後,可把後端的兩臺tomcat服務器的http的connector禁用掉,在負載均衡集羣環境下後端的各tomcat服務器在server.xml主配置文件中的Engine容器中必定要加上「jvmRote="集羣列表中定義的名稱""。

 

PS:  測試

分別在2個tomcat下創建項目test1,並新增andashu.jsp,內容以下:

<%

 

System.out.println("===========");

 

%>

 

分別訪問2個tomcat,http://IP:8081/test1/andashu.jsp 以及http://10.14.133.204:8080/test1/andashu.jsp,若是2個tomcat的日誌catalina.out裏 都打印出===========,證實2個tomcat訪問都ok

 

分別啓動apache worker2,worker3,用不一樣的瀏覽器或者不一樣的機器分別訪問http://IP/test1/andashu.jsp,若是若是2個tomcat的日誌catalina.out裏 都打印出===========,證實負載均衡搭建成功(這裏要用不一樣瀏覽器或者不一樣機器訪問)

 

試節點故障,隨便停掉其中的一臺tomcat,繼續訪問http://IP/test1/andashu.jsp,能正常訪問

相關文章
相關標籤/搜索