ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。
消息队列的主要作用是为了解决高并发访问高峰,加快响应速度。一般情况下,不用消息队列,客户端来的请求会直接写入数据库,在访问高峰期,高并发的情况下,会对数据库访问造成压力,响应发生延迟,造成数据库访问的瓶颈。使用队列后,用户的请求发给队列后会立刻返回,之后再由消息队列的消费者进程监听对应的队列,从消息队列中获取数据,异步写入数据库。消息队列的服务处理速度远快于数据库,因此用户的响应延迟可得到有效改善。
(摘自https://blog.csdn.net/d124939312/article/details/71214180)
一、下载安装ActiveMQ
1、到官网下载软件:http://activemq.apache.org/download.html。
2、将下载得到的压缩包解压到你喜欢的目录(也可以重命名文件夹名)。
3、运行。
刚开始启动的时候遇到一个问题:java.net.URISyntaxException: Illegal character in hostname at index 6: ws://z_hh:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600。
原因是我的计算机名包含了下划线,改一下就好了。
4、打开浏览器访问http://ip:8161/admin,用户名密码都是admin。
二、Spring Boot整合ActiveMQ
1、引入ActiveMQ的maven依赖(使用boot-starter不需要版本号,它会自动选择最合适的版本)。
<!-- ActiveMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
2、配置。
application.yml
JmsConfig.java
目的地:
// 目的地
@Value("${activemq.queueDestination}")
private String queueDestination;
@Value("${activemq.topicDestination}")
private String topicDestination;
@Bean
public Destination queueDestination() {
return new ActiveMQQueue(queueDestination);
}
@Bean
public Destination topicDestination() {
return new ActiveMQTopic(topicDestination);
}
连接工厂和重发机制:
@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("${spring.activemq.broker-url}") String url,
@Value("${spring.activemq.user}") String username,
@Value("${spring.activemq.password}") String password,
RedeliveryPolicy redeliveryPolicy){
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory(username, password, url);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
return activeMQConnectionFactory;
}
JmsTemplate:
@Bean
public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory){
JmsTemplate jmsTemplate=new JmsTemplate();
jmsTemplate.setDeliveryMode(2);//进行持久化配置 1表示非持久化,2表示持久化
jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
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;
}
@Bean
public JmsListenerContainerFactory<?> jmsTopicListenerContainerFactory(ActiveMQConnectionFactory activeMQConnectionFactory) {
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(activeMQConnectionFactory);
factory.setPubSubDomain(true);
return factory;
}
3、队列消息
生产者
/**
* 生产者
* @author z_hh
* @time 2018年8月3日
*/
@Component
public class Producer {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
public void sendMsg(Object message) throws JsonProcessingException {
String jsonStr = mapper.writeValueAsString(message);
System.out.println("======>>>发送queue消息:" + jsonStr);
jmsMessagingTemplate.convertAndSend(queueDestination, jsonStr);
}
@Autowired
private ObjectMapper mapper;
@Resource
private Destination queueDestination;
}
消费者
@Component
public class Consumer {
@JmsListener(destination = "${activemq.queueDestination}")
public void receiveMsg(String text) {
System.out.println("<<<======收到queue消息:" + text);
}
}
测试
@GetMapping("/queue/send")
public String sendQueueMsg(@RequestParam String msg) throws JsonProcessingException {
producer.sendMsg(msg);
Student student = new Student();
student.setId(1);
student.setName("周煌华");
student.setMobile("15682568083");
producer.sendMsg(student);
return "发送成功!";
}
结果
4、主题模式
发布者
@Component
public class Publisher {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
public void publish(String message) {
System.out.println("======>>>发布topic消息:" + message);
jmsMessagingTemplate.convertAndSend(topicDestination, message);
}
@Resource
private Destination topicDestination;
}
订阅者
@Component
public class Subscriber {
@JmsListener(destination = "${activemq.topicDestination}", containerFactory = "jmsTopicListenerContainerFactory")
public void subscribe(String text) {
System.out.println("<<<======收到topic消息:" + text);
}
}
测试
@GetMapping("/topic/send")
public String sendMsg(@RequestParam String msg) {
publisher.publish(msg);
return "发送成功!";
}
结果