前面一篇博文提到消息队列的三大作用:
(1)解耦
(2)异步
(3)削峰限流
当下主流的消息队列主要有Kafka、ActiveMQ、RabbitMQ、RocketMQ
rocketMq以其高吞吐量,支持分布式,可支撑大量的topic而成为一些公司的首选(实习的公司用的rocketMq),下面就做一个Springboot整合rocketMq的实践吧
unzip rocketmq-all-4.8.0-bin-release.zip
cd rocketmq-all-4.8.0-bin-release
nohup sh bin/mqnamesrv
nohup sh bin/mqbroker -n localhost:9876
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.apache.rocketmq
rocketmq-spring-boot-starter
2.2.0
org.projectlombok
lombok
在application.yml里引入rocketMq配置
rocketmq:
name-server: 127.0.0.1:9876
producer:
group: zju-rocket-mq
consumer:
group: zju-rocket-mq
@PostConstruct注解在服务器加载Servlet初始化生产者,配置jvm钩子函数优雅的关闭消息队列
@Service
public class Producer {
@Value("${rocketmq.producer.group}")
private String groupName;
@Value("${rocketmq.name-server}")
private String nameServerAddress;
private static DefaultMQProducer producer = null;
private static final Integer DEFAULT_TIMEOUT = 500;
@PostConstruct
public void init(){
producer = new DefaultMQProducer(groupName);
producer.setNamesrvAddr(nameServerAddress);
producer.setInstanceName("TestForProducer");
try {
producer.start();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
//钩子函数随jvm销毁关闭mq
@Override
public void run() {
producer.shutdown();
}
}));
} catch (MQClientException e) {
e.printStackTrace();
}
}
public static String sendMessage(String topic, String tag, String mes){
byte[] messageByte = mes.getBytes();
Message message = new Message(topic, tag, messageByte);
SendResult sendResult = null;
try {
sendResult = producer.send(message);
} catch (MQClientException e) {
e.printStackTrace();
} catch (RemotingException e) {
e.printStackTrace();
} catch (MQBrokerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return sendResult.getMsgId();
}
}
@PostConstruct初始化消费者,消费者订阅topic配置相应的handler
@Service
public class Consumer {
@Value("${rocketmq.producer.group}")
private String groupName;
@Value("${rocketmq.name-server}")
private String nameServerAddress;
@Autowired
private TestHandler handler;
@PostConstruct
public void init(){
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(groupName);
consumer.setNamesrvAddr(nameServerAddress);
consumer.registerMessageListener(handler);
consumer.setInstanceName("TestForConsumer");
try {
consumer.subscribe("topic", "tag");
consumer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
}
}
TestHandler实现MessageListenerConcurrently接口,覆写consumeMessage方法
@Slf4j
@Service
public class TestHandler implements MessageListenerConcurrently {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
if(list == null || list.isEmpty()){
log.info("the message received is empty");
}
log.info("receive message, start to consume");
try{
for(MessageExt msg:list){
String body = new String(msg.getBody(),"UTF-8");
log.info("the topic={},the message={}",msg.getTopic(),body);
}
}catch(UnsupportedEncodingException e){
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
}
@RestController
@RequestMapping("/test")
public class TestController {
@PostMapping("/writeMessage")
public void writeMessage() throws InterruptedException {
Producer.sendMessage("topic", "tag", "hello, RocketMq");
}
}
gitHub地址:github