今天简单的搭建了RabbitMQ环境,并整合了SpringBoot,中间遇到了许多坑,总算搭建成功了。
RabbitMQ介绍
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache).
环境搭建
安装RabbitMQ需要安装Erlang开发环境,这一步是最坑的,因为版本问题,Erlang可能不兼容RabbiMQ,博主尝试了许多版本终于安装成功。相应的版本对应关系看这里。博主使用的rabbimq版本为3.7.9,Erlang版本为21.0.1。
安装Erlang
去官网或者下载博主的安装包提取码a0a2,下载完一步一步next就行,然后配置环境变量ERL_HOME,变量值D:\Program Files\erl10.0.1(你的安装路径),添加到path%ERL_HOME%\bin。打开控制台输入erl:
安装rabbitmq
去官网或者下载博主的安装包提取码8ozw,下载完安装,一步步next下来就行。切换到安装目录的sbin目录下,启动rabbitmq-server.bat,
创建消息生产者
新建SpringBoot项目rabbitmq-producer,添加依赖
org.springframework.boot
spring-boot-starter-amqp
修改application.yml配置文件
server:
port: 8081
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
新建配置类ProducerConf
import com.rabbitmq.client.impl.AMQImpl.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ProducerConf {
@Bean
public Queue queue (){
return new Queue();
}
}
创建一个发消息的业务HelloService
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class HelloService {
@Autowired
private AmqpTemplate template;
public void send () {
template.convertAndSend("queue","hey, boys ^_^");
}
}
再创建一个运行发消息的线程
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class HelloServiceRunner implements ApplicationRunner {
@Autowired
private HelloService service;
@Override
public void run(ApplicationArguments args) throws Exception {
new Thread(() -> {
while (true) {
service.send();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
消息的生产者就写好了
创建消息消费者
同样新建SpringBoot项目rabbitmq-customer,配置文件
server:
port: 8082
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
创建HelleService的接收者HelloServiceReceive
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class HelloServiceReceive {
@RabbitListener(queues="queue") //监听器监听指定的Queue
public void process(String str) {
System.out.println("Receive:"+str);
}
}
启动customer会发现报错:
org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[queue]
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:710) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.passiveDeclarations(BlockingQueueConsumer.java:594) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:581) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.initialize(SimpleMessageListenerContainer.java:1196) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1041) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_201]
Caused by: java.io.IOException: null
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:126) ~[amqp-client-5.4.3.jar:5.4.3]
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:122) ~[amqp-client-5.4.3.jar:5.4.3]
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:144) ~[amqp-client-5.4.3.jar:5.4.3]
at com.rabbitmq.client.impl.ChannelN.queueDeclarePassive(ChannelN.java:1006) ~[amqp-client-5.4.3.jar:5.4.3]
at com.rabbitmq.client.impl.ChannelN.queueDeclarePassive(ChannelN.java:52) ~[amqp-client-5.4.3.jar:5.4.3]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler.invoke(CachingConnectionFactory.java:1110) ~[spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at com.sun.proxy.$Proxy64.queueDeclarePassive(Unknown Source) ~[na:na]
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:689) [spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]
... 5 common frames omitted
我们要先去管理端添加一个队列,队列名字要与监听器指定的相同
再次启动customer和proucer,会发现customer接收到了producer发送的消息:
说明整合成功了
这只是一个简单的demo,rabbitmq还有许多功能和特性待我去研究。