注意:本篇博文涉及的知識內容如下,實驗中所用的系統環境爲RHEL6.4。
1.Java基礎知識講解
2.Tomcat的安裝和實現
3.通過apache的mod_proxy模塊代理並實現Tomcat負載均衡
4.基於Tomcat集羣的網上商城的實現
------------------------------------------------------------------------------------------
1.Java基礎知識講解
1.1.Java相關的體系結構
1.Java程序設計語言
2.Java class 文件格式
3.Java 應用編程接口
4.Java 虛擬機
1.2.Java運行環境
用Java語言編譯源代碼,把它編譯成Java Class文件,然後在Java VM中運行class文件;當編寫程序時,通過調用類(Java API)中的方法來訪問系統資源,而當程序運行時,它通過調用class文件中實現了Java API的方法也滿足程序的Java API調用。Java VM和Java API一起組成了一個“平臺”,所有Java程序都在其上編譯和運行,因此,它們有時也被稱作Java運行時環境。
相關實現模型如下:
1.3.JVM(虛擬機)運行數據區域
1.4.相關術語概念
1.JVM : Java虛擬機 主要包含類加載器和相關的執行引擎
2.JDK : Java開發工具 主要包括Java運行環境,和javac編輯器及相關的API
3.Java SE : 包含JDK和一些核心的JAVA API
4.Java EE : 由Java SE 和一些Java企業級的API組成
1.5.web容器(Tomcat)
當JSP應用程序第一次調用之後,JSP會被編譯成一個servlet類,後續的操作直接使用此類,從而避免了每次調用的都要重新分析和編譯。因此,類似servlet,JSP的執行需要在container中完成JSP的container跟servlet的container基本相同。但在JSP執行之前,需要一些額外的步驟如與servlet代碼建立會話等。Tomcat包含了一個叫做Catalina的Servlet container(執行servlet和編譯過的JSP)和一個JSP編譯器(Jasper)。
事實上,一個包含了JSP編譯器和Servlet容器的應用程序組合通過被稱作Web容器。
2.Tomcat的安裝和實現
2.1.JDK的安裝
目前開源的JDK有ApacheHarmony, OpenJDK, SunJDK等。下載鏈接:
http://www.oracle.com/technetwork/java/javase/downloads/index.html
[root@TomcatA ~]# rpm -ivh jdk-7u9-linux-x64.rpm [root@TomcatA ~]# ll /usr/java/ total 4 lrwxrwxrwx 1 root root 16 Oct 3 19:52 default -> /usr/java/latest drwxr-xr-x 10 root root 4096 Oct 3 19:52 jdk1.7.0_09 lrwxrwxrwx 1 root root 21 Oct 3 19:52 latest ->/usr/java/jdk1.7.0_09 [root@TomcatA ~]# vim /etc/profile.d/java.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin:$PATH [root@TomcatA ~]# . /etc/profile.d/java.sh [root@TomcatA ~]# java -version java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode) [root@TomcatA ~]#
2.2.Tomcat安裝(JAVA程序) --> 解壓部署
官方網站: http://tomcat.apache.org/
[root@TomcatA ~]# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/ [root@TomcatA ~]# cd /usr/local/ [root@TomcatA ~]# ln -sv apache-tomcat-7.0.42 tomcat `tomcat' -> `apache-tomcat-7.0.42 [root@TomcatA ~]# vim /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat exportPATH=$CATALINA_HOME/bin:$PATH [root@TomcatA ~]# catalina.sh --help #顯示相關的命令選項 [root@TomcatA ~]# jps #顯示當前系統運行的JVM程序
2.3.編輯啓動服務腳本:
[root@TomcatA ~]# 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_OPTS='-Xms64m -Xmx256m' #設置JAVA運行時的內容大小 JAVA_HOME=/usr/java/latest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME exec $CATALINA_HOME/bin/catalina.sh $*
2.4.配置文件介紹:
Tomcat的配置文件默認存放在$CATALINA_HOME/conf目錄中,主要有以下幾個:
1.server.xml: Tomcat的主配置文件,Service, Connector, Engine, Realm, Valve,Hosts主組件的相關配置信息;
2.web.xml:遵循Servlet規範標準,用於配置servlet,併爲所有的Web應用程序提供包括MIME映射等默認配置信息;
3.tomcat-user.xml:Realm認證時用到的相關角色、用戶和密碼等信息;Tomcat自帶的manager默認情況下會用到此文件;在Tomcat中添加/刪除用戶,爲用戶指定角色等將通過編輯此文件實現;
4.catalina.policy:Java相關的安全策略配置文件,在系統資源級別上提供訪問控制的能力;
5.catalina.properties:Tomcat內部package的定義及訪問相關的控制,也包括對通過類裝載器裝載的內容的控制;Tomcat6在啓動時會事先讀取此文件的相關設置;
6.ogging.properties:Tomcat6通過自己內部實現的JAVA日誌記錄器來記錄操作相關的日誌,此文件即爲日誌記錄器相關的配置信息,可以用來定義日誌記錄的組件級別以及日誌文件的存在位置等;
7.context.xml:所有host的默認配置信息;
2.5.主配置文件 /usr/local/tomcat/conf/server.xml中常用的組件介紹:
Server組件:使tomcat服務器啓動一個實例
Service組件:關聯一個引擎和此引擎相關的連接器
Connector組件:爲引擎設置相關的連接器以接受客戶端的訪問請求
Engine組件:是servlet處理器的一個實例,即servlet引擎
Host組件:位於engine容器中用於接收請求並進行相應處理的主機或虛擬主機
Context組件:在某些意義上類似於apache中的路徑別名,一個Context定義用於標識tomcat實例中的一個Web應用程序
其餘組建和詳細參數信息請參考官方文檔,在這裏我就不再敘述。
2.6.應用程序目錄的結構:
/WEB-INF/web.xml:包含當前webapp的deploy描述符,如所有的servlets和JSP等動態文件的詳細信息,會話超時時間和數據源等;因此,其也通常用於定義當前webapp特有的資源;
/WEB-INF/classes: 包含所有服務器端類及當前應用程序相關的其它第三方類等;
/WEB-INF/lib: 包含JSP所用到的JAR文件;
2.7.簡單測試:
我們將上述connector的端口由默認的8080修改爲80,重啓tomcat服務器並進行簡單的訪問測試
3.通過apache的mod_proxy模塊代理並實現Tomcat負載均衡
3.1.實驗拓撲環境
3.2.簡單應用程序的部署
在這裏我們使用默認的/usr/local/tomcat/webapps/目錄直接部署虛擬目錄實現,而不再使用單獨的虛擬主機定義。配置簡單實現如下:
TomcatA:
[root@TomcatA ~]# cd /usr/local/tomcat/webapps/ [root@TomcatA webapps]# mkdir -pv test/WEB-INF/{classes,lib} [root@TomcatA webapps]# vim test/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>
TomcatB:
主要配置同TomcatA相同,只需要設置不同的主頁文件:
[root@TomcatA webapps]# vim test/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>
#配置完成之後,利用之前提供的腳本重啓兩臺tomcat服務器。
Apache:利用mod_proxy模塊實現負載均衡。
1.啓動RHEL6.4上默認的httpd服務。
2.新添加配置文件如下:
[root@apache ~]# vim /etc/httpd/conf.d/mod_proxy.conf ProxyVia on ProxyRequests Off #關閉正向代理 ProxyPreserveHost Off <Proxy balancer://xkun> #定義代理的後端real server BalancerMemberajp://192.168.21.1:8009 loadfactor=1 BalancerMemberajp://192.168.21.2:8009 loadfactor=1 ProxySetlbmethod=byrequests </Proxy> <Location /xkun> #狀態檢測的實現 SetHandler balancer-manager #調用處理模塊 Proxypass ! #不向後方代理 Order allow,deny #定義訪問權限 Allow from all #建議在實際生產中做好訪問控制 </Location> <Proxy *> #相關反向代理的權限控制 Order allow,deny Allow from all </Proxy> ProxyPass / balancer://xkun/ #設置代理路徑的映射管理 ProxyPa***everse / balancer://xkun/ <Location / > #定義相關的訪問控制策略 Order allow,deny Allow from all </Location>
3.重啓所有服務器進行訪問測試
#注意:重啓之前,最好編輯/etc/sysctl.conf文件打開ip_forward轉發
# service httpd start
3.3.簡單測試如下:
1.查看狀態信息
2.查看部署好的jsp程序
3.4.實驗總結:
1.通過上述實驗我們實現瞭如何利用apache的mod_proxy模塊實現了tomcat的負載均衡。
2.雖然本次實現了tomcat負載均衡但我們發現session無法得到保持。我將在一下敘述中進行實現
3.5.基於內存複製實現tomcat集羣中的session共享
1.分別在TomcatA和TomcatB服務器的主配置文件上添加如下信息(只需修改各自的receiver):
# vim server.xml #添加在引擎容器中以實現所有虛擬主機的共享
<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.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" <!--注意修改地址爲自己的網卡IP --> 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=""/> <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>
2.完成之後,還需要在應用程序部署目錄中添加下配置文件並修改,實現兩臺tomcat的內存共享:
[root@TomcatA ~]# cd /usr/local/tomcat/conf/ [root@TomcatA conf]# cp -a web.xml ../webapps/test/WEB-INF/ # 修改web.xml文件在 web-app 容器中添加如下行: <distributable />
3.同樣在TomcatB上進行同樣的配置,添加相同的配置文件。只是需要將地址修改爲自己網卡地址,在上述代碼中已給有提示。關於server.xml中添加集羣相關的配置文件詳解請參考官方文檔。
4.同啓重啓後端的兩臺tomcat服務器,並進行訪問測試結果如下:
我們發現無論如何刷新,session id的信息都不會再改變。至此,我們完成了如何利用apache的mod_proxy模塊實現tomcat服務器的負載均衡,同時我們也完成了tomcat內存共享集羣的實現。下面我將通過一個網上購物商城實例來給大家做進一步的講解和總結。
4.基於Tomcat集羣的網上商城的實現
4.1.實驗拓撲環境:
4.2.shop應用程序的部署
注意:同樣在這裏我們使用默認的/usr/local/tomcat/webapps/目錄直接部署虛擬目錄實現。
下載開源網上購物商城程序包如下:shopxx-a5-Beta.zip
下載路徑:
簡單配置如下:
1.TomcatA:
[root@TomcatA ~]# unzip shopxx-a5-Beta.zip [root@TomcatA ~]# cd shopxx-v3.0-Beta/ [root@TomcatA shopxx-v3.0-Beta]# ls shopxx-3.0Beta/ admin favicon.ico install META-INF robots.txt upload changelog.txt index.jsp license.html resources shopxx.txt WEB-INF [root@TomcatA shopxx-v3.0-Beta]# mv shopxx-3.0Beta /usr/local/tomcat/webapps/shop
2.MySQL: (安裝方法我就不再敘述,可以參考之前的博客)
mysql> create database shopxx; mysql> create user 'showuser'@'%' identified by'showpass'; mysql> grant all on shopxx.* to 'showuser'@'%';
3.Apache: (代理配置文件和上一個實現相同,這裏就不再給出)
先註釋BalancerMemberajp://192.168.21.2:8009 loadfactor=1
4.然後訪問:http://172.16.21.100/shop 根據提示進行安裝:直至出現如下界面:
5.TomcatB: 將TomcatA的關於shop/目錄的配置複製到TomcatB中。
# scp -rp shop 192.168.21.2:/usr/local/tomcat/webapps/[email protected]
問題:在購物商城的實現過程中,我也遇見了session無法保持的情況。即同一用戶再次登錄時購物車的商品有可能爲空。
解決方案:利用tomcat集羣實現內存共享,這在上面的案例中也有介紹。
同樣修改配置文件server.xml添加上述內容(在上面我已經做過詳細的說明)。
同時修改配置文件#vim shop/WEB-INF/web.xml添加如下一行
<distributable />
同時啓動tomcat服務器。
當端口啓動時,再次訪問站點主頁進行測試http://172.16.21.100/shop
註冊用戶並將商品加入購物車。多次執行退出登錄操作。我們發現購物車的商品一直存在:
無論我如何刷新,登錄用戶的購物車信息都會存在。實現了後端集羣的信息共享。至此基於tomcat的集羣的相關實現我已經寫完了。如果大家有什麼疑問歡迎和我交流。
QQ:572807025 郵箱:[email protected]
注意:本次實驗所用的系統環境爲RHEL6.4,整個實驗過程全部由筆者親自實踐。筆者將會在後續的博客中陸續更新:如何利用HAProxy代替apache實現反向代理並實現動靜分離,並利用keepalived實現HAProxy的高可用。同時也會將HAProxy替換成Varnish實現相應的反向代理和緩存。通過對多種web架構的實現並進行相應的壓力測試,比較各種架構的性能好壞。