簡介
Apache ActiveMQ是Apache軟件基金會所研發的開放源代碼消息中間件;由於ActiveMQ是一個純Java程序,因此只需要操作系統支持Java虛擬機,ActiveMQ便可執行。
作用
- 應用解耦
- 異步通信
- 流量削峯
- 消息通訊
安裝
提供docker的安裝方式,其他方式網上也都有很多
與springboot整合
jar依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--如果參數配置pool爲true的話,需要引入下列依賴包-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
配置文件
spring:
# activemq
activemq:
broker-url: tcp://xxx:61616
user: admin
password: admin
pool:
enabled: true
max-connections: 100
packages:
#注意 對象傳輸需開啓包白名單 否則會報錯- -
trust-all: true
in-memory: true
# 自定義queue名稱
queue-name: gourd-queue
# 自定義topic名稱
topic-name: gourd-topic
jms:
# 開啓發布訂閱模式
pub-sub-domain: true
配置類
配置類加上@EnableJms註解,註冊重試、持久化配置bean
/**
* active消息隊列配置
* @author gour.hu
*/
@Configuration
@EnableJms
public class ActiveMqConfig {
/**
* 定義存放消息的隊列
* @return
*/
@Bean
public Queue queue(@Value("${spring.activemq.queue-name}")String queueName) {
return new ActiveMQQueue(queueName);
}
/**
* 發佈訂閱模式
* @return
*/
@Bean
public Topic topic(@Value("${spring.activemq.topic-name}")String topicName) {
return new ActiveMQTopic(topicName);
}
@Bean
public RedeliveryPolicy redeliveryPolicy(){
RedeliveryPolicy redeliveryPolicy= new RedeliveryPolicy();
// 啓用指數倍數遞增的方式增加延遲時間。
redeliveryPolicy.setUseExponentialBackOff(true);
// 重連時間間隔遞增倍數,只有值大於1和啓用useExponentialBackOff參數時才生效。默認5
redeliveryPolicy.setBackOffMultiplier(2);
// 最大重傳次數,達到最大重連次數後拋出異常。爲-1時不限制次數,爲0時表示不進行重傳。默認6
redeliveryPolicy.setMaximumRedeliveries(6);
// 重發時間間隔,默認爲1秒
redeliveryPolicy.setInitialRedeliveryDelay(5000L);
// 啓用防止衝突功能,因爲消息接收時是可以使用多線程併發處理的,應該是爲了重發的安全性,避開所有併發線程都在同一個時間點進行消息接收處理。
redeliveryPolicy.setUseCollisionAvoidance(true);
// 設置重發最大拖延時間-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 user, @Value("${spring.activemq.password}")String password,
RedeliveryPolicy redeliveryPolicy){
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory(user,password,url);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
return activeMQConnectionFactory;
}
@Bean
public JmsTemplate getJmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory,
MessageConverter jacksonJmsMessageConverter,@Value("${spring.jms.pub-sub-domain}")Boolean subAdmin){
//使用CachingConnectionFactory可以提高部分性能。
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setSessionCacheSize(100);
cachingConnectionFactory.setTargetConnectionFactory(activeMQConnectionFactory);
JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
//設置deliveryMode(持久化)
jmsTemplate.setExplicitQosEnabled(true);
// 設置消息是否持久化
jmsTemplate.setDeliveryPersistent(true);
// 設置消息轉換器
jmsTemplate.setMessageConverter(jacksonJmsMessageConverter);
// 設置消息是否以事務
jmsTemplate.setSessionTransacted(true);
jmsTemplate.setPubSubDomain(subAdmin);
return jmsTemplate;
}
/**
* topic模式的ListenerContainer
*
* @param activeMQConnectionFactory
* @return
*/
@Bean("jmsListenerContainerTopic")
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory activeMQConnectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer,@Value("${spring.application.name}")String applicationName) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, activeMQConnectionFactory);
// 設置消息轉換器
factory.setMessageConverter(jacksonJmsMessageConverter());
factory.setPubSubDomain(true);
factory.setSessionTransacted(true);
factory.setAutoStartup(true);
//開啓持久化訂閱
factory.setSubscriptionDurable(true);
factory.setClientId(applicationName);
return factory;
}
/**
* queue模式的ListenerContainer
* @param activeMQConnectionFactory
* @return
*/
@Bean("jmsListenerContainerQueue")
public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory activeMQConnectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, activeMQConnectionFactory);
// 設置消息轉換器
factory.setMessageConverter(jacksonJmsMessageConverter());
factory.setPubSubDomain(false);
return factory;
}
/**
* 消息轉換器
* @return
*/
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
}
提供者
/**
* 隊列消息控制器
* @author gourd.hu
*/
@RestController
@RequestMapping("/activeMq")
@Api(tags = "activeMq", description = "隊列消息控制器" )
public class ActiveMqController {
/**
* 注入存放消息的隊列,用於下列方法一
*/
@Autowired
private Queue queue;
/**
* 注入springboot封裝的工具類
*/
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@GetMapping("send")
@ApiOperation(value = "發送消息到隊列")
public BaseResponse send(@RequestParam("msg") String msg) {
jmsMessagingTemplate.convertAndSend(queue, msg);
return BaseResponse.ok("success!");
}
@Autowired
private Topic topic;
@GetMapping("/topic")
@ApiOperation(value = "發送消息到主題")
public BaseResponse handlerActiveMq(@RequestParam("msg")String msg) {
jmsMessagingTemplate.convertAndSend(topic, msg);
return BaseResponse.ok("success!");
}
}
消費者
@SendTo 加上此註解消費方法可以有返回值,否則只能爲void
/**
* 消息消費
*
* @author gourdhu
*/
@Component
@Slf4j
public class ConsumerService {
/**
* 使用JmsListener配置消費者監聽的隊列,其中name是接收到的消息
* @param message
* @return
*/
@JmsListener(destination = "gourd-queue",containerFactory = "jmsListenerContainerQueue")
@SendTo("SQueue")
public void handleMessage(final TextMessage message) throws JMSException {
log.info("queue-consumer收到的報文爲:" + message.getText());
}
@JmsListener(destination = "gourd-topic",containerFactory = "jmsListenerContainerTopic")
@SendTo("STopic")// 加上此註解可以有返回值,否則只能爲void
public void receiveTopic(final TextMessage message) throws JMSException {
log.info("topic-consumer收到的報文爲:" + message.getText());
// if(true){
// throw new BusinessException("測試消息重試");
// }
}
}
至此整合完成,經測試持久化和重試都是正常的。
===============================================
代碼均已上傳至本人的開源項目
spring-cloud-plus:https://blog.csdn.net/HXNLYW/article/details/104635673