ActiveMQ 入门(三)——嵌入式 和 消息持久化方案

ActiveMQ 高级用法一、嵌入式MQ

在实际开发中,如果项目没能给太多资源,而现在业务中又需要用到MQ,可以考虑嵌入式MQ,嵌入式MQ不需要安装ActiveMQ,只需要导入相关依赖就可以

1、pom文件需导入依赖:(在前两篇关于MQ的依赖的基础上导入这个依赖)

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

2、首先启动一个嵌入式MQ的服务,代码如下:

public class EmbedMQ {
	
	public static void main(String[] args) throws Exception {
		
        BrokerService brokerService = new BrokerService();
        brokerService.setBrokerName("EmbedMQ");
        brokerService.addConnector("tcp://localhost:62000");
        brokerService.setManagementContext(new ManagementContext());
        brokerService.start();
	}
}

3、生产者端:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class EmbedJmsProducter {
		//默认连接用户名
	    private static final String USERNAME= ActiveMQConnection.DEFAULT_USER;
	    //默认连接密码
	    private static final String PASSWORD= ActiveMQConnection.DEFAULT_PASSWORD;
	    //默认连接地址
	    private static final String BROKEURL= "tcp://localhost:62000";
	    //发送的消息数量
	    private static final int SENDNUM = 10;

	    public static void main(String[] args) {
	        ConnectionFactory connectionFactory;
	        Connection connection = null;
	        Session session;
	        Destination destination;
	        MessageProducer messageProducer;

	      connectionFactory= new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
	        try {
	            connection = connectionFactory.createConnection();
	            connection.start();
	            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
	            //destination = session.createQueue("HelloWAM");
	            destination = session.createTopic("EmbedMQ");
	            messageProducer = session.createProducer(destination);
	            for (int i = 0; i < SENDNUM; i++) {
	                String msg = "内置MQ" + i + " " + System.currentTimeMillis();
	                TextMessage message = session.createTextMessage(msg);
	                System.out.println("发送消息:" + msg);
	                messageProducer.send(message);
	            }
	            session.commit();
	        } catch (JMSException e) {
	            e.printStackTrace();
	        } finally {
	            if (connection != null) {
	                try {
	                    connection.close();
	                } catch (JMSException e) {
	                    e.printStackTrace();
	                }
	            }
	        }
	    }
}

消费者端:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class EmbedJmsConsumer {
	
	 private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
     private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
     private static final String BROKEURL = "tcp://localhost:62000";

     public static void main(String[] args) {
    	 ConnectionFactory connectionFactory;//连接工厂
    	 Connection connection = null;//连接
    	 Session session;//会话 接受或者发送消息的线程
    	 Destination destination;//消息的目的地
    	 MessageConsumer messageConsumer;//消息的消费者
    	 //实例化连接工厂
    	 connectionFactory = new ActiveMQConnectionFactory(USERNAME,PASSWORD, BROKEURL);
    	 try {
    		 //通过连接工厂获取连接
    		 connection = connectionFactory.createConnection();
    		 //启动连接
    		 connection.start();
    		 //创建session
    		 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    		 //创建一个连接HelloWorld的消息队列
    		 destination = session.createTopic("EmbedMQ");

    		 //创建消息消费者
    		 messageConsumer = session.createConsumer(destination);
    		 messageConsumer.setMessageListener(new MessageListener() {
    		   public void onMessage(Message message) {
    			 try {
    			System.out.println("Accept msg : "+ ((TextMessage) message).getText());
    				 } catch (JMSException e) {
    					 e.printStackTrace();
    				 }
    			 }
    		 });
    	 } catch (JMSException e) {
    		 e.printStackTrace();
    	 }
     }
}

4、测试

先启动服务,在启动消费者,最后启动生产者发送消息。

ActiveMQ高级用法二、消息持久化方案:

生产环境中,ActiveMQ可能挂掉,为了保证挂掉后消息不丢失,需要对消息进行持久化,ActiveMQ提供几种解决方案。

1、AMQ:基于文件存储,它具有写入速度快和容易恢复的特点。消息存储在一个个文件中,文件的默认大小为32M,如果一条消息的大小超过了32M,那么这个值必须设置大一点。当一个存储文件中的消息已经全部被消费,那么这个文件将被标识为可删除,在下一个清除阶段,这个文件被删除。AMQ适用于ActiveMQ5.3之前的版本。

2、KahaDB消息存储-提供了容量的提升和恢复能力,是现在的默认存储方式;KahaDB是基于文件的本地数据库储存形式,虽然没有AMQ的速度快,但是它具有强扩展性,恢复的时间比AMQ短,从5.4版本之后KahaDB做为默认的持久化方式。由于是默认的存储方案,即便不做任何配置,ActiveMQ启动时,也会启动KahaDB。这种情况文件所在位置是ActiveMQ安装路径下的/data/KahaDB子目录

3、JDBC消息存储-消息基于JDBC存储的,将数据存到数据库中;这种不是默认配置,如果想使用要做如下配置                                

修改配置文件  conf/ActiveMQ.xml 
1.将:  
      <persistenceAdapter>
	      <kahaDB directory="${activemq.base}/data/kahadb"/>
      </persistenceAdapter>
修改为:
      <persistenceAdapter>
          <jdbcPersistenceAdapter  dataSource="#mysql-ds "/>
      </persistenceAdapter>

2.在</broker>标签后,增加数据源的配置:

 <bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" 
   destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=UTC"/>
        <property name="username" value="****"/>
        <property name="password" value="****"/>
        <property name="poolPreparedStatements" value="true"/>
    </bean>
其中数据库名activemq需要在mysql中提前创建好,relaxAutoCommit=true这个属性必须要有,其他属性根据自身数据库信息及业务配置

放入必须的jar包
将 mysql 的驱动包放到ActiveMQ/lib 包下,启动ActiveMQ,如果报错,查看data/activemq.log 文件,可能是缺少其他jar包,我启动时报错,根据启动日志显示缺少commons-dbcp2-2.5.0.jar和commons-pool2-2.5.0.jar这两个包,同样导入到ActiveMQ/lib目录下,再次启动,启动成功

查看数据库,发现多了三张表

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,其他的只能作为备份等待Master       Broker不可用,才可能成为下一个Master Broker。这个表用于记录哪个Broker是当前的Master Broker。

activemq_msgs用于存储消息,Queue和Topic都存储在这个表中。主要的数据库字段如下:                                                         id:自增的数据库主键                                                                                                                                                                       container:消息的destination                                                                                                                                                             msgid_prod:消息发送者客户端的主键                                                                                                                                             msg_seq:是发送消息的顺序,msgid_prod+msg_seq可以组成jms的messageid

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值