ActiveMQ配置使用

  • 介紹

ActiveMQ 是Apache出品,最流行的,能力強勁的開源消息總線。ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已經是很久的事情了,但是JMS在當今的J2EE應用中間仍然扮演着特殊的地位。


  • ActiveMQ的特性
  1. 多種語言和協議編寫客戶端。語言: Java, C, C++, C#, Ruby, Perl, Python, PHP。應用協議: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
  2. 完全支持JMS1.1和J2EE 1.4規範 (持久化,XA消息,事務)
  3. 對Spring的支持,ActiveMQ可以很容易內嵌到使用Spring的系統裏面去,而且也支持Spring2.0的特性
  4. 通過了常見J2EE服務器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的測試,其中通過JCA 1.5 resource adaptors的配置,可以讓ActiveMQ可以自動的部署到任何兼容J2EE 1.4 商業服務器上
  5. 支持多種傳送協議:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
  6. 支持通過JDBC和journal提供高速的消息持久化
  7. 從設計上保證了高性能的集羣,客戶端-服務器,點對點
  8. 支持Ajax
  9. 支持與Axis的整合
  10. 可以很容易得調用內嵌JMS provider,進行測試

  • 使用場景

    多個項目之間集成
    (1) 跨平臺
    (2) 多語言
    (3) 多項目
    降低系統間模塊的耦合度,解耦
    (1) 軟件擴展性
    系統前後端隔離
    (1) 前後端隔離,屏蔽高安全區

1、 不同語言應用集成
ActiveMQ 中間件用Java語言編寫,因此自然提供Java客戶端 API。但是ActiveMQ 也爲C/C++、.NET、Perl、PHP、Python、Ruby 和一些其它語言提供客戶端。在你考慮如何集成不同平臺不同語言編寫應用的時候,ActiveMQ 擁有巨大優勢。在這樣的例子中,多種客戶端API通過ActiveMQ 發送和接受消息成爲可能,無論使用的是什麼語言。此外,ActiveMQ 還提供交叉語言功能,該功能整合這種功能,無需使用遠程過程調用(RPC)確實是個優勢,因爲消息協助應用解耦。
2、 作爲RPC的替代
使用RPC同步調用的應用十分普遍。假設大多數客戶端服務器應用使用RPC,包括ATM、大多數WEB應用、信用卡系統、銷售點系統等等。儘管很多系統很成功,但是轉換使用異步消息可以帶來很多好處,而且也不會放棄響應保證。使用同步請求的系統在規模上有較大的限制,因爲請求會被阻塞,從而導致整個系統變慢。如果使用異步消息替代,可以很容易增加額外的消息接收者,使得消息能被併發消耗,從而加快請求處理。當然,你的系統應用間應該是解耦的。
3、 應用之間解耦
正如之前討論的,緊耦合架構可以導致很多問題,尤其是如果他們是分佈的。鬆耦合架構,在另一方面,證實了更少的依賴性,能夠更好地處理不可預見的改變。不僅可以在系統中改變組件而不影響整個系統,而且組件交互也相當的簡單。相比使用同步的系統(調用者必須等待被調用者返回信息),異步系統(調用方發送消息後就不管,即fire-and-forget)能夠給我們帶來事件驅動架構(event-driven architecture EDA)。
4、 作爲事件驅動架構的主幹
解耦,異步架構的系統允許通過代理器自己配置更多的客戶端,內存等(即vertical scalability)來擴大系統,而不是增加更多的代理器(即horizontal scalability)。考慮如亞馬遜這樣繁忙的電子商務系統。當用戶購買物品,事實上系統需要很多步驟去處理,包括下單,創建發票,付款,執行訂單,運輸等。但是用戶下單後,會立即返回“謝謝你下單”的界面。不只是沒有延遲,而且用戶還會受到一封郵件表明訂單已經收到。在亞馬遜下單的例子就是一個多步處理的例子。每一步都由單獨的服務去處理。當用戶下單是,有一個同步的體積表單動作,但整個處理流程並不通過瀏覽器同步處理。相反地,訂單馬上被接受和反饋。而剩下的步驟就通過異步處理。如果在處理過程中出錯,用戶會通過郵件收到通知。這樣的異步處理能提供高負載和高可用性。
5、 提高系統擴展性
很多使用事件驅動設計的系統是爲了獲得高可擴展性,例如電子商務,政府,製造業,線上遊戲等。通過異步消息分開商業處理步驟給各個應用,能夠帶來很多可能性。考慮設計一個應用來完成一項特殊的任務。這就是面向服務的架構(service-oriented architecture SOA)。每一個服務完成一個功能並且只有一個功能。應用就通過服務組合起來,服務間使用異步消息和最終一致性。這樣的設計便可以引入一個複雜事件處理概念(complex event processing CEP)。使用CEP,部件間的交互可以被記錄追蹤。在異步消息系統中,可以很容易在部件間增加一層處理。


  • 安裝

安裝
首先去http://activemq.apache.org/download.html 下載最新版本
目錄如下:
+bin (windows下面的bat和unix/linux下面的sh)
+conf (activeMQ配置目錄,包含最基本的activeMQ配置文件)
+data (默認是空的)
+docs (index,replease版本里面沒有文檔,-.-b不知道爲啥不帶)
+example (幾個例子)
+lib (activemMQ使用到的lib)
-apache-activemq-4.1-incubator.jar (ActiveMQ的binary)
-LICENSE.txt
運行信息
運行信息
-NOTICE.txt
-README.txt
-user-guide.html
這裏寫圖片描述
啓動bin/win64/activemq.bat
啓動成功就可以訪問管理員界面:http://localhost:8161/admin

  • 使用,消息發送方式

(1)、點對點方式(point-to-point Queue)

點對點的消息發送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存貯消息,Sneder 發送消息,receive接收消息.具體點就是Sender Client發送Message Queue ,而 receiver Cliernt從Queue中接收消息和”發送消息已接受”到Quere,確認消息接收。消息發送客戶端與接收客戶端沒有時間上的依賴,發送客戶端可以在任何時刻發送信息到Queue,而不需要知道接收客戶端是不是在運行


(2)、發佈/訂閱 方式(publish/subscriber Messaging
Topic)

發佈/訂閱方式用於多接收客戶端的方式.作爲發佈訂閱的方式,可能存在多個接收客戶端,並且接收端客戶端與發送客戶端存在時間上的依賴。一個接收端只能接收他創建以後發送客戶端發送的信息。作爲subscriber ,在接收消息時有兩種方法,destination的receive方法,和實現message listener 接口的onMessage 方法。

發送消息的基本步驟:
(1)、創建連接使用的工廠類JMS ConnectionFactory
(2)、使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
(3)、使用連接Connection 建立會話Session
(4)、使用會話Session和管理對象Destination創建消息生產者MessageSender
(5)、使用消息生產者MessageSender發送消息

消息接收者從JMS接受消息的步驟
(1)、創建連接使用的工廠類JMS ConnectionFactory
(2)、使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
(3)、使用連接Connection 建立會話Session
(4)、使用會話Session和管理對象Destination創建消息接收者MessageReceiver
(5)、使用消息接收者MessageReceiver接受消息,需要用setMessageListener將MessageListener接口綁定到MessageReceiver消息接收者必須實現了MessageListener接口,需要定義onMessage事件方法。

這裏寫圖片描述

【ActiveMQ配置文件】

ActiveMQ內存配置和密碼設置

1.配置內存  

  bin中activemq.bat 中的第一行 加上 :
  REM 配置內存
  set ACTIVEMQ_OPTS=-Xms1G -Xmx1G

2.修改控制檯密碼

打開conf/jetty.xml,

<bean id="securityConstraint" class="org.eclipse.jetty.http.security.Constraint">
    <property name="name" value="BASIC" />
    <property name="roles" value="admin" />
    <property name="authenticate" value="false" />
</bean>


將property name爲authenticate的屬性value="false" 改爲"true",高版本的已經默認爲true了。

控制檯的登錄用戶名密碼保存在conf/jetty-realm.properties文件中,內容如下:

# Defines users that can access the web (console, demo, etc.)
# username: password [,rolename ...]
admin: admin, admin

值得注意的是 用戶名和密碼的格式是:用戶名 : 密碼 ,角色名

此處我使用的apache-activemq-5.13.2 已經爲true不用更改了。

3.修改客戶端連接密碼

3.1修改activemq.xml配置,需要新增一個插件,在節點裏面節點前面添加如下

<plugins> 
   <simpleAuthenticationPlugin> 
         <users> 
              <authenticationUser username="${activemq.username}" password="${activemq.password}" groups="users,admins"/> 
         </users> 
   </simpleAuthenticationPlugin> 
</plugins>

或者直接修改爲(即直接將username和password賦值,所賦的值即爲用戶名和密碼。如果使用這一種方式的話,下面的3.2步則不需要了):

<plugins> 
   <simpleAuthenticationPlugin> 
         <users> 
              <authenticationUser username="testUserName" password="testPassword" groups="users,admins"/> 
         </users> 
   </simpleAuthenticationPlugin> 
</plugins>

3.2用戶名密碼文件爲:credentials.properties

## --------------------------------------------------------------------------- 
## Licensed to the Apache Software Foundation (ASF) under one or more 
## contributor license agreements. See the NOTICE file distributed with 
## this work for additional information regarding copyright ownership. 
## The ASF licenses this file to You under the Apache License, Version 2.0 
## (the "License"); you may not use this file except in compliance with 
## the License. You may obtain a copy of the License at 
## 
## http://www.apache.org/licenses/LICENSE-2.0 
## 
## Unless required by applicable law or agreed to in writing, software 
## distributed under the License is distributed on an "AS IS" BASIS, 
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
## See the License for the specific language governing permissions and 
## limitations under the License. 
## --------------------------------------------------------------------------- 

# Defines credentials that will be used by components (like web console) to access the broker 

activemq.username=system    # 用戶名
activemq.password=manager   # 密碼
guest.password=password

代碼:

這裏寫圖片描述

點對點方式(point-to-point Queue):

消費者:

package com.h3c.activMQ;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class QueueConsumer {

    public static void main(String[] args) {
        //連接信息設置
        String username = "zhangsan";
        String password = "123";
        String brokerURL = "failover://tcp://localhost:61616";
        //連接工廠
        ConnectionFactory connectionFactory = null;
        //連接
        Connection connection = null;
        //會話 接受或者發送消息的線程
        Session session = null;
        //消息的目的地
        Destination destination = null;
        //消息消費者
        MessageConsumer messageConsumer = null;
        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(username, password, brokerURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建session
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //創建一個連接QueueTest的消息隊列
            destination = session.createQueue("QueueTest");
            //創建消息消費者
            messageConsumer = session.createConsumer(destination);

            while (true) {
                TextMessage textMessage = (TextMessage) messageConsumer.receive(100000);
                System.out.println("-----------");
                if(textMessage != null){
                    System.out.println("成功接收消息:" + textMessage.getText());
                }else {
                    break;
                }
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

生產者 :

package com.h3c.activMQ;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class QueueProducer {

    public static void main(String[] args) {
        //連接信息設置
        String username = "zhangsan";
        String password = "123";
        String brokerURL = "failover://tcp://localhost:61616";
        //連接工廠
        ConnectionFactory connectionFactory = null;
        //連接
        Connection connection = null;
        //會話 接受或者發送消息的線程
        Session session = null;
        //消息的目的地
        Destination destination = null;
        //消息生產者
        MessageProducer messageProducer = null;
        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(username, password, brokerURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建session
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            //創建一個名稱爲QueueTest的消息隊列
            destination = session.createQueue("QueueTest");
            //創建消息生產者
            messageProducer = session.createProducer(destination);
            //發送消息
            TextMessage message = null;
            for (int i=0; i<10; i++) {
                //創建要發送的文本信息
                message = session.createTextMessage("Queue消息測試" +(i+1));
                //通過消息生產者發出消息 
                messageProducer.send(message);
                System.out.println("發送成功:" + message.getText());
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(null != connection){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

發佈/訂閱 方式(publish/subscriber Messaging Topic)

生產者:

package com.h3c.Topic;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;

public class TopicProducer {

    public static void main(String[] args) {
        //連接信息設置
        String username = "zhangsan";
        String password = "123";
        String brokerURL = "failover://tcp://localhost:61616";
        //連接工廠
        ConnectionFactory connectionFactory = null;
        //連接
        Connection connection = null;
        //會話 接受或者發送消息的線程
        Session session = null;
        //消息的主題
        Topic topic = null;
        //消息生產者
        MessageProducer messageProducer = null;
        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(username, password, brokerURL);
        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建session
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            //創建名爲TopicTest的主題
            topic = session.createTopic("TopicTest");  
            //創建主題生產者
            messageProducer = session.createProducer(topic);
            messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);//不將數據持久化
            //發送主題
            TextMessage message = null;
            for (int i=0; i<10; i++) {
                //創建要發送的文本信息
                message = session.createTextMessage("Topic主題測試" +(i+1));
                //通過主題生產者發出消息 
                messageProducer.send(message);
                System.out.println("發送成功:" + message.getText());
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(null != connection){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }  
    }

}

消費者:

package com.h3c.Topic;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;

public class TopicConsumer {

    public static void main(String[] args) {
        //連接信息設置
        String username = "zhangsan";
        String password = "123";
        String brokerURL = "failover://tcp://localhost:61616";
        //連接工廠
        ConnectionFactory connectionFactory = null;
        //連接
        Connection connection = null;
        //會話 接受或者發送消息的線程
        Session session = null;
        //主題的目的地
        Topic topic = null;
        //主題消費者
        MessageConsumer messageConsumer = null;
        //實例化連接工廠
        connectionFactory = new ActiveMQConnectionFactory(username, password, brokerURL);

        try {
            //通過連接工廠獲取連接
            connection = connectionFactory.createConnection();
            //啓動連接
            connection.start();
            //創建session
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //創建一個連接TopicTest的主題
            topic = session.createTopic("TopicTest");  
            //創建主題消費者
            messageConsumer = session.createConsumer(topic);

            messageConsumer.setMessageListener(new MyMessageListener());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

}

class MyMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message) {  
        TextMessage textMessage = (TextMessage) message;  
        try {  
            System.out.println("接收訂閱主題:" + textMessage.getText());  
        } catch (JMSException e) {  
            e.printStackTrace();  
        }  
    } 

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