ActiveMQ安装、详解、SpringBoot集成

一、ActiveMQ安装

1、下载地址
http://activemq.apache.org/download-archives.html 
2、目录结构

apache-activemq-5.9.1
├─bin(启动脚本)
│ ├─win32
│ └─win64
├─conf(配置文件)
├─data(日志文件)
├─docs(说明文档)
├─example(例子:包括配置文件、代码)
│ ├─conf
│ ├─perfharness
│ ├─ruby
│ ├─src
│ └─transactions
│ └─src
├─lib(activemq用到的jar包)
│ ├─camel
│ ├─extra
│ ├─optional
│ └─web
└─webapps(管理台的应用)
├─admin
│ ├─decorators
│ ├─images
│ ├─js
│ │
│ ├─META-INF
│ ├─styles
│ ├─test
│ ├─WEB-INF
│ │
│ └─xml
├─demo
│ ├─js
│ ├─META-INF
│ ├─portfolio
│ ├─sandbox
│ ├─test
│ │
│ ├─WEB-INF
│ └─websocket
├─fileserver
│ ├─META-INF
│ └─WEB-INF

└─styles

3、windows启动

双击\apache-activemq-X.X.X\bin\win64\activemq.bat

4、linux启动
tar -zxvf apache-activemq-X.X.X-bin.tar.gz
cd apache-activemq-X.X.X/bin/linux-x86-64/
./activemq start
5、访问

http://localhost:8161/admin
默认用户名密码为admin、admin,后便可看到如下图的ActiveMQ控制台界面了

6、界面详解

ActiveMQ安装、详解、SpringBoot集成_第1张图片

二、ActiveMQ理论基础

1、分类

1)Point-to-Point Messaging Domain(点对点通信模型)
在点对点通信模式中,应用程序由消息队列,发送方,接收方组成。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
特点:

  • 每个消息只要一个消费者
  • 接收方在接收完消息之后,需要向消息队列应答成功
  • 发送方不管是否在发送消息,接收方都可以从消息队列中去到消息(The receiver can fetch message whether it is running or not when the sender sends the message)
  • 发送者和接收者在时间上是没有时间的约束,也就是说发送者在发送完消息之后,不管接收者有没有接受消息,都不会影响发送方发送消息到消息队列中。
    ActiveMQ安装、详解、SpringBoot集成_第2张图片
    2)Publish/Subscribe Messaging Domain(发布/订阅通信模型)
    在发布/订阅消息模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端。该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。
    特点:

  • 一个消息可以传递个多个订阅者(即:一个消息可以有多个接受方)

  • 发布者与订阅者具有时间约束,针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
  • 为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。
    ActiveMQ安装、详解、SpringBoot集成_第3张图片
2、概念

1)消息中间件(JMS Provider) : 指提供了对JMS协议的第三方组件,比如ActiveMQ就是一个消息中间件,另外比较知名的还有KFA, Rabbit MQ等。
2)消息模式:分为点对点(Point to Point,即P2P)和发布/订阅(Pub/Sub),对应的数据结构分别是队列(Queue)和主题(Topic)
3)消息(Message): 通信内容的载体,其结构主要分为消息头,属性和消息体,并且根据存储结构的不同分为好几种。
4)消息生产者:产生消息的一方,在P2P模式下,指消息发送者(Sender),在P/S模式下指消息发布者(Publisher)
5)消息消费者:接收消息的一方,对应于两种模式分别是消息接收者(Receiver)和消息订阅者(Subscriber)
在JMS的标准协议里,有几个重要的接口,先简单罗列如下:
1)ConnectionFactory :创建Connection的工厂,通过这个对象来创建一个到某个消息服务的连接。
2)Connection: 一个具体的连接,由ConnectionFactory创建
3)Session: 由Connection创建的用于操作消息的接口,本接口可以直接用来创建消息的生产者对象
4)Destination:消息存储的位置,发送者把消息发送到指定位置,消费者从指定位置取消息,那么这个指定位置可能是一个topic也可能是一个queue,由这个来表示。
5)MessageProducer: 消息的生产者,包括QueueSender和TopicPublisher
6)MessageConsumer: 消息的消费者, 包括QueueReceiver和TopicSubscriber
7)MessageListener: 消息监听器,这个是提供给消费者监听消息使用的,在添加了某个监听器之后,一旦消费到达,则会调用其onMessage方法。

3、常用代码
//链接工厂
ActiveMQConnectionFactory connectionFactory = null;

//链接对象
Connection connection = null;
connectionFactory = new ActiveMQConnectionFactory("admin","admin","tcp://192.168.1.111:61616");
connection = connectionFactory.createConnection();

connection.start();

//第一个参数是否开启事务 true开启 ,false不开启事务,如果开启记得手动提交
//参数二,表示的是签收模式,一般使用的有自动签收和客户端自己确认签收
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);



//JMS消息生产者
Queue queue = session.createQueue("test_queue");
//为队列创建消息生产者
MessageProducer producer = session.createProducer(queue);

Destination destination = session.createQueue("test-queue");
//为目的地创建消息生产者
MessageProducer producer = session.createProducer(destination);

//创建话题
Topic topic = session.createTopic("myTopic.messages"); 
//为话题创建消息生产者
MessageProducer producer = session.createProducer(topic); 

//创建消息
TextMessage message = session.createTextMessage();
message.setText("测试队列消息"+i);
//发送消息到目的地
producer.send(message);



//JMS消息消费者
//队列(目的地,消费者消费消息的地方)
Queue queue = session.createQueue("test_queue"); 
//消息消费者
MessageConsumer consumer = session.createConsumer(queue); 

//消息目的地
Destination destination = session.createQueue("test-queue");
//消息消费者
MessageConsumer consumer = session.createConsumer(destination);

//创建话题
Topic topic = session.createTopic("myTopic.messages"); 
//为话题创建消费者
MessageConsumer consumer = session.createConsumer(topic); 



//JMS消息监听器
consumer.setMessageListener(new MessageListener(){
    @Override
    public void onMessage(Message message) {
        //TestBean tbean =(TestBean)((ObjectMessage)message).getObject();
        TextMessage textMessage = (TextMessage)message;
        try {
            String value = textMessage.getText();
            System.out.println("value: "+value);
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
});
4、消息组成

1)消息头
JMS消息头预定义了若干字段用于客户端与JMS提供者之间识别和发送消息,预编译头如下:

  • JMSDestination : 消息发送的目的地,主要是指Queue和Topic,由session创建而由生产者的send方法设置.
  • JMSDeliveryMode:传送模式:有两种即久模式和非持久模式。一条持久性的消息应该被传输”一次仅仅一次”,这就意味着如果JMS提供者出现故障,该消息并不会丢失,它会在服务器恢复之后再次传递。一条非持久的消息最多会传递一次,这意味着服务器出现故障,该消息将永远丢失。由session穿件由消息生产者的send方法设置
  • JMSMessageID:唯一识别每个消息的标识,由JMS消息生产者产生。由send方法设置
  • JMSTimestamp:一个JMS Provider在调用send()方法时自动设置,它是消息被发送和消费者实际接收的时间差。由客户端设置
  • JMSCorrelationID:用来连接到另外一个消息,典型的应用是在回复消息中连接到原消息。在大多数情况下,JMSCorrelationID用于将一条消息标记为对JMSMessageID标示的上一条消息的应答,不过,JMSCorrelationID可以是任何值,不仅仅是JMSMessageID。由客户端设置
  • JMSReplyTo:提供本消息回复消息的目的地址,由客户端设置
  • JMSRedelivered:如果一个客户端收到一个设置了JMSRedelivered属性的消息,则表示可能客户端曾经在早些时候收到过该消息,但并没有签收(acknowledged)。如果该消息被重新传送,JMSRedelivered=true 否则 JMSRedelivered=flase 。由JMS Provider设置
  • JMSType:消息类型的标识符,由客户端设置
  • JMSExpiration:消息过期时间,等于Destination的send方法中的timeToLive值加上发送时刻的GMT的时间值。如果timeToLive值等于零,则JMSExpiration被设置为零,表示该消息永不过期。如果发送后,在消息过期时间之后消息还没有被发送到目的地,则该消息被清除。由send方法设置
  • JMSPriority:消息优先级,从0-9十个级别,0-4是普通消息,5-9是加急消息。JMS不要求JMS Provider严格按照这十个优先级发送消息,但必须保证加急消息要先于普通消息到达,默认是4级。由send方法设置

一个消息的消息头有这些属性,我们可以按照需要对这个消息的消息进行设计,在将这个消息使用消息生产者的send()方法发送到消息服务上。

2)消息属性
我们可以给消息设置自定义属性,这些属性主要是提供给应用程序的。对于实现消息过滤功能,消息属性非常有用,JMS API定义了一些标准属性,JMS服务提供者可以选择性的提供部分标准属性。

3)消息体
在消息体中,JMS API定义了五种类型的消息格式,让我们可以以不同的形式发送和接受消息,并提供了对已有消息格式的兼容。不同的消息类型如下:

  • Text message : javax.jms.TextMessage,表示一个文本对象。
  • Object message : javax.jms.ObjectMessage,表示一个JAVA对象。
  • Bytes message : javax.jms.BytesMessage,表示字节数据。
  • Stream message :javax.jms.StreamMessage,表示java原始值数据流。
  • Map message : javax.jms.MapMessage,表示键值对。

三、ActiveMQ应用

1、依赖
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-activemqartifactId>
dependency>
2、YML
spring:
  jms:
    pub-sub-domain: false   # 配置消息的类型,如果是true则表示为topic消息,如果为false表示Queue消息
  activemq:
    user: admin    # 连接用户名
    password: admin   # 连接密码
    broker-url: tcp://localhost:61616 # 消息组件的连接主机信息

补充:

spring.activemq.broker-url=tcp://127.0.0.1:61616
#集群配置
#spring.activemq.broker-url=failover:(tcp://172.18.1.188:61616,tcp://172.18.1.18:61616) 
# 在考虑结束之前等待的时间
#spring.activemq.close-timeout=15s 
# 默认代理URL是否应该在内存中。如果指定了显式代理,则忽略此值。
spring.activemq.in-memory=true 
# 是否在回滚回滚消息之前停止消息传递。这意味着当启用此命令时,消息顺序不会被保留。
spring.activemq.non-blocking-redelivery=false
# 密码
spring.activemq.password=123456
# 等待消息发送响应的时间。设置为0等待永远。
spring.activemq.send-timeout=0
spring.activemq.user=haha
# 是否信任所有包
#spring.activemq.packages.trust-all=
# 要信任的特定包的逗号分隔列表(当不信任所有包时)
#spring.activemq.packages.trusted=
# 当连接请求和池满时是否阻塞。设置false会抛“JMSException异常”。
#spring.activemq.pool.block-if-full=true
# 如果池仍然满,则在抛出异常前阻塞时间。
#spring.activemq.pool.block-if-full-timeout=-1ms
# 是否在启动时创建连接。可以在启动时用于加热池。
#spring.activemq.pool.create-connection-on-startup=true
# 是否用Pooledconnectionfactory代替普通的ConnectionFactory。
#spring.activemq.pool.enabled=false 
# 连接过期超时。
#spring.activemq.pool.expiry-timeout=0ms
# 连接空闲超时
#spring.activemq.pool.idle-timeout=30s
# 连接池最大连接数
#spring.activemq.pool.max-connections=1
# 每个连接的有效会话的最大数目。
#spring.activemq.pool.maximum-active-session-per-connection=500
# 当有"JMSException"时尝试重新连接
#spring.activemq.pool.reconnect-on-exception=true
# 在空闲连接清除线程之间运行的时间。当为负数时,没有空闲连接驱逐线程运行。
#spring.activemq.pool.time-between-expiration-check=-1ms
# 是否只使用一个MessageProducer
#spring.activemq.pool.use-anonymous-producers=true
3、定义队列|主题
import javax.jms.Queue;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;

@Configuration
@EnableJms
public class ActiveMQConfig {
    /**
     * 定义点对点队列
     * @return
     */
    @Bean
    public Queue queue() {
        return new ActiveMQQueue("msg.queue") ;
    }

    /**
     * 定义一个主题
     * @return
     */
    @Bean
    public Topic topic() {
        return new ActiveMQTopic("msg.topic");
    }
}
4、定义生产者
import javax.annotation.Resource;
import javax.jms.Queue;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import cn.mldn.microboot.producer.IMessageProducerService;

@Service
public class MessageProducerServiceImpl implements IMessageProducerService {
    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Resource
    private Queue queue;
    @Override
    public void sendMessage(String msg) {
        this.jmsMessagingTemplate.convertAndSend(this.queue, msg);
    }

}
5、定义消费者
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

@Service
public class MessageConsumerService {
    @JmsListener(destination="mldn.msg.queue")
    public void receiveMessage(String text) {   // 进行消息接收处理
        System.err.println("【*** 接收消息 ***】" + text);
    }
}
补充;
@EnableJms  
@Configuration  
public class ActiveMQ4Config {  

    @Bean
    public Queue queue(){
        return new ActiveMQQueue("queue1");

    }

    @Bean
    public RedeliveryPolicy redeliveryPolicy(){
            RedeliveryPolicy  redeliveryPolicy=   new RedeliveryPolicy();
            //是否在每次尝试重新发送失败后,增长这个等待时间
            redeliveryPolicy.setUseExponentialBackOff(true);
            //重发次数,默认为6次   这里设置为10次
            redeliveryPolicy.setMaximumRedeliveries(10);
            //重发时间间隔,默认为1秒
            redeliveryPolicy.setInitialRedeliveryDelay(1);
            //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
            redeliveryPolicy.setBackOffMultiplier(2);
            //是否避免消息碰撞
            redeliveryPolicy.setUseCollisionAvoidance(false);
            //设置重发最大拖延时间-1 表示没有拖延只有UseExponentialBackOff(true)为true时生效
            redeliveryPolicy.setMaximumRedeliveryDelay(-1);
            return redeliveryPolicy;
    }

    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory (@Value("${activemq.url}")String url,RedeliveryPolicy redeliveryPolicy){  
        ActiveMQConnectionFactory activeMQConnectionFactory =  
                new ActiveMQConnectionFactory(
                       "admin",
                        "admin",
                        url);
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        return activeMQConnectionFactory;

    }

    @Bean
    public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory,Queue queue){
        JmsTemplate jmsTemplate=new JmsTemplate();
        jmsTemplate.setDeliveryMode(2);//进行持久化配置 1表示非持久化,2表示持久化
        jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
        jmsTemplate.setDefaultDestination(queue); //此处可不设置默认,在发送消息时也可设置队列
        jmsTemplate.setSessionAcknowledgeMode(4);//客户端签收模式
        return jmsTemplate;
    }

    //定义一个消息监听器连接工厂,这里定义的是点对点模式的监听器连接工厂
    @Bean(name = "jmsQueueListener")
    public DefaultJmsListenerContainerFactory jmsQueueListenerContainerFactory(ActiveMQConnectionFactory activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory factory =
    new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(activeMQConnectionFactory);
        //设置连接数
        factory.setConcurrency("1-10");
        //重连间隔时间
        factory.setRecoveryInterval(1000L);
        factory.setSessionAcknowledgeMode(4);
        return factory;
    }

}  


你可能感兴趣的:(ActiveMQ安装、详解、SpringBoot集成)