品優購項目筆記(九):消息中間件ActiveMQ

消息中間件

介紹

什麼是JMS
jms的全稱是Java message service(Java消息服務),jms是jdk底層定義的規範,各大廠商都有實現這個規範的技術。

作用:在soa分佈式架構系統中,或企業的多個項目中,進行多個系統異步傳遞消息。

同步和異步

  • 同步技術:
    dubbo是一中同步技術, 實時性高, controller調用service項目, 調用就執行, 如果service項目中的代碼沒有執行完, controller裏面的代碼一致等待結果
  • 異步技術:
    mq消息中間件技術(jms) 是一種異步技術, 消息發送方, 將消息發送給消息服務器, 消息服務器未必立即處理.什麼時候去處理, 主要看消息服務器是否繁忙, 消息進入服務器後會進入隊列中, 先進先出.實時性不高.

使用場景
場景一:使用消息服務器當做大的隊列使用, 先進先出, 來處理高併發寫入操作
在這裏插入圖片描述
場景二:使用消息服務器可以將業務系統的串行執行改爲並行執行, 處理效率高, 更合理的榨取服務器的性能.

在這裏插入圖片描述

缺點:
消息中間件實時性不高, 因爲發送方將消息發送給消息服務器後, 消息服務器未必能夠立即處理, 主要看消息服務器是否繁忙, 隊列中先進先出, 如果數據量大, 要排隊等待執行

jms消息服務器同類型技術:

  • ActiveMQ:
    是apache的一個比較老牌的消息中間件, 它比較均衡, 既不是最安全的, 也不是最快的.
  • RabbitMQ:
    是阿里巴巴的一個消息中間件, 更適合金融類業務, 它對數據的安全性比較高.能夠保證數據不丟失.
  • ZeroMQ:
    史上最快的消息隊列系統
  • Kafka:
    Apache下的一個子項目。特點:高吞吐,在一臺普通的服務器上既可以達到10W/s的吞吐速率;完全的分佈式系統。適合處理海量數據。

JMS中支持的消息類型:

  • TextMessage–一個字符串對象
  • MapMessage–一套名稱-值對
  • ObjectMessage–一個序列化的 Java 對象(可傳遞集合)
  • BytesMessage–一個字節的數據流
  • StreamMessage – Java 原始值的數據流

JMS消息傳遞類型

兩種發送模式

  • 點對點模式: 一個發送方, 一個接收方. 也可以多個發送方, 一個接收方, 主要是接收方必須是第一個.

在這裏插入圖片描述

  • 訂閱發佈模式: 一個發送方, 多個接收方. 發送方也可以是多個, 主要看接收方, 接收方必須是多個

在這裏插入圖片描述

ActiveMQ小例子

代碼只做瞭解,因爲不同的jms,代碼完全不同,所以之後會通過spring來進行管理

點對點

當發送方發送數據之後,接收方不論是先啓動還是後啓動,都能夠接收到數據。

接收方

package cn.itcast.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 點對點模式 接收方
 */
public class QueueConsumer {
    public static void main(String[] args) throws Exception{
        //1.創建連接工廠
        ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.200.128:61616");
        //2.獲取連接
        Connection connection = connectionFactory.createConnection();
        //3.啓動連接
        connection.start();
        //4.獲取session  (參數1:是否啓動事務,參數2:消息確認模式)
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5.創建隊列對象
        Queue queue = session.createQueue("test-queue");
        //6.創建消息消費
        MessageConsumer consumer = session.createConsumer(queue);

        //7.監聽消息
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                TextMessage textMessage=(TextMessage)message;
                try {
                    System.out.println("接收到消息:"+textMessage.getText());
                } catch (JMSException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        //8.等待鍵盤輸入
        System.in.read();
        //9.關閉資源
        consumer.close();
        session.close();
        connection.close();

    }
}

發送方

package cn.itcast.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 點對點模式 發送方
 */
public class QueueProducer {
    public static void main(String[] args) throws Exception{
        //1.創建連接工廠
        ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.200.128:61616");
        //2.獲取連接
        Connection connection = connectionFactory.createConnection();
        //3.啓動連接
        connection.start();
        //4.獲取session  (參數1:是否啓動事務,參數2:消息確認模式)
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5.創建隊列對象,指定發送的隊列名稱,可以隨意起名,但發送到哪裏,就要從哪裏接收
        Queue queue = session.createQueue("test-queue");
        //6.創建消息生產者
        MessageProducer producer = session.createProducer(queue);
        //7.創建消息
        TextMessage textMessage = session.createTextMessage("歡迎來到神奇的品優購世界");
        //8.發送消息
        producer.send(textMessage);
        //9.關閉資源
        producer.close();
        session.close();
        connection.close();

    }
}

訂閱發佈

發送方發完數據之後,數據就被髮送出去了,如果接收方沒有提前啓動,則無法收到數據。

發送方

package cn.itcast.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 訂閱發佈模式:發送方
 */
public class TopicProducer {
    public static void main(String[] args) throws Exception{
        //1.創建連接工廠
        ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.200.128:61616");
        //2.獲取連接
        Connection connection = connectionFactory.createConnection();
        //3.啓動連接
        connection.start();
        //4.獲取session  (參數1:是否啓動事務,參數2:消息確認模式)
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5.創建主題對象
        Topic topic = session.createTopic("test-topic");
        //6.創建消息生產者
        MessageProducer producer = session.createProducer(topic);
        //7.創建消息
        TextMessage textMessage = session.createTextMessage("歡迎來到神奇的品優購世界");
        //8.發送消息
        producer.send(textMessage);
        //9.關閉資源
        producer.close();
        session.close();
        connection.close();

    }
}

n個接收方

package cn.itcast.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 訂閱發佈模式:接收方
 */
public class TopicConsumer1 {
    public static void main(String[] args) throws Exception{
//1.創建連接工廠
        ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.200.128:61616");
        //2.獲取連接
        Connection connection = connectionFactory.createConnection();
        //3.啓動連接
        connection.start();
        //4.獲取session  (參數1:是否啓動事務,參數2:消息確認模式)
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5.創建主題對象
        //Queue queue = session.createQueue("test-queue");
        Topic topic = session.createTopic("test-topic");
        //6.創建消息消費
        MessageConsumer consumer = session.createConsumer(topic);

        //7.監聽消息
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                TextMessage textMessage=(TextMessage)message;
                try {
                    System.out.println("接收到消息:"+textMessage.getText());
                } catch (JMSException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        //8.等待鍵盤輸入
        System.in.read();
        //9.關閉資源
        consumer.close();
        session.close();
        connection.close();

    }
}

如何保證消息服務器不丟消息

答: 我們使用的是activemq消息服務器, 它有兩種發送模式點對點和訂閱發佈

  • 點對點:
    不用管, 消息服務器有內部機制保證絕對不會丟數據.
    原理:
    發送方將消息發送給消息服務器後, 消息服務器會將隊列中的消息發送給接收方, 接收方接收到消息後會給消息服務器返回一個響應, 消息服務器接收到響應後認爲消息接收成功, 將隊列中這個發送完的消息刪除。
    如果消息服務器在一定時間內沒有接受到響應, 則認爲消息接收方宕機, 這個時候會將發送完的這個消息進行持久化保存, 如果消息接收方服務器重新啓動連接消息服務器, 消息服務器會監聽到, 會將之前持久化的消息重新發送給消息服務器.
  • 訂閱發佈:
    訂閱發佈模式沒有實現保證數據安全的機制, 如果消息服務器將消息發送給接收方, 接收方接收到就算接收到了,沒接收到就算丟了, 也不進行持久化.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章