消息中间件学习二之ActiveMQ

本文详细介绍了Apache ActiveMQ的安装、配置及使用,包括Springboot集成示例。深入探讨了消息类型(队列与主题)、生产者、Broker和消费者的特性,分析了消息持久化、生产者异步发送、消费者幂等性处理等关键点,并提到了ActiveMQ的集群和连接协议。最后总结了ActiveMQ的性能特点。
摘要由CSDN通过智能技术生成

一、安装

ActiveMQ是Apache旗下的一款消息中间实现,可以支持多语言客户端,也是一个老牌消息中间件实现,所以各项功能也相对成熟。
首先我们可以去官网下载所需要的版本
在这里插入图片描述
我这里用的是centos去安装的,下载好对应的版本即可。

下载完成之后解压:
在这里插入图片描述
启动ActiveMQ(进入到安装目录的bin目录下执行):
在这里插入图片描述
启动完成之后,就可以采用ip:8161/admin/html查看管理后台界面,默认账号密码都是admin。
在这里插入图片描述
此时我们就可以在我们的应用中使用ActiveMQ了,本文将使用Springboot来使用ActiveMQ。

二、样例

首先新建一个Springboo项目,然后引入ActiveMQ的jar包。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

配置文件:

spring:
  activemq:
    broker-url: tcp://192.168.0.11:61616
    user: admin
    password: admin
queue: active.test
@Configuration
public class Configure {
    @Value("${queue}")
    private String queue;
    @Bean
    public Queue logQueue() {
        return new ActiveMQQueue(queue);
    }
}

生产者:将每三秒钟发送一个消息到对应的队列中


@Component
@EnableScheduling
public class Producer {
    @Autowired
    private Queue logQueue;
    @Autowired
    private JmsMessagingTemplate  jmsTemplate;
    @Scheduled(fixedDelay = 3000)
    public void seedQueue() {
        jmsTemplate.convertAndSend(logQueue,"test for queue"+System.currentTimeMillis());
    }
}

消费者:消费者将不断的监听消息,然后打印消息

@Component
public class Consumer {
    @JmsListener(destination = "${queue}")
    public void receive(String msg) {
        System.out.println("receive from activemq:" + msg);
    }
}

以上是Springboot的一个简单案例,接下来我们按照传统方式来写一个代码如下:

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class TraditionalWay {
    private String BROKER="tcp://192.168.0.11:61616";
    private String queue="traditional.way";
    public void  producer() throws JMSException {
        ActiveMQConnectionFactory connectionFactory=new ActiveMQConnectionFactory("admin","admin",BROKER);
        Connection connection=connectionFactory.createConnection();
        connection.start();
        Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination=session.createQueue(queue);
        MessageProducer producer=session.createProducer(destination);
         int i=0;
        while (true){

           TextMessage message=session.createTextMessage();
           message.setText("traditional message send:"+i++);
            producer.send(message);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {

            }
        }
    }
    public void  consumer() throws JMSException {
        ActiveMQConnectionFactory connectionFactory=new ActiveMQConnectionFactory("admin","admin",BROKER);
        Connection connection=connectionFactory.createConnection();
        connection.start();
        Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination=session.createQueue(queue);
        MessageConsumer consumer=session.createConsumer(destination);

        while (true){
            TextMessage message=(TextMessage)consumer.receive();
            System.out.println("traditional message receive: "+message.getText());
        }
    }
    public static void main(String[] args) throws JMSException {
        TraditionalWay way=new TraditionalWay();
        new Thread(()->{
            try {
                way.producer();
            } catch (JMSException e) {
            }
        }).start();
        way.consumer();
    }
}

传统方式,完全按照第一部分中的顺序来执行,这就是一个标准的实现。此时我们再来看管理后台,两个队列分别有消息的产生和消费
在这里插入图片描述

三、深入分析

第一、二部分只是简单安装和初步使用了API,接下来分别从消息类型、生产者、broker、消费者四个角度来分析ActiveMQ。

1、消息类型
ActiveMQ中主要有两种模式,一种是队列(queue),一种是主题(topic)

队列是点对点模式,也就是一个消息只能是一个消费者消费,但是对于同一个队列,可以有多个生产者同时写入消息,以及多个消费者同时去消费消息
主题模式,就类似以发布/订阅模型,生产者,往对应主题上发送消息,消费者去消费对应主题消息,此时的消费者可以有多个(消费者消费的消息只有是在消费者订阅主题之后,生产者发送的消息才可以消费)

那么消息还可以分为持久化和非持久化方式,持久化方式也就是说在服务器重启之后,消息还存在,非持久化方式,消息保存在内存中,重启之后就会丢失(setDeliveryMode配置)。在ActiveMQ中可以配置持久化方式,在其配置文件中的< persistenceAdapter >节点即可,可以保存在硬盘上,也可以保存在数据库中。

那么此时会有个问题,比较服务器的内存是有限的,持久化数据存储在文件或者数据库中,非持久化数据存储在内存中,那么当非持久化数据达到内存不够用时,此时会怎样?
此时非持久化数据,会保持在一个临时文件中(文件大小可以配置),但是服务重启之后,临时文件的数据是不可以恢复的,也就是说非持久化数据是不可以恢复的。
不管是持久化文件还是临时文件都有一个最大值设置,如果持久化文件达到最大值之后,此时生产者会阻塞,消费者可以继续消费消息,相反如果非持久化的临时文件达到最大值,生产者会阻塞,所以在选择的时候尽量使用持久化方式。

2、生产者

从生产者角度来讲,我们需要关心什么问题呢?首先消息发送是否支持同步和异步,消息发送失败之后,是否有重试机制、是否发送了重复消息,消息发送大小限制,以及消息时批量发还是单个发送(吞吐量问题)。

(一)消息发送方式
ActiveMQ中基本上都是异步模式发送消息的,如果当前消息没有开启事务并且消息时持久化模式,那么会以同步发送,也就是说会等到服务端确认之后,才会继续执行,否则会进行阻塞,此时我们可以通过在连接参数上加上jms.useAsyncSend=true来使用异步方式发送,当消息以异步方式发送的时候,还可以设置一个回调接口来查看当前消息是否发送成功(CompletionListener实现这个接口),我们在发送消息的时候还可以设定当前消息的一个存活时间。

这里提到一个事务,我们在创建Session的时候,会设置两个参数一个是是否开启事务,另一个是响应机制,事务简单理解就是当前消息发送时候,因为某些原因需要回滚,这在ActiveMQ中是支持的,只需要开启事务即可也就是true,第二个参数就是消息签收模式,一般针对消费者。

(二)消息失败
当消息发送失败,之后会抛出异常,客户端可以根据异常信息进行一个消息重试,此时需要注意到当前消息是否会出现一个重发,如果出现重发了消费端需要对重复数据进行相应的幂等处理。

(三)消息大小

当消息以异步方式发送时,此时可以采用一个窗口大小(producerWindowSize配置来控制消息发送)。生产者每发送一个消息,就会统计当前消息字节,当生产者发送的消息达到窗口大小时,此时新消息不会继续发送,会等待服务器的响应,因为每发送一个消息服务端的内存就会增加对应的大小,如果没有及时消费的话,服务器响应之后,会返回一个size大小,也就是此时服务端的内存使用减少了size,所以窗口大小相应减少,此时就可以继续发送。

3、broker

broker就相当于一个ActiveMQ服务实例,也是存储消息和转发消息的核心所在,上边分析了消息的存储方式以及相应需要注意的事项。
关于broker还有一些连接协议概念,比如connector,我们在连接broker的时候会使用tcp://ip:port方式来进行,这也是ActiveMQ内嵌的一种方式。

如果查看ActiveMQ的配置文件会发现有如下配置(transport connector):
在这里插入图片描述
其中就有我们的tcp方式,我也可以配置udp\nio\http模式,修改对应的端口,然后连接的时候使用对应的协议即可。ssl是一种安全协议,transport connector是针对客户端到服务端的连接,那么broker-to-broker呢?

broker-to-broker就是ActiveMQ中集群通信方式(network connector),可以通过这项配置来实现集群功能。

4、消费者

消费者可以同步的获取消息,也可以异步的通过监听器来获取服务端消息,对于消费者来说,需要处理重复数据,以及数据消费完成之后的应答(可以自动和手动)。消费者端还可以创建一个持久订阅,这种方式只针对主题模式,当消费者宕机之后,恢复之后可以继续读取主题数据。针对消费者,当消息没有被正确消费,服务端会有一个重发机制(默认6次),或者消息过期都会被放到死信队列中,所以在系统中可以有两个队列来保证业务的正常使用,一个正常队列,一个死信队列,后者主要是用于处理异常情况,但是也需要注意消息的重复消费问题

四、总结

本文大致介绍了一下ActiveMQ的相关知识,ActiveMQ 的单机吞吐量在万级,可以支持ms级时效性,可用性高(集群),功能齐全。客户可以根据自身的需求进行选择。

以上,有任何不对的地方请指正,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟+1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值