準備三臺主機,一臺提供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="集羣列表中定義的名稱""。
分別在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,能正常訪問