Java并发编程:02 -消息队列(MQ)springboot整合ActiveMQ整体流程版

消息队列是微服务之间通信(调度)的一个重要方式之一,这里只是做一个整合的笔记,因此不做过多的场景描述以及前提!!!

1.0 下载ActiveMQ以及安装并启动

http://activemq.apache.org/components/classic/download/

在这里插入图片描述
选择对应的版本下载即可

window 如何处理

步骤1:解压apache-activemq-5.15.10

步骤2:cmd 进入bin目录下

步骤3:输入命令:

activemq start

说明:步骤3可以替换为进入 \bin\win64\activemq.bat 双击即可

步骤4:观察控制台输出是否正常,如下图,你会看到8161的端口几乎是没什么问题的啦

在这里插入图片描述

步骤5:在浏览器输入:http://localhost:8161

步骤6:你会看到如下方的图片显示

在这里插入图片描述

步骤7:创建一个消息队列

在这里插入图片描述

linux 如何处理

主要流程和window类似(核心流程都在下方图,这是我的个人服务器整体操作流程)

在这里插入图片描述
其他的流程和window都一样了,然后如果 需要外网访问即可开发端口

2.0 springboot整合ActiveMQ (JmsMessagingTemplate模式)

2.1 导入相关依赖

build.gradle

// springboot 整合 activemq
compile group: 'org.springframework.boot', name: 'spring-boot-starter-activemq', version: '2.1.8.RELEASE'
// activemq连接池 (可选,如果不导入则在.properties修改对应的配置即可)
// compile group: 'org.apache.activemq', name: 'activemq-pool', version: '5.15.9'

2.2 添加配置

application-dev.properties

# activemq 配置
# true 表示使用内置的MQ,false则连接服务器
spring.activemq.in-memory=false
# 设置服务端地址
spring.activemq.broker-url=tcp://localhost:61616
# true表示使用连接池;false时,每发送一条数据创建一个连接
#spring.activemq.pool.enabled=true
# 连接池最大连接数
#spring.activemq.pool.max-connections=10
# 空闲的连接过期时间,默认为30秒
#spring.activemq.pool.idle-timeout=30000

2.3 编写主要核心类

TestMqHelper

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.TypeUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.jms.Destination;
import java.io.Serializable;

/**
 * @author houyu
 * @createTime 2019/10/29 23:35
 */
@Component
@Slf4j
public class TestMqHelper {

    /**
     * 生产者
     */
    @Service("producer")
    public static class TestMqProducer {

        /**
         * 定义发送消息目的地
         */
        private static final Destination testMqDestination = new ActiveMQQueue("test.queue");

        @Autowired
        private JmsMessagingTemplate jmsTemplate;

        /**
         * 发送消息
         *
         * @param dto 数据传输对象
         */
        public void sendMessage(final TestMqDTO dto) {
            String message = JSON.toJSONString(dto);
            log.info("{}, 发送信息:{}", testMqDestination.toString(), message);
            jmsTemplate.convertAndSend(testMqDestination, message);
        }

        /**
         * 消费者留言
         * 可以在这里进行重试机制的建立,也就是说消费者消费失败,记录还是继续往队列进行添加重试
         *
         * @param message
         */
        @JmsListener(destination = "test.return.queue")
        public void consumerMessage(String message) {
            log.info("生产者收到消费者反馈信息:{}", message);
            TestMqDTO dto = JSON.parseObject(message, TestMqDTO.class);
            Integer retry = TypeUtils.castToInt(dto.getRetry());
            if (retry != null && retry > 0) {
                dto.setRetry(--retry);
                this.sendMessage(dto);
                log.info("调用重试机制", message);
            }
        }
    }

    /**
     * 消费者
     */
    @Component
    private static class TestMqConsumer {

        @JmsListener(destination = "test.queue")
        @SendTo("test.return.queue")

        private String receiveQueue(String message) {
            TestMqDTO dto = JSON.parseObject(message, TestMqDTO.class);
            log.info("消费者收到生产者信息:{}", dto.toString());
            // 调用具体业务service进行消费信息
            // 约束消费成功需要把retry修改为0
            dto.setRetry(0);
            return JSON.toJSONString(dto);
        }
    }

    /**
     * 消息支持的类型
     * Supported message payloads are: String, byte array, Map<String,?>, Serializable object.
     */
    @Data
    public static class TestMqDTO implements Serializable {
        /** 重试次数(可以重试的次数, 不成功的话不修改, 由consumerMessage修改, 成功直接修改为0) */
        private Integer retry;
        /** 业务ID, 或者使用是业务实体DTO等 */
        private String businessId;
        /** 备注信息 */
        private String remark;
    }

}

2.4 编写测试接口

TestMqController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author houyu
 * @createTime 2019/10/29 23:48
 */
@RestController
public class TestMqController {

    @Autowired
    private TestMqHelper.TestMqProducer testMqProducer;


    @RequestMapping("/mq/activemq/test")
    public String testMq() {
        TestMqHelper.TestMqDTO testMqDTO = new TestMqHelper.TestMqDTO();
        testMqDTO.setRetry(3);
        testMqDTO.setBusinessId("123");
        testMqDTO.setRemark("没有备注信息~~");

        testMqProducer.sendMessage(testMqDTO);
        return "success";
    }

}

在学习的过程中,其实发现了很多了,其中就是多消费者消费问题

3.0 多消费者是什么情况(是否重复消费?)

场景 : 开启两个消费者,生产消息3条,看看是什么情况?

具体直接看图即可,并不会造成重复消费问题

在这里插入图片描述

4.0 短暂总结【后续还会深入学习MQ】

  • 目前发现是多消费者的情况,是由ActiveMQ维护单一消费的,相对比较友好(看具体业务场景)
  • 暂时只是完成了基本的整合以及应用,还有待深入了解其内部API相关的功能,应该还有比较强悍的应用场景,里边还有很多API都不知道什么情况。
  • 如何持久化到本地?
  • 如何多消费者多消费?如何多消费者积极消费?

在这里插入图片描述

并发编程是博主的学习记录,权当学习笔记,这里的记录有可能不精准甚至不准确,因此需要借阅请慎重!!!
深知并发的水很深,因此如果文章中有差错,还望指出更正,谢谢!!!
讨论:for.houyu@foxmail.com

发布了46 篇原创文章 · 获赞 13 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览