tomcat7+apache(mod_jk/mod_proxy)負載均衡

操作目的
前端的web服務器接收請求,若是jsp頁面,就通過mod_jk/mod_proxy連接器轉發至後端的tomcat服務器,並實現tomcat的負載均衡,session會話的保持



簡單拓撲圖
 

準備工作:
兩臺服務器
172.16.220.11  安裝httpd tomcat  把web服務器和tomcat做在一臺服務器上 主機名爲tomcat1
172.16.220.12   安裝tomcat     做爲tomcat服務器   主機名爲tomcat2
同步兩臺服務器的時間
hwclock -s

一、準備兩臺服務器

  1. tomcat1  
  2.  編譯安裝httpd  
  3. 準備的包apr-1.4.6.tar.bz2 apr-util-1.4.1.tar.bz2 httpd-2.4.2.tar.bz2  
  4.  
  5. 安裝apr  
  6. #tar xf apr-1.4.6.tar.bz2  
  7. #cd apr-1.4.6  
  8. #./configure --prefix=/usr/local/apr  
  9. #make  
  10. #make install  
  11.  
  12. #tar xf apr-util-1.4.1.tar.bz2   
  13. #cd apr-util-1.4.1  
  14. #./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr  
  15. #make  
  16. #make install  
  17.  
  18. 編譯安裝apache   
  19. (注意:編譯的時候要啓用--enable-so  指定apr的位置  啓用--enable-proxy --enable-proxy-http --enable-proxy=ajp模塊)  
  20. #yum -y install pcre-devel  
  21. #tar xf httpd-2.4.2.tar.bz2  
  22. #cd httpd-2.4.2  
  23. #./configure --prefix=/usr/local/apache --sysconfdir=/etc/httpd --enable-so --enable-sll --enable-zlib --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util --enable-proxy --enable-proxy-http --enable-proxy-ajp  
  24. #make   
  25. #make install  

 

添加PidFile文件
 

  1. #vim /etc/httpd/httpd.conf  
  2. 添加  
  3. PidFile "/var/run/httpd.pid"  

 

提供服務腳本編輯/etc/rc.d/init.d/httpd

  1. #!/bin/bash  
  2. #  
  3. # httpd        Startup script for the Apache HTTP Server  
  4. #  
  5. # chkconfig: - 85 15  
  6. # description: Apache is a World Wide Web server.  It is used to serve \  
  7. #        HTML files and CGI.  
  8. # processname: httpd  
  9. # config: /etc/httpd/conf/httpd.conf  
  10. # config: /etc/sysconfig/httpd  
  11. # pidfile: /var/run/httpd.pid  
  12.  
  13. # Source function library.  
  14. . /etc/rc.d/init.d/functions  
  15.  
  16. if [ -f /etc/sysconfig/httpd ]; then  
  17.         . /etc/sysconfig/httpd  
  18. fi  
  19.  
  20. # Start httpd in the C locale by default.  
  21. HTTPD_LANG=${HTTPD_LANG-"C"}  
  22.  
  23. # This will prevent initlog from swallowing up a pass-phrase prompt if  
  24. # mod_ssl needs a pass-phrase from the user.  
  25. INITLOG_ARGS="" 
  26.  
  27. # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server  
  28. # with the thread-based "worker" MPM; BE WARNED that some modules may not  
  29. # work correctly with a thread-based MPM; notably PHP will refuse to start.  
  30.  
  31. # Path to the apachectl script, server binary, and short-form for messages.  
  32. apachectl=/usr/local/apache/bin/apachectl  
  33. httpd=${HTTPD-/usr/local/apache/bin/httpd}  
  34. prog=httpd 
  35. pidfile=${PIDFILE-/var/run/httpd.pid}  
  36. lockfile=${LOCKFILE-/var/lock/subsys/httpd}  
  37. RETVAL=0 
  38.  
  39. start() {  
  40.         echo -n $"Starting $prog: "  
  41.         LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS  
  42.         RETVAL=$?  
  43.         echo  
  44.         [ $RETVAL = 0 ] && touch ${lockfile}  
  45.         return $RETVAL  
  46. }  
  47.  
  48. stop() {  
  49.  echo -n $"Stopping $prog: "  
  50.  killproc -p ${pidfile} -d 10 $httpd  
  51.  RETVAL=$?  
  52.  echo  
  53.  [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}  
  54. }  
  55. reload() {  
  56.     echo -n $"Reloading $prog: "  
  57.     if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then  
  58.         RETVAL=$?  
  59.         echo $"not reloading due to configuration syntax error"  
  60.         failure $"not reloading $httpd due to configuration syntax error"  
  61.     else  
  62.         killproc -p ${pidfile} $httpd -HUP  
  63.         RETVAL=$?  
  64.     fi  
  65.     echo  
  66. }  
  67.  
  68. # See how we were called.  
  69. case "$1" in  
  70.   start)  
  71.  start  
  72.  ;;  
  73.   stop)  
  74.  stop  
  75.  ;;  
  76.   status)  
  77.         status -p ${pidfile} $httpd  
  78.  RETVAL=$?  
  79.  ;;  
  80.   restart)  
  81.  stop  
  82.  start  
  83.  ;;  
  84.   condrestart)  
  85.  if [ -f ${pidfile} ] ; then  
  86.   stop  
  87.   start  
  88.  fi  
  89.  ;;  
  90.   reload)  
  91.         reload  
  92.  ;;  
  93.   graceful|help|configtest|fullstatus)  
  94.  $apachectl $@  
  95.  RETVAL=$?  
  96.  ;;  
  97.   *)  
  98.  echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|fullstatus|graceful|help|configtest}"  
  99.  exit 1  
  100. esac  
  101.  
  102. exit $RETVAL  
  103.  
  104. #chmod +x /etc/rc.d/init.d/httpd  
  105. #chkconfig --add httpd  
  106. #service httpd start  
  107.  
  108. 添加apache的路徑  
  109. #vim /etc/profile  
  110. PATH:$PATH:/usr/local/apache/bin  
  111. 而後重新載入/etc/profile  
  112. #. /etc/profile  
  113.  
  114. # httpd -D DUMP_MODULES  | grep proxy              //查看加載的模塊  
  115.  proxy_http_module (shared)  
  116.  proxy_fcgi_module (shared)  
  117.  proxy_scgi_module (shared)  
  118.  proxy_ajp_module (shared)  
  119.  
  120.    
  121. tomcat1 tomcat2  
  122. 安裝tomcat  
  123. # rpm -ivh jdk-7u5-linux-i586.rpm   
  124.  
  125. 爲JVM指定JDK路徑  
  126. #vim /etc/profile  
  127. JAVA_HOME=/usr/java/jdk1.7.0_05  
  128. PATH=$PATH:$JAVA_HOME/bin:$PATH  
  129. export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC JAVA_HOME  
  130. #. /etc/profile  
  131. # printenv  
  132. 有如下內容  
  133. JAVA_HOME=/usr/java/jdk1.7.0_05  
  134. # java -version              //可以測試jdk是否生效  
  135. java version "1.7.0_05"  
  136. Java(TM) SE Runtime Environment (build 1.7.0_05-b05)  
  137. Java HotSpot(TM) Client VM (build 23.1-b03, mixed mode, sharing)  
  138.  
  139.  
  140. #tar xf  apache-tomcat-7.0.29.tar.gz -C /usr/local  
  141. # cd /usr/local  
  142. # ln -sv apache-tomcat-7.0.29 tomcat  
  143. # /usr/local/tomcat/bin/catalina.sh start 啓動  
  144.  
  145. 至此,兩臺服務器準備完畢  

tomcat1和tomcat2上統一做如下配置 

  1. tomcat1  
  2. #vim /usr/local/tomcat/conf/server.xml  
  3. 修改  
  4.  <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA">   
  5. 演示效果,在TomcatA上某context中提供特定頁面  
  6. #cd /usr/local/tomcat/webapps  
  7. #mkdir -pv sess/WEB-INF/{lib,classes}  
  8. #cd sess  
  9. #vim index.jsp  
  10. 添加如下內容  
  11. <%@ page language="java" %> 
  12. <html> 
  13.   <head><title>TomcatA</title></head> 
  14.   <body> 
  15.     <h1><font color="red">TomcatA </font></h1> 
  16.     <table align="centre" border="1"> 
  17.       <tr> 
  18.         <td>Session ID</td> 
  19.         <td><%= session.getId() %></td> 
  20.       </tr> 
  21.       <tr> 
  22.         <td>Created on</td> 
  23.         <td><%= session.getCreationTime() %></td> 
  24.      </tr> 
  25.     </table> 
  26.   </body> 
  27. </html> 
  28. #/usr/local/tomcat/conf/catalina.sh stop  
  29. #/usr/local/tomcat/conf/catalina.sh stop  
  30.  
  31.  
  32. tomcat2  
  33. #vim /usr/local/tomcat/conf/server.xml  
  34. 修改  
  35.  <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB"> 
  36.  
  37. 演示效果,在TomcatB上某context中,提供特定頁面  
  38. #cd /usr/local/tomcat/webapps  
  39. #mkdir -pv sess/WEB-INF/{lib,classes}  
  40. #cd sess  
  41. #vim index.jsp  
  42. 添加如下  
  43. <%@ page language="java" %> 
  44. <html> 
  45.   <head><title>TomcatB</title></head> 
  46.   <body> 
  47.     <h1><font color="blue">TomcatB </font></h1> 
  48.     <table align="centre" border="1"> 
  49.       <tr> 
  50.         <td>Session ID</td> 
  51.         <td><%= session.getId() %></td> 
  52.       </tr> 
  53.       <tr> 
  54.         <td>Created on</td> 
  55.         <td><%= session.getCreationTime() %></td> 
  56.      </tr> 
  57.     </table> 
  58.   </body> 
  59. </html> 
  60.  
  61. # /usr/local/tomcat/bin/catalina.sh stop  
  62. # /usr/local/tomcat/bin/catalina.sh start  
  63.  

 

二、整合apache和tomcat

2.1 基於mod_jk 實現負載均衡

  1. tomcat1:  
  2. 修改/etc/httpd/extra/httpd-jk.conf爲如下內容:  
  3. # Load the mod_jk  
  4. LoadModule  jk_module  modules/mod_jk.so  
  5. JkWorkersFile  /etc/httpd/extra/workers.properties  
  6. JkLogFile  logs/mod_jk.log  
  7. JkLogLevel  debug  
  8. JkMount  /*  lbcluster1  
  9. JkMount  /status  stat1  
  10. 保存退出                          
  11.  
  12. (lbcluster1  這個名字是虛的,專門是爲了實現負載均衡的)  
  13.  
  14.  
  15. 編輯/etc/httpd/extra/workers.properties,添加如下內容:  
  16.  
  17. worker.list=lbcluster1,stat1  
  18.  
  19. worker.TomcatA.port=8009 
  20. worker.TomcatA.host=172.16.220.11  
  21. worker.TomcatA.type=ajp13 
  22. worker.TomcatA.lbfactor=1 
  23.  
  24. worker.TomcatB.port=8009 
  25. worker.TomcatB.host=172.16.220.12  
  26. worker.TomcatB.type=ajp13 
  27. worker.TomcatB.lbfactor=1 
  28.  
  29. worker.lbcluster1.type=lb  
  30. worker.lbcluster1.balance_workers=TomcatA,TomcatB  
  31. worker.stat1.type=status 
  32. worker.lbcluster1.sticky_session = 0 
  33.  
  34. #service httpd restart  
  35.  

 

測試:172.16.220.11/sess 刷新訪問,可以看到兩臺tomcat主機輪詢訪問,實現了負載均衡

 

 

 


問題依然存在,就是會話無法保持。接下來會解決這個問題
(把/etc/httpd/extra/workers.properties中的worker.lbcluster1.sticky_session 的值改爲1,發現請求總是定向到一臺tomcat服務器上)

2.2 基於mod_proxy實現負載均衡

  1. tomcat1:  
  2.  
  3. #vim /etc/httpd/httpd.conf  
  4. Include /etc/httpd/extra/httpd-vhosts.conf  
  5. #Include /etc/httpd/extra/httpd-jk.conf  
  6.  
  7. #vim /etc/httpd/extra/httpd-vhosts.conf  
  8. 內容改爲:  
  9. ProxyRequests Off  
  10. ProxyPass / balancer://lbcluster1/ stickysession=jsessionid 
  11. ProxyPa***everse / balancer://lbcluster1/  
  12. <proxy balancer://lbcluster1> 
  13.         BalancerMember ajp://172.16.220.11:8009 loadfactor=10 route=TomcatA 
  14.         BalancerMember ajp://172.16.220.12:8009 loadfactor=10 route=TomcatB 
  15. </proxy> 
  16.  
  17. <VirtualHost *:80> 
  18.         ServerAdmin [email protected]  
  19.         ServerName tomcat.magedu.com  
  20. </VirtualHost> 
  21.  
  22. #service httpd restart  
  23.  

測試tomcat.magedu.com/sess 實現了負載均衡

 

 

 


但是會話依然無法保持(若配置worker.lbcluster1.sticky_session = 1 這裏的sticksession=jsessionid 訪問可以實現請求定向到一臺tomcat上)

四、tomcat基於session複製的集羣

  1. (DeltaManager 和BackupManager都可以實現)  
  2. 在tomcat1主機上:  
  3. #vim /usr/local/tomcat/conf/server.xml  
  4. <Engine...>行下面添加如下內容:  
  5.  
  6. <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" 
  7.                    channelSendOptions="8"> 
  8.      <Manager className="org.apache.catalina.ha.session.DeltaManager" 
  9.                     expireSessionsOnShutdown="false" 
  10.                     notifyListenersOnReplication="true"/> 
  11.        <Channel className="org.apache.catalina.tribes.group.GroupChannel"> 
  12.           <Membership className="org.apache.catalina.tribes.membership.McastService" 
  13.                    address="228.50.10.1"   bind="172.16.220.11"   port="45564" 
  14.                    frequency="500"  dropTime="3000"/> 
  15.              <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
  16.                                 address="172.16.220.11"   port="4000"  autoBind="100" 
  17.                                 selectorTimeout="5000"   maxThreads="6"/> 
  18.              <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> 
  19.                 <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> 
  20.              </Sender> 
  21.        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> 
  22.        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> 
  23.      </Channel> 
  24.      <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" 
  25.                         filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/> 
  26.      <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> 
  27.      <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" 
  28.                      tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" 
  29.                     watchDir="/tmp/war-listen/"  watchEnabled="false"/> 
  30.       <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> 
  31.       <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> 
  32. </Cluster> 
  33.  
  34. #cp /usr/local/tomcat/conf/web.xml /usr/local/tomcat/webapps/sess/WEB-INF  
  35. #vim /usr/local/tomcat/webapps/sess/WEB-INF/web.xml  
  36. 在  
  37. <web-app xmlns="http://java.sun.com/xml/ns/javaee" 
  38.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  39.   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
  40.                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  41.   version="3.0"> 後面添加如下  
  42. <distributable/> 
  43.  
  44. #/usr/local/tomcat/bin/catalina.sh stop  
  45. #/usr/local/tomcat/bin/catalina.sh start  
  46. #service httpd restart  
  47.  
  48. tomcat2上的配置和tocmat1上的配置一樣,只不過是把tomcat1的地址改爲tomcat2的地址爲172.16.220.12,然後複製web.xml,重啓服務

訪問 tomcat.magedu.com/sess 效果是負載均衡,並且會話是保持的

 


此時前端也可以是mod_jk(把apache的配置文件中的虛擬主機取消,mod_jk啓用即可)


 

  1. 操作過程中遇到了不少問題,這裏分享一下:  
  2.  
  3. 1、第五步中啓動httpd時,啓動成功了,但是端口並沒有監聽,什麼原因?  
  4. # tail /usr/local/apache/logs/error_log   
  5. [Wed Aug 29 12:25:43.918479 2012] [proxy_balancer:emerg] [pid 25008:tid 3086427904] AH01177: Failed to lookup provider 'shm' for 'slotmem': is mod_slotmem_shm loaded?  
  6. 編譯配置文件啓用這個模塊即可  
  7. LoadModule slotmem_shm_module modules/mod_slotmem_shm.so  
  8.  
  9. 2、 使用mod_jk總是實現不了複製均衡,什麼問題?頁面訪問的一直是TomcatA,鬱悶啊  
  10. 原因1:worker.lbcluster1.balance_workers = TomcatA,TomcatB  中 “TomcatA和TomcatB之間多了一個空格,導致TomcatA出不來  
  11.  2:沒有加worker.lbcluster1.sticky_session = 0 ,導致無法負載均衡,添加上之後就OK了  
  12.  
  13. 3、做mod_proxy時遇到了錯誤  
  14. 重啓httpd 時錯誤  
  15. # service httpd restart  
  16. Stopping httpd:                                            [FAILED]  
  17. Starting httpd:                                            [  OK  ]  
  18. # tail /usr/local/apache/logs/error_log  
  19. [proxy_balancer:emerg] [pid 4753:tid 3086935808] (22)Invalid argument: AH01186: worker slotmem_grab failed  
  20. [Wed Aug 29 20:15:18.609721 2012] [:emerg] [pid 4753:tid 3086935808] AH00020: Configuration Failed, exiting  
  21.  
  22. 解決:在虛擬主機的配置文件中,第一次是把  
  23. ProxyPass / balancer://lbcluster1/ stickysession=jsessionid 
  24. ProxyPa***everse / balancer://lbcluster1/ 這兩項內容定義在了虛擬主機內部,出了錯誤  
  25.  
  26. 定義在全局位置就可以了  
  27.  
  28. 4、在實現session複製時,定義<distributable/>時,放在其他地方就不行,即便是放在  
  29. <web-app xmlns="http://java.sun.com/xml/ns/javaee" 
  30.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  31.   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
  32.                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  33.   version="3.0"> 的前面就不行,一定要放在後面纔可以,可以是下面的任何一定地方,這是文件讀取時加載的順序  
  34.  

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章