實驗環境:Red Hat Enterprise Linux Server release 6.4
核心:Linux 2.6.32-358.el6.x86_64
下載下傳jdk和tomcat
Jdk
老版本:jdk-6u31-linux-x64-rpm.bin
http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-419409.html#jdk-6u45-oth-JPR
新版本:jdk-7u9-linux-x64.rpm
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
Tomcat :apache-tomcat-7.0.42.tar.gz
http://tomcat.apache.org/download-70.cgi
一、配置安裝tomcat,主機ip:172.16.5.12 hostname www.a.com
1、裝jdk
jdk-7u9-linux-x64.rpm直接rpm -ivh就行了
我使用jdk-6u31-linux-x64-rpm.bin安裝
# chmod +x jdk-6u31-linux-x64-rpm.bin
# ./jdk-6u31-linux-x64-rpm.bin
Press Enter to continue.....
直接ctrl+c退出
# cd /usr/java
# ls
default jdk1.6.0_31 latest
#vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/latest
export PATH=$JAVA_HOME/bin:$PATH
# . /etc/profile.d/java.sh
# java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04) 運作環境版本
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)
HotSpot(TM) Java虛拟機的名稱
2、裝tomcat
# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/
# cd /usr/local/
# ln -sv apache-tomcat-7.0.42 tomcat
# vim /etc/profile.d/tomcat.sh
export CATALINA_HOME=/usr/local/tomcat
export PATH=$CATALINA_HOME/bin:$PATH
# . /etc/profile.d/tomcat.sh
# cd /usr/local/tomcat/bin
# catalina.sh version
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/latest
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/7.0.42
Server built: Jul 2 2013 08:57:41
Server number: 7.0.42.0
OS Name: Linux
OS Version: 2.6.32-358.el6.x86_64
Architecture: amd64
JVM Version: 1.6.0_31-b04
JVM Vendor: Sun Microsystems Inc.
# catalina.sh start 啟動服務
# catalina.sh stop 停止服務
http://172.16.5.12:8080/
Tomcat 預設監聽8080端口

對Apache tomcat進行管理,需要配置 /usr/local/tomcat/conf/tomcat-users.xml
圖中有說明如何配置 ,需要加入兩組使用者
# vim /usr/local/tomcat/conf/tomcat-users.xml
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="qiufengsong" password="songqiufeng" roles="manager-gui,
admin-gui"/>
3、可以為tomcat寫一個服務腳本,讓他開機自動啟動
# vim /etc/rc.d/init.d/tomcat
#!/bin/sh
# Tomcat init script for Linux.
#
# chkconfig: 2345 96 14
# description: The Apache Tomcat servlet/JSP container.
JAVA_HOME=/usr/java/latest
CATALINA_HOME=/usr/local/tomcat
export JAVA_HOME CATALINA_HOME
exec $CATALINA_HOME/bin/catalina.sh $*
# chmod +x /etc/rc.d/init.d/tomcat
# chkconfig --add tomcat
# chkconfig tomcat on
# service tomcat stop
二、自定義一個虛拟主機,提供java程式頁面
下載下傳論壇程式JspRun!_6.0.0_GBK.zip
http://down.chinaz.com/soft/24848.htm
# mkdir -pv /web/app1
# unzip JspRun!_6.0.0_GBK.zip
# cp -rp upload/* /web/app1/
# vim /usr/local/tomcat/conf/server.xml
<Engine name="Catalina" defaultHost="www.a.com">
<Host name="www.a.com" appBase="/web/app1" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/web/app1"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="a_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
# service tomcat stop
# service tomcat start
浏覽器中輸入http://172.16.5.12/install.jsp
安裝即可
中間要為論壇建立一個資料庫管理者帳号,要在論壇綁定的資料庫中建立,當然,mysqld也是實作要裝好的。
三、以上面配置好的tomcat為基礎,配置Apache基于mod_jk代理連接配接tomcat
ajp(Apache jserv protocal)
Apache做代理時,mod_proxy子產品對http、https、ajp三種協定都支援,mod_jk則隻支援ajp協定。
對于http協定時,tomcat伺服器就是一個完全意義上的web伺服器。
對于ajp協定時,tomcat伺服器是伺服器端,代理是用戶端,需要連接配接器連接配接。需要加載mod_jk.so,需要安裝jk連接配接器來實作。
Apache做代理,支援ajp協定,可以禁用http協定,這樣就可以把tomcat完全隐藏在後端,使用者隻有通過Apache代理才能通路。
Nginx跟後端tomcat建立連接配接必須基于http協定。
以Apache伺服器做代理,進行配置
Ip:172.16.5.11
Hostname www.b.com
後端tomcat伺服器
Ip:172.16.5.12
Hostname www.a.com
Apache伺服器配置
# yum -y groupintall “ Development tools”“ Server Platform Development”
# yum -y install httpd
# yum -y install apr-devel apr-util-devel httpd-devel(包含apxs)
安裝jk連接配接器http://tomcat.apache.org/download-connectors.cgi
JK 1.2.37 Source Release tar.gz
# tar xf tomcat-connectors-1.2.37-src.tar.gz
# cd /root/tomcat-connectors-1.2.37-src/native
# ./configure --with-apxs=/usr/sbin/apxs
# make && make install
# ls /usr/lib64/httpd/modules/
# cd /etc/httpd/conf.d/
# vim mod_jk.conf
注釋:# Load the mod_jk
LoadModule jk_module modules/mod_jk.so #加載剛編譯的子產品
JkWorkersFile /etc/httpd/conf.d/workers.properties # jk連接配接器的工作屬性
JkLogFile logs/mod_jk.log # 日志
JkLogLevel debug #日志級别
JkMount /* TomcatA #加載的執行個體 與Apache代理的tomcat配置檔案中的執行個體相對應
JkMount /status/ stat1 #start1 在workers.properties 中定義
Workers.properties
# cd /etc/httpd/conf.d/
# vim workers.properties
worker.list=TomcatA,stat1
worker.TomcatA.port=8009 #ajp協定監聽的端口
worker.TomcatA.host=172.16.5.12 #tomcat伺服器 ip
worker.TomcatA.type=ajp13
worker.TomcatA.lbfactor=1
worker.stat1.type = status #狀态資訊
JkMount /status/ stat1----------》worker.stat1.type = status
TomcatA的解釋
在tomcat伺服器上編輯配置檔案
<Engine name="Catalina" defaultHost="www.a.com" jvmRoute="TomcatA">
這樣就實作了Apache基于ajp協定對tomcat代理了,重新開機httpd即可生效。
四、Apache基于mod_jk代理tomcat實作負載均衡
1、另開一台虛拟機,配置ip
# ifconfig eth0 172.16.5.13/16 up
# hostname www.c.com
2、安裝配置tomcat
3、在代理伺服器上修改配置檔案/etc/httpd/conf.d/workers.properties
4、便捷配置
# vim /etc/httpd/conf.d/workers.properties
worker.list = lbcluster1,stat1
worker.TomcatA.type = ajp13
worker.TomcatA.host = 172.16.5.12
worker.TomcatA.port = 8009
worker.TomcatA.lbfactor = 5
worker.TomcatB.type = ajp13
worker.TomcatB.host = 172.16.5.13
worker.TomcatB.port = 8009
worker.TomcatB.lbfactor = 5
worker.lbcluster1.type = lb
worker.lbcluster1.sticky_session = 0
worker.lbcluster1.method = R
worker.lbcluster1.balance_workers = TomcatA, TomcatB
worker.stat1.type = status
5、後端tomcat伺服器為
Ip:172.16.5.12 www.a.com
Ip:172.16.5.13 www.c.com
# Vim /usr/local/tomcat/conf/server.xml
<Engine name="Catalina" defaultHost="www.a.com" jvmRoute="TomcatA">
<Host name="www.a.com" appBase="/web/app2" unpackWARs="true"
autoDeploy="true">
<Context path="" docBase="/web/app2"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="a_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
# mkdir /web/app2
# vim /web/app2/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA </font></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>
# service tomcat stop
# service tomcat start
# Vim /usr/local/tomcat/conf/server.xml
<Engine name="Catalina" defaultHost="www.c.com" jvmRoute="TomcatB">
<Host name="www.c.com" appBase="/web/app2" unpackWARs="true"
autoDeploy="true">
<Context path="" docBase="/web/app2"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="a_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
# mkdir /web/app2
# vim /web/app2/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB </font></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>
# service tomcat stop
# service tomcat start
6、# vim /etc/httpd/conf.d/mod_jk.conf
# Load the mod_jk
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel debug
JkMount /* lbcluster1
JkMount /status/ stat1
# service httpd start
可以看到負載均衡
五、Apache基于mod_proxy代理tomcat實作負載均衡
加載mod_proxy,将之前配置的mod_jk.conf删除
負載一台伺服器
# cd /etc/httpd/conf.d/
# vim mod_proxy.conf
ProxyVia on
ProxyRequests Off
proxypreservehost off
<Proxy *>
order allow,deny
allow from all
</Proxy>
proxypass / http://172.16.5.11:8080/
proxypassreverse / http://172.16.5.11:8080/
<Location / >
order allow,deny
allow from all
</Location>
負載均衡
# cd /etc/httpd/conf.d/
# vim mod_proxy.conf
ProxyVia on
ProxyRequests Off
proxypreservehost off
<Proxy balancer://hotcluster>
BalancerMember http://172.16.5.11:8080/
BalancerMember http://172.16.5.12:8080/
ProxySet lbmethod=byrequests
</Proxy>
<Location /balancer>
SetHandler balancer-manager
proxypass !
Order Deny,Allow
Allow from all
</Location>
<Proxy *>
order allow,deny
allow from all
</Proxy>
proxypass / balancer://hotcluster/
proxypassreverse / balancer://hotcluster/
<Location / >
order allow,deny
allow from all
</Location>
注意:require all granted和order allow,deny;allow from all的差別
前者是2.4以後的版本,後者是2.2之前的版本
使用虛拟主機實作反向代理時,可以這樣配置完成虛拟主機的狀态資訊輸出
ProxyRequests Off
<proxy balancer://lbcluster1>
BalancerMember ajp://172.16.5.11:8009 loadfactor=1
BalancerMember ajp://172.16.5.12:8009 loadfactor=1
ProxySet lbmethod=bytraffic
</proxy>
<VirtualHost *:80>
ServerName localhost
ProxyVia On
ProxyPass / balancer://lbcluster1/ stickysession=JSESSIONID|jsessionid nofailover=On
ProxyPassReverse / balancer://lbcluster1/
<Location /balancer-manager>
SetHandler balancer-manager
Proxypass !
order allow,deny
allow from all
</Location>
<Proxy *>
order allow,deny
allow from all
</Proxy>
<Location / >
order allow,deny
allow from all
</Location>
</VirtualHost>
六、tomcat基于session複制的叢集
代理伺服器配置mod_proxy的代理配置
# vim /etc/httpd/conf.d/mod_proxy.conf
ProxyVia on
ProxyRequests Off
proxypreservehost off
<Proxy balancer://hotcluster>
BalancerMember http://172.16.5.11:8080/ loadfator=1
BalancerMember http://172.16.5.12:8080/ loadfator=1 #權重
ProxySet lbmethod=byrequests
</Proxy>
<Location /balancer>
SetHandler balancer-manager
proxypass !
order allow,deny
allow from all
</Location>
<Proxy *>
order allow,deny
allow from all
</Proxy>
proxypass / balancer://hotcluster/ stickysession=jsessionid
proxypassreverse / balancer://hotcluster/
<Location / >
order allow,deny
allow from all
</Location>
注意:代理服務可能出現的問題,使用80端口可以代理到後端,使用8080端口卻代理不到後端
ap_proxy_connect_backend disabling worker for (172.16.5.11)
Permission denied: proxy: HTTP: attempt to connect to 172.16.5.12:8080 (172.16.5.12) failed
錯誤原因:
代理伺服器的安全政策啟用了,關閉安全政策
解決方案:
# getenforce
Enforcing
# setenforce 0
# getenforce
Permissive
再次通路,發現可以代理到後端伺服器。
後端tomcat的配置
節點1:
# vim /usr/local/tomcat/conf/server.xml
</Host>
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.150.10.1"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="172.16.5.12"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/" watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
</Engine>
注意其中的多點傳播位址和ip位址,多點傳播位址要盡可能的使用自己定義的,ip位址是節點自己的位址
節點2:
</Host>
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.150.10.1"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="172.16.5.11"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/" watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
</Engine>
兩個節點的多點傳播位址一定要相同,IP位址都是各自自己的ip
我們在/usr/local/tomcat/webapps/中另外為tomcat建立站點目錄
# vim /usr/local/tomcat/webapps/testapp
# cd /usr/local/tomcat/webapps/testapp
# mkdir WEB-INF/{lib,classes} -pv (标準化配置)
# vim index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="blue">TomcatA </font></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>
# service tomcat stop
# service tomcat start
# cd /usr/local/tomcat/conf/
# cp web.xml ../webapps/testapp/WEB-INF/
# vim ../webapps/testapp/WEB-INF/web.xml
version="3.0">
<distributable />
兩個節點配置相似,參照配置即可。需要重點注意的是,如果是三台主機配置,代理伺服器有兩張網卡,一個公網ip,一個内網網關,内網節點配置的ip需要将網關指向代理伺服器的内網位址。如果是自己做實驗,沒有用到那麼多位址,也最起碼要保證内網位址有預設網關,否則tomcat伺服器起不來的。
實驗效果圖
七、以nginx做代理,實作動靜分離,動态的内容代理到tomcat,靜态的内容代理到另一台主機,隻需要在nginx上添加以下配置即可。
location ~ \.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js)$ {
proxy_pass http://172.16.5.13;
proxy_set_header X-Real-IP $remote_addr;
}
location ~ \.(jsp|do|css)$ {
proxy_pass http://172.16.5.12;這裡要注意對方端口,tomcat預設是8080
}
八、tomcat原理
tomcat是一個java程式的web平台,然而它又不是一個完整意義上的java EE(java企業級運作平台),是以,現如今很多企業使用開源元件如structs、spring和hibernate來建構複雜的應用。
tomcat是一個java程式的web平台,然而,它的運作需要借助一些類庫和工具,當然還有另外的環境機制,這些都是由jdk來實作的。可以說tomcat隻是一個java應用程式的容器,而站在它背後的jdk才是運作整個程式的核心。
Tomcat Server處理一個http請求的過程
假設來自客戶的請求為:
http://localhost:8080/wsota/wsota_index.jsp
1) 請求被發送到本機端口8080,被在那裡偵聽的Coyote HTTP/1.1 Connector獲得
2) Connector把該請求交給它所在的Service的Engine來處理,并等待來自Engine的回應
3) Engine獲得請求localhost/wsota/wsota_index.jsp,比對它所擁有的所有虛拟主機Host
4) Engine比對到名為localhost的Host(即使比對不到也把請求交給該Host處理,因為該Host被定義為該Engine的預設主機)
5) localhost Host獲得請求/wsota/wsota_index.jsp,比對它所擁有的所有Context
6) Host比對到路徑為/wsota的Context(如果比對不到就把該請求交給路徑名為""的Context去處理)
7) path="/wsota"的Context獲得請求/wsota_index.jsp,在它的mapping table中尋找對應的servlet
8) Context比對到URL PATTERN為*.jsp的servlet,對應于JspServlet類
9) 構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet或 doPost方法
10)Context把執行完了之後的HttpServletResponse對象傳回給Host
11)Host把HttpServletResponse對象傳回給Engine
12)Engine把HttpServletResponse對象傳回給Connector
13)Connector把HttpServletResponse對象傳回給客戶browser