ActiveMQ嵌入Tomcat

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

  • ActiveMQ中的BrokerService
  • 自啓動Servlet配置
  • 使用jconsole瞭解嵌入ActiveMQ運行狀態

一、開啓BrokerService

在pom.xml添加ActiveMQ依賴,本次代碼實例採用5.7版本,記住只需要activemq-core就行

<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>activemq-core</artifactId>
  <version>5.7.0</version>
</dependency>

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

  1. 是否需要在jconsole中顯示監控信息 broker.setUseJmx(true)
  2. 設置連接用戶名和密碼,如何使用驗證插件
  3. 是否持久化,存儲位置設置,持久化配置

所以需要啓動一個連接地址 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<AuthenticationUser> d = new ArrayList<AuthenticationUser>();
 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個步驟

  1. 建立連接,採用failover:()方式,自動斷線重連
  2. 建立Session,獲取發送或接收目標Destination ,指定是隊列(session.createQueue(queueName)),還是主題(session.createTopic(topicName))
  3. 通過Session獲取生產者或消費者
  4. 生產或消費消息

我們現在編寫一個生產者的代碼,並循環產生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();
    }
  }
});

運行效果

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

三、監控嵌入的ActiveMQ

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

Alt text
待jconsole啓動後,選擇ActiveMQ所在的進程。連接後選擇Mbean頁籤

Alt text
紅框的地方分別爲已消費和已進入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,完美解決所有問題。

 

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