JBoss4.2.3GA+Apache/2.2.11+mod_jk1.2.28 搭建負載均衡 全過程記錄(附上搭建環境)


 

    都是從網上搜集,再通過自己的實踐總結出來的,相信對沒做過Load Balancing的同學會有一定幫助。

先來三章概念:

1.     JBoss集群配置概念

JBoss集群(Cluster)是 一組計算機節點的集合,它們作為一個整體向用戶提供一組網絡資源。一個理想的集群對用戶是透明的。用戶由單一入口訪問集群的資源,從來不會意識到集群中的 節點。在他們看來,集群是一個系統,而非多個計算機系統。集群還應該支持隨意增加和減少集群系統的節點,而這同樣不會影響到用戶的訪問。

2.     JBoss集群分類

習慣上,JBoss集群配置的關鍵是把集群分為高可用(HighAvailability,簡稱HA)集群和高性能計算(HighPerfermanceComputing,簡稱HPC)集群兩類。HA集群的目標是提高系統的可使用性(availability),即可靠性(reliability)和可維護性(maintainability)。請不要將集群中的可使用性(availability)與UE和交互設計中的可用性(Usability)混淆。HA集群的核心是防止單點失效,這一般是通過失敗轉移來實現的,即在一個節點失效后由另一個節點接替服務。不丟失用戶狀態。HA集群的其他主要特性還包括負載均衡、session同步等。我們使用的SQLServer數據庫的雙機熱備和Oracle的RAC都屬於HA集群。HPC集群采用並行計算技術提供超大規模計算和存儲能力,多數超級計算機都是HPC集群。這不是我們關注的集群。

3.     JBoss集群架構

JBoss集群是HA集群。JBoss集群有2種架構。一是客戶端攔截器(Client-sideinterceptor)架構,一是負載均衡器(Loadbalancer)架構。客戶端攔截器架構適於用C/S結構,負載均衡器架構適用於B/S結構。本文只敘述負載均衡器架構的JBoss集群。

 

 

負載均衡器架構由負載均衡器和n個集群節點組成。每個節點是一個JBoss服 務器實例。負載均衡器是全局唯一的前置機,全部用戶請求都發到負載均衡器,由其轉發到各節點。當負載均衡器發現一個節點失效后,會將請求轉發到另一個節點 上,從而保證服務得以延續。負載均衡器同時負責加權靜態負載均衡調度。總之,負載均衡器的健康程度決定了集群的全局健康度,負載均衡器失敗將導致集群全部 失效。這是前置機架構集群的主要潛在問題。

JBoss的負載均衡器架構集群實際是由Tomcat的HTTP集群實現的。JBoss有自己的負載均衡器,但效果不佳,官方文檔沒有介紹,幾乎沒有人使用。一般情況下,我們都是采用apache+mod_jk作為負載均衡器。下文敘述的都是基於這種架構。mod_jk是apache的一個插件,負責apache與tomcat之間的通訊,是JBoss集群配置(tomcat集群)的關鍵。

4.准備環境

文件都上傳在金山網盤上

文件名:mod_jk-1.2.28-httpd-2.2.3.so, 訪問地址: http://www.kuaipan.cn/file/id_55504313337774089.htm ,訪問密碼:T5P6iu

文件名: jboss-4.2.3.GA.zip , http://www.kuaipan.cn/file/id_55504313337774088.htm  訪問密碼:Tt6aA4

文件名:apache_2.2.11-win32-x86-no_ssl.msi,  http://www.kuaipan.cn/file/id_55504313337774087.htm 訪問密碼:epzU33

如果失效了搜索下面文件名下載:

1)jboss-4.2.3.GA.zip

2)apache_2.2.11-win32-x86-no_ssl

3)mod_jk-1.2.28-httpd-2.2.3.so

5、安裝JDK什么的不用說了吧 略過N字

6、安裝apache_2.2.11-win32-x86-no_ssl

  安裝無非就是下一步下一步,不過有幾點要注意:

  1)路徑不要有中文,不要空格(地球上的程序員都知道)

  2)apache安裝時提示占用的端口為80和8080 ,這兩個端口都是容易占用的端口,安裝的時候最好確保沒被占用,

    雖然安裝之后可以修改他的端口,但是安裝的時候要是被占用,不知道會不會有什么影響。

       正確安裝后可以在電腦右下角看到圖標,還是先把他關掉吧,下面要做配置了

7、修改apache配置文件

  1)、找到安裝apache時的目錄下 conf/httpd.conf文件,在最后一行添加 Include conf/mod_jk.conf

  2)、把mod_jk-1.2.28-httpd-2.2.3.so 文件 更名為 mod_jk.so后,復制到安裝目錄下/modules文件夾中。注意同目錄下有個manual,不要搞錯了。

  3)、在 conf文件夾下新建文件mod_jk.conf

     文件內容 

     mod_jk.conf
# Load mod_jk module. Specify the filename # of the mod_jk lib you’ve downloaded and # installed in the previous section LoadModule jk_module modules/mod_jk.so # Where to find workers.properties JkWorkersFile conf/workers.properties # Where to put jk logs JkLogFile logs/mod_jk.log # Set the jk log level [debug/error/info] JkLogLevel info # Select the log format JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " # JkOptions indicate to send SSL KEY SIZE, JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories # JkRequestLogFormat set the request format JkRequestLogFormat "%w %V %T" JkMount /* loadbalancer 

 

            或者我網盤中也有 mod_jk.conf    http://www.kuaipan.cn/file/id_55504313337774090.htm 訪問密碼:ejLrRQ

  4)、在conf文件夾下 新建文件 workers.properties

    

workers.properties
worker.list=loadbalancer,node1,node2 # Define the first node... worker.node1.port=8009 worker.node1.host=10.0.0.114 worker.node1.type=ajp13 worker.node1.lbfactor=1 worker.node1.local_worker=1 worker.node1.cachesize=10 worker.node1.cache_timeout=600 worker.node1.reply_timeout=100 worker.node1.socket_timeout=300 # Define the first node... worker.node2.port=9711 worker.node2.host=10.0.0.114 worker.node2.type=ajp13 worker.node2.lbfactor=1 worker.node2.local_worker=1 worker.node2.cachesize=10 worker.node2.cache_timeout=600 worker.node2.reply_timeout=100 worker.node2.socket_timeout=300 # Now we define the load-balancing behaviour worker.loadbalancer.type=lb worker.loadbalancer.balanced_workers=node1,node2 worker.loadbalancer.sticky_session=0 
workers.properties中的屬性解釋,很重要
reply_timeout:此屬性告訴web server在接到遠端的Tomcat已死並實時的切換到集群中的另外一個Tomcat的回應之前等待一段時間。默認情況下web server將永遠等待。屬性值為web server要等待回應的時間(以ms為單位),所以如果具有運行時間較長的servlet時設置其值要小心。此屬性在jk 1.2.6版本被增加進來,以求避免Tomcat的死機和在支持ajp13的servlet引擎上發生的問題。此屬性默認為失效的。 cache_timeout:本屬性用於聲明JK在cache中保留一個打開的socket的時間,它對減少web serer的線程數有所幫助。眾所周知,一個身背重負的web server(例如apache)建立childs/threads來處理負載,而當負載減少時它將銷毀無用的childs/threads。每個 child在轉發請求給Tomcat時要打開一個ajp13連接,而在Tomcat那一端也將建立一個ajp13線程與之通訊。 socket_timeout:此屬性說明連接在未激活的狀況下持續多久,web server將主動切斷之。這是一個使Tomcat端的陳舊線程不致過多的好方法,但是也帶來了在下一次請求到來時需要重新打開socket的開銷。此屬性與cache_timeout有類似的功效,但是它工作在non-cache模式。 本例采用一台計算機同時啟動2個jboss的方案實現的。所以ip一樣,AJP/1.3端口不一樣。JBoss的Web集群使用apache的 mod_jk,瀏覽器請求apache服務器,apache服務器根據workers.properties中的配置進行request分發,apache服務器和Jboss中的Tomcat可以用ajp1.3進行通信的,request通過ajp1.3協議的包裝被發送到 Jboss,Jboss執行后返回結果。 其中對於node的命名規則是worker.節點名.xxxx。所以上述文件定義了兩個節點:node1和node2。8009端口是jboss默認的ajp端口,另外需要注意的是worker.node2.lbfactor參數,它是節點的負載加權,它的值越大,獲得負載的機會就越大。可以根據node的硬件性能進行調整。 上面的文件中配置了兩個節點,name分別為 node1,node2,指定兩個節點的IP,並在worker.loadbalancer.balance_workers中指定所有的node列表,worker.loadbalancer.sticky_session設置是否啟用“粘着的”Session,sticky session是指來自同一IP的請求將被發送到同一個Jboss節點,sticky session設為0的話同一session的不同請求會被負載均衡分發到不同的jboss節點上。 

   5)、在conf/目錄創建新文件uriworkermap.properties 內容如下

uriworkermap.properties
/jmx-console=loadbalancer /jmx-console/*=loadbalancer /web-console=loadbalancer /web-console/*=loadbalancer 

   至此apache的配置基本結束唯一剩下的就是workers.properties中節點的IP還需要根據之后的部署環境來改變

8、Jboss集群節點配置

  1) 修改 JBOSS_HOME/server/all/deploy/jboss-web.deployer/server.xml

     將Engine 修改如下:<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1"> 

       這個node1 應該是與workers.properties中節點名字一樣,還有一個jboss 就應該是node2了。

  2)修改  JBOSS_HOME/server/all/deploy/ jboss-web.deployer/META-INF/ jboss-service.xml

    找到<attributename="UseJK">改為:<attribute name="UseJK">true</attribute>  

9、部署(到此關於負載均衡的配置就結束了。當然還差一點點,關於session的復制,稍后再說,先把基本的跑起來。)

     1)部署之前先把之前的workers.properties 中的兩個ip改成待部署的兩台服務器的ip 和端口,注意 文件中設置的端口並非server.xml        中的TCP端口,而是下面一點的AJP端口

     2)啟動你的Apache服務器 必須先啟動Apache

     3)啟動jboss 這邊要注意了 啟動時一定要這樣啟動:  搞一個快捷方式到桌面 ,右鍵 屬性 在目標中 加上參數  -c all -b xxx.xxx.xxx.xxx(jboss所在服務器的ip)

10、部署完也該測試下

  1)測試的話自己建個web程序,然后寫個servlet 打印一句話,然后把web工程放到jboss/server/all/frame/下 ,

    這樣兩個jboss下就都有了,如果不行再放一次,然后重啟jboss。

    2)訪問 http://localhost:<port>/    port  是apache的端口,不要訪問錯了。首先應該可以看到jboss的歡迎頁。

    如果可以看到,那應該沒問題了,可以把和apache在同一服務器的那個jboss關掉,如果還可以訪問,說明99% OK

    3)進一步測試, 訪問你之前寫的那個servlet, 它打印的語句應該分別在兩台服務器的jboss控制台中輪流顯示。

11、Jboss集群的session復制

    集群的缺陷和粘着session

  截止到現在,Jboss集群工作得很完美,除了session。

    目前配置的Jboss集群中,各節點是被動的、相互獨立的,相當於增加了節點狀態檢測的DNS輪詢,所以session也是相互獨立的。當同一用戶的2個請求被轉發到不同的Jboss    節點  上時,會出現session信息假”丟失”的現象。

    為此,Jboss提出粘着session(stickysession)概念。使用粘着session后,來自同一IP的請求將被發送到同一個Jboss節點,從而保證session使用的連續性。如果應用中沒有   使用  session,則可以使用非粘着session的jboss集群。這樣,負載分布更為合理。

  設置方法是編輯負載均衡器的/usr/local/apache2/conf/workers.properties的worker.loadbalancer.sticky_session。設置為1使用粘着session,設置為0不使用粘着session。

  使用粘着session還存在一種隱患,當某個節點發生故障時,該節點的session將全部丟失。要徹底解決這個問題,就要用到jboss session復制

   Jboss session復制原理

  jboss session復制是jboss session同步的一種實現。原理是在各Jboss節點間建立橫向聯系,每個節點都將本節點的session變化同步到其他所有節點上。

  jboss的session復制與HTTP集群是相互配合、相互獨立的兩個系統。session復制是節點間的橫向聯系,HTTP集群是負載均衡器與節點的縱向聯系。

  

12、配置Jboss節點

  JBOSS_HOME/server/all/deploy/jbossweb-cluster.sar/META-INF/jboss-service.xml,

  找到<attribute name="ClusterConfig">,有udp和tcp兩種方式,任選一種即可,將bind_addr改為本機ip,

  <tcpping initial_hosts 值設為:node1 IP[7810],node2 IP[7810] ;

     找到 server/all/deploy/tc5-cluster.sar/META-INF/jboss-service.xml

     找到<config><udp,將><config>到</config>全部注釋掉.
     jboss session復制有UDP和TCP兩種方式.UDP采用多播方式,但問題比較多,所以采用TCP方式。

    找到<config> <tcp,將><config>到</config>生效.並對該部分進行以下修改:

·  

·   將全部down_thread和up_thread的false都改為true. 

·  

· 在<tcp bind_addr=后填入本機的IP,比如<TCP bind_addr=

·  

· 在<tcpping initial_hosts=后填入本機和集群其他全部Jboss節點的IP[7810],比如

  <tcpping initial_hosts=192.168.130.95[7810],192.168.130.99[7810],192.168.130.112[7810]></tcpping> 

· 

其他參數還包括:

參數
ClusterName是集群名稱,比如partition1.
在同一局域網內,可以存在多個jboss集群,根據集群名稱區分它們.所以,集群中各節點配置的集群名稱必須一致,而機器IP則沒有特殊要求,只要它們能相互連通. 理論上,可以在一台機器上安裝多個Jboss實例,分屬於不同的集群.但這會極大地增加復雜度,是不好的配置方式.jijian91嚴重不建議給自己找麻煩。

IsolationLevel是隔離等級.
可選值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED,READ_UNCOMMITTED, 和 NONE。這里的隔離級別和數據庫的隔離級別有同樣的含義,對於大多數WEB應用程序來講通常設置為REPEATABLE_READ。

CacheMode是緩存模式。
由於session復制是通過緩存實現的,所以實際上是復制模式.可選值包括:REPL_SYNC 和REPL_ASYNC,確定改變是應該同步還是異步復制。缺省值是REPL_ASYNC.使用同步復制,確保在請求完成之前傳播改變,session同步沒有滯后,但效率低。

在應用程序的web.xml的<web-app>段中增加<distributable />,如下所示:

<?xml version="1.0" encoding="UTF-8"?>  

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee ;    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd ;">  

<distributable />  

</web-app>

在web-inf中添加jboss-web.xml文件,內容如下:

<!DOCTYPE jboss-web PUBLIC  

    "-//JBoss//DTD Web Application 4.2//EN"  

    "http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">  

<jboss-web>  

    <replication-config>  

        <replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>

            <replication-granularity>SESSION</replication-granularity>  

            <replication-field-batch-mode>true</replication-field-batch-mode>  

    </replication-config>  

    <context-root>/</context-root>  

</jboss-web> 

 

13、測試session 復制

新建servlet  然后下面是測試的代碼

testSession
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class testSession
 */
public class testSession extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public testSession() {
        super();
        // TODO Auto-generated constructor stub
    }

  
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        synchronized (request) {
            doPost(request, response);
        }
        
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Object o =  request.getSession().getAttribute("index");
    if(o==null){
        request.getSession().setAttribute("index", 1);
        System.out.println(1);
    }else{
        request.getSession().setAttribute("index", new Integer(o.toString()).intValue()+1);
        System.out.println(request.getSession().getAttribute("index").toString());
    }
    
    
    }

}

 

 

 

      紅色字都是滿重要的地方,或者是我在看網上資料是含糊不清的地方,在此做下總結。方便以后工作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM