ActiveMQ jdbc persistence of subscription

JMS basic concepts and norms

Messaging domains (JMS domains)

Also known as message mode, a message model, there are two kinds:

  1. Peer (p2p)
    Here Insert Picture Description

concept

  • Message queue (Queue)
  • Provider (Sender)
  • Consumers (Receiver)
  • Each message is sent to a particular queue, the receiver acquires the message from the queue. It retains the message queue until they are consumed or timeout.

Feature

  • Each message is only a consumer (Consumer) (ie, once consumed, the message is no longer in the message queue)
  • Between providers and consumers is not dependent on time, that is to say when the provider sends a message, whether consumers have no running, it will not affect the message is sent to the queue
  • Each message will be sent only to a consumer. There may be multiple consumers in a queue listening, but each message in the queue can only be consumed by a consumer queue.
  • There is order in the message. Queues a message server according to the order of the message into the queue and transmits them to the consumer. When the consumer has been, from the head of the queue will delete them (unless the message priority).
  • After a successful consumer response to receiving the message queue to be successful

2. publish and subscribe (pub / sub)

Here Insert Picture Description
concept

  • Theme (Topic)
  • Publisher (Publisher)
  • Subscribers (Subscriber)

Feature

  • Each message can have multiple consumers
  • There are dependent on the time between publishers and subscribers. After the subscribers for a topic, it must create a subscriber, the publisher's message to the consumer, and in order to consume the message, the subscriber must keep the state running.
  • In order to alleviate such strict time correlation, JMS allows subscribers to create a persistent subscription. Thus, even if the subscriber is not running, it can also receive the message publisher.
  • Each message will be sent to multiple message consumer called subscribers.
  • Publishers usually do not know, no sense of where a subscriber is receiving the message topic.
  • Message pushed to consumers, which means that the message will be sent to the consumer, without request.

Composition message (data format)

1. The message header

The message contains the identification information and routing information

2. news body

  • TextMessage - a String object

  • MapMessage - a set of name - value pairs

  • BytesMessage - one byte of data stream

  • StreamMessage - the original value of flow data Java

  • ObjectMessage - a serialized Java object


配置详解:

从上可知: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:

For storing messages, Quene and Topic are stored in this table:
ID database auto-increment primary key
container: Destination message
msgid_prod: sender client message primary key
msg_seq: is MessageID order message is, msgid_prod + msg_seq may be composed of JMS
expiration: expiration time of the message, to store the number of milliseconds 1970-01-01
msg: java binary data sequence object message body
prioritry: priority from 0-9, the larger the higher the priority data

Finally, attach the test code:

jar包

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

Connection Configuration


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";
}

announcer

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();
    }
}

Recipient

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();
                }
            }
        });
    }
}

Published 14 original articles · won praise 0 · Views 316

Guess you like

Origin blog.csdn.net/qq_38205881/article/details/104483987