消息队列是微服务之间通信(调度)的一个重要方式之一,这里只是做一个整合的笔记,因此不做过多的场景描述以及前提!!!
文章目录
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