ActiveMQ嵌入Tomcat

weixin_33751566發表於2018-09-12

在一些專案中,單獨開啟一個ActiveMQ,對於專案實施來說有時略顯繁瑣。所以我們將ActiveMQ內嵌到Tomcat,Tomcat啟動同時就順帶啟動了ActiveMQ。由此我們需要掌握三個個重要的知識點

ActiveMQ中的BrokerService

自啟動Servlet配置

使用jconsole瞭解嵌入ActiveMQ執行狀態

一、開啟BrokerService

在pom.xml新增ActiveMQ依賴,本次程式碼例項採用5.7版本,記住只需要activemq-core就行

  org.apache.activemq

  activemq-core

  5.7.0

在編寫BrokerService程式碼部分,主要注意三個點

是否需要在jconsole中顯示監控資訊 broker.setUseJmx(true)

設定連線使用者名稱和密碼,如何使用驗證外掛

是否持久化,儲存位置設定,持久化配置

所以需要啟動一個連線地址 tcp://localhost:61616,使用者名稱為admin,密碼為admin,需要持久化,持久化資料檔案儲存地址為 /activemq ,需要啟動jconsole監控的BrokerService的程式碼如下:

1 // author:herbert qq:464884492

2 BrokerService broker = new BrokerService();

3 broker.setUseJmx(true); // 開啟監控

4 broker.setPersistent(true); // 持久化

5 broker.setBrokerName("Test");

6 SimpleAuthenticationPlugin sap = new SimpleAuthenticationPlugin();

7 AuthenticationUser au = new AuthenticationUser("admin", "admin","users");

8 ArrayList d = new ArrayList();

9 d.add(au);

10 sap.setUsers(d); // 使用者驗證

11 broker.setPlugins(new BrokerPlugin[] { sap });

12 String mqDataPath = "/activemq"; // 儲存位置

13 broker.getPersistenceAdapter().setDirectory(new File(mqDataPath));

14 broker.addConnector("tcp://localhost:61616"); // 連線地址

15 broker.start();

二、生產者和消費者

ActiveMQ中,通用的訊息傳遞方式有兩種

佇列,支援訊息持久化,未消費的訊息,在重啟後依然存在。若有多個消費者,在每次提取一條訊息的前提下,所有消費均分佇列中的訊息

主題,不支援訊息持久化,未消費的訊息,在重啟後訊息丟失。若有多個消費,每個消費者依次消費主題中所有訊息

不管是生產者還是消費者程式碼編寫,主要是4個步驟

建立連線,採用failover:()方式,自動斷線重連

建立Session,獲取傳送或接收目標Destination ,指定是佇列(session.createQueue(queueName)),還是主題(session.createTopic(topicName))

通過Session獲取生產者或消費者

生產或消費訊息

我們現在編寫一個生產者的程式碼,並迴圈產生10條訊息

1 // author:herbert qq:464884492

2 String mqConnUrl = "tcp://localhost:61616";

3 String connUrl = "failover:(" + mqConnUrl.trim()+ ")?initialReconnectDelay=1000&maxReconnectDelay=30000";

4 ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin","admin", connUrl);

5 javax.jms.Connection connection = connectionFactory.createConnection();

6 connection.start();

7 Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

8 Destination destination = session.createQueue("system");

9 MessageProducer messageProducer = session.createProducer(destination);

10 

11 for (int i = 0; i < 10; i++) {

12  javax.jms.TextMessage message = session.createTextMessage("ActiveMQ 傳送的訊息" + i);

13  System.out.println("傳送訊息:" + "ActiveMQ 傳送的訊息" + i);

14  messageProducer.send(message);

15 }

編寫一個消費,消費上邊的10條訊息

// author:herbert qq:464884492

String mqConnUrl = "tcp://localhost:61616";

String connUrl = "failover:(" + mqConnUrl.trim()+ ")?initialReconnectDelay=1000&maxReconnectDelay=30000";

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", connUrl);

javax.jms.Connection connection = connectionFactory.createConnection();

connection.start();

Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

Destination destination = session.createQueue("system");

MessageConsumer messageConsumer = session.createConsumer(destination);

messageConsumer.setMessageListener(new MessageListener() {

  @Override

  public void onMessage(javax.jms.Message message) {

    ActiveMQTextMessage m = (ActiveMQTextMessage) message;

    try {

      System.out.println("接收到:" + m.getText());

     } catch (JMSException e) {

      e.printStackTrace();

    }

  }

});

執行效果

12016719-aed5b1631749ff0d


可見,我們生產者,產生的10條訊息,已成功被消費者處理了。

三、監控嵌入的ActiveMQ

對於嵌入的ActiveMQ,在BrokerService啟動前需要設定 broker.setUseJmx(true);然後找到你的JAVA_HOME,切換到bin,輸入jconsole命令。

12016719-241520e99b93829e


待jconsole啟動後,選擇ActiveMQ所在的程式。連線後選擇Mbean頁籤

12016719-c79976f813f82528


紅框的地方分別為已消費和已進入MQ中的訊息的條數。選擇操作,找到那個SendTextMessage還可以想此佇列傳送訊息。

四、Selvelt跟隨Tomcat啟動

對於Tomcat7.x版本之後Tomcat,Selvelt都可以通過直接在程式碼中通過註解的方式配置URl連線,一起是否自啟動loadOnStartup這個值>=0表示需要自啟動,值越小優先順序越高

1 // author:herbert qq:464884492

2 @WebServlet(urlPatterns = "/initmq", loadOnStartup = 1)

3 public class InitMqServlet extends HttpServlet {

4  @Override

5  public void init(ServletConfig config) throws ServletException {

6  super.init(config);

7  // 這裡編寫啟動ActiveMQ程式碼

8  }

9 }

五、總結

這次以ActiveMQ作為訊息佇列使用切入點,總體上說還比較順利。其中唯一出現問題的地方就是對於activeMQ依賴過多,多依賴了jaractivemq-broker,導致訊息能連線,但不能傳送訊息。後邊直接換成 activemq-all,有出現slf4j日誌衝突,使用exclusions依然不能解決問題。最終只依賴 activemq-core,完美解決所有問題。