ActiveMQのJDBC永続サブスクリプションの

JMS基本的な概念や規範

メッセージングドメイン(JMSドメイン)

また、メッセージモード、メッセージのモデルとして知られている、2種類があります。

  1. ピア(P2P)
    ここに画像を挿入説明

コンセプト

  • メッセージキュー(待ち行列)
  • プロバイダ(送信者)
  • 消費者(レシーバー)
  • 各メッセージは、特定のキューに送信され、受信機は、キューからメッセージを取得します。それは彼らが消費またはタイムアウトするまで、メッセージキューを保持します。

機能

  • 各メッセージには、唯一の消費者(コンシューマー)(すなわち、消費たら、メッセージがメッセージキューになくなりました)です
  • プロバイダーと消費者の間の時間に依存しない、プロバイダがメッセージを送信するときに消費者が何も実行されていないかどうか、それはメッセージがキューに送信されます影響しません、と言うことです
  • 各メッセージは、消費者に送信されます。そこキューリスニングで複数の消費者かもしれませんが、キュー内の各メッセージは、コンシューマ・キューによって消費することができます。
  • メッセージ内の順序があります。キューメッセージサーバキューへのメッセージの順序に応じて消費者に送信します。消費者がされている場合は、キューの先頭から(メッセージの優先順位がない限り)それらを削除します。
  • 成功するためにメッセージキューを受信することに成功した消費者の反応の後

2.パブリッシュおよびサブスクライブ(パブ/サブ)

ここに画像を挿入説明
コンセプト

  • テーマ(トピック)
  • パブリッシャー(出版社)
  • 加入者(加入者)

機能

  • 各メッセージには、複数のコンシューマを持つことができます
  • パブリッシャとサブスクライバの間の時間に依存してあります。トピックの加入後は、それが消費者に加入者、出版社のメッセージを作成する必要がありますし、メッセージを消費するために、加入者は、実行中の状態を維持しなければなりません。
  • そのような厳密な時間相関を緩和するために、JMSは、加入者が永続的なサブスクリプションを作成することができます。このように、加入者が実行されていない場合でも、それはまた、メッセージのパブリッシャを受け取ることができます。
  • 各メッセージには、複数のメッセージコンシューマと呼ばれる加入者に送信されます。
  • 出版社は通常、加入者がメッセージのトピックを受信して​​いるところのは意味わかりません。
  • メッセージが要求することなく、消費者に送信されることを意味し、消費者にプッシュメッセージ。

組成メッセージ(データフォーマット)

1.メッセージ・ヘッダ

メッセージは、識別情報とルーティング情報を含んでいます

2.消息体

  • TextMessage - Stringオブジェクト

  • MapMessage - 名前のセット - 値のペア

  • BytesMessageは - データ・ストリームの1つのバイト

  • StreamMessageの - フローデータのJavaの元の値

  • ObjectMessage - シリアル化されたJavaオブジェクト


配置详解:

从上可知:p2p模型和发布订阅(pub/sub)有个很大的区别就是时间上的依赖性的区别。p2p默认不依赖时间,而发布订阅需要创建一个可持久化的订阅。发布订阅模型默认自带了kahaDB 存储方式 (官方推荐。基于日志文件,5.4 之后的默认持久化)。无需配置。但是为了方便查看,这边改用jdbc来持久化订阅。下面提一下配置(linux上安装)。

第一步:引入3个jar包:

mysql(数据库驱动) 、HikariCP(连接池) 、slf4j(日志接口) , 放到 activemq安装目录下的lib文件夹下;

第二步:安装目录activemq/conf/activemq.xml 配置 dataSource
<!-- Hikari Datasource -->
    <bean id="activemq-mysql" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="close">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUrl"   value="jdbc:mysql://192.168.5.4:3306/activemq?serverTimezone=GMT%2B8"/>
        <property name="username" value="root" />
        <property name="password" value="1234" />
    </bean>
配置持久化
<persistenceAdapter>
  <!--默认配置 <kahaDB directory="${activemq.data}/kahadb"/> -->
<jdbcPersistenceAdapter dataSource="#activemq-mysql" createTablesOnStartup="true"/></persistenceAdapter>
第三步:先建好数据库(库名同上jdbc配置),再重启activeMQ;
第四步:成功,自动建表如下:
ACTIVEMQ_ ACKS : 存储持久订阅的信息

ACTIVEMQ_ LOCK : 锁表(集群使用)

ACTIVEMQ_ MSGS : 消息表

三个表详解:

activemq_acks:

用于存储订阅关系,如果是持久化的Topic,订阅者和服务器订阅关系在这个表保:主要的数据库字段如下
container:消息的Destination
sub_dest:如果是使用的Static集群,这个字段会有集群和其他系统的信息
client_id:订阅者都必须有一个唯一的客户端id用于区分
sub_name:订阅者名称
selector:选择器,可以选择只消费满足条件的消息,条件可以用自定义属性实现,可以支持多属性and和or操作
last_acked_id:记录消费过的消息id

activemq_lock

在集群环境中才有用,只有一个broker可以获得消息,称为Master Broker,其他的只能作为备份等待

activemq_msg:

メッセージを格納するために、Queneおよびトピックは、このテーブルに格納されている:
IDデータベース自動増分基本キー
コンテナを:宛先メッセージ
msgid_prod:送信側クライアント・メッセージ主キー
msg_seqは:注文メッセージであるメッセージIDされ、msgid_prod + msg_seqは、JMSから構成されてもよいです
有効期限:メッセージの有効期限、ミリ秒1970-01-01の数格納する
メッセージ:Javaのバイナリデータ列オブジェクトメッセージボディ
prioritry:0-9からの優先権、より大きな優先度の高いデータを

最後に、テストコードを添付:

瓶包

	<dependency>
         <groupId>org.apache.activemq</groupId>
         <artifactId>activemq-all</artifactId>
         <version>5.15.11</version>
    </dependency>

接続設定


public class MyConfig {
    //定义ActiveMQ的连接地址
    public static final String ACTIVEMQ_URL = "tcp://192.168.5.4:61616";
    //topic 队列名称
    public static final String TOPIC_NAME = "topic_01";
}

出版社

public class PersistentSender {
    public static void main(String[] args) throws JMSException {
        //创建连接工厂
        ConnectionFactory activeMQConnectionFactory =
                new ActiveMQConnectionFactory(MyConfig.ACTIVEMQ_URL);
        //创建连接
        Connection connection = activeMQConnectionFactory.createConnection();
        //打开连接
        connection.start();
        //创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列目标
        Destination destination = session.createTopic(MyConfig.TOPIC_NAME);
        //创建一个生产者
        MessageProducer producer = session.createProducer(destination);
        //发送消息时用使用持久模式(默认的,可写可不写)
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        //创建消息
        TextMessage message = session.createTextMessage("我是永恒的帅哥擦擦擦");
        //发送消息
        producer.send(message);
        //在本地打印消息
        System.out.println("我现在发的消息是:" + message.getText());
        //关闭连接
        connection.close();
    }
}

受信者

public class PersistentRecv01 {
    public static void main(String[] args) throws JMSException {
        String myId = "PersistentRecv01";
        //创建连接工厂
        ConnectionFactory activeMQConnectionFactory =
                new ActiveMQConnectionFactory(MyConfig.ACTIVEMQ_URL);
        //创建连接
        Connection connection = activeMQConnectionFactory.createConnection();
        //持久订阅
        connection.setClientID(myId);
        //打开连接
        connection.start();
        //创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列目标
        Topic topic = session.createTopic(MyConfig.TOPIC_NAME);
        //创建消费者
        MessageConsumer consumer = session.createDurableSubscriber(topic, myId);
        
        //接收消息(这里也可以用while循环)
        //textMessage = (TextMessage)consumer.receive(); 是一个阻塞队列
        //这里用监听器持续接收消息
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                TextMessage receive = (TextMessage)message;
                try {
                    System.out.println("PersistentRecv 111 : " + receive.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

公開された14元の記事 ウォンの賞賛0 ビュー316

おすすめ

転載: blog.csdn.net/qq_38205881/article/details/104483987