一、RabbitMQ的介绍
- 1、什么是MQ?
MQ(message queue):消息队列,存储消息的容器,用于分布式系统之间进行通信。 - 2、什么是AMQP?
AMQP(Advanced Message Queuing Protocol):高级消息队列协议,规定的接口:
connection:连接
channel:轻量级的connection
exchange:分发消息
queue:存储消息的容器 - 3、什么是RabbitMQ?
RabbitMQ[ˈræbɪt]是erlang语言编写的实现AMQP协议的消息中间件 - 4、为什么要使用RabbitMQ?(RabbitMQ的使用场景)?
解耦:a服务本来只调用b、c服务,若添加d服务无需修改a服务的源代码
异步:a服务把消息发送到mq,b、c服务接收消息后以异步的方式运行
削峰:按并发量慢慢拉取消息 - 5、启动器
spring-boot-starter-amqp
二、RbbitMQ的安装
- 1、安装erlang的语言环境
cd /usr/upload
rpm -ivh esl-erlang-17.3-1.x86_64.rpm --force --nodeps
rpm -ivh esl-erlang_17.3-1~centos~6_amd64.rpm --force --nodeps
rpm -ivh esl-erlang-compat-R14B-1.el6.noarch.rpm --force --nodeps
- 2、安装RabbitMQ
rpm -ivh rabbitmq-server-3.4.1-1.noarch.rpm
- 3、启动和关闭
service rabbitmq-server start
service rabbitmq-server status
chkconfig rabbitmq-server on
service rabbitmq-server stop
service rabbitmq-server restart
- 4、安装后台管理界面
rabbitmq-plugins enable rabbitmq_management
service rabbitmq-server restart
- 5、创建账户
rabbitmqctl add_user admin 1111
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
rabbitmqctl list_users
三、五种消息模型
- 1、simple消息模型
producer------------>|queue|----------->consumer
手动ack:
channel.basicConsume(, false, );//不自动ack
try {
... ...
channel.basicAck(envelope.getDeliveryTag(), false);//手动ack
}catch (Exception e){
e.printStackTrace();
}
问题:如何保证消费者把消息成功消费?手动ack(理论)
- 2、work消息模型
producer------------>|queue|----------->多consumer
能者多劳:
channel.basicQos(1);
问题:如何防止消息堆积?能者多劳+多consumer
-
3、fanout消息模型
bind
producer------------>exchange------------->|多queue|----------->多consumer注意:exchange只负责分发消息,若没有queue绑定到exchange则消息会丢失
-
4、direct消息模型
bind(routing key)
producer------------>exchange------------------------->|多queue|----------->多consumerrouting key:灵活控制消息分发
-
5、topic消息模型
bind(*.routing key.#)
producer------------>exchange------------------------------>|多queue|----------->多consumer通配符: #:匹配n个单词 *:匹配1个单词
四、rabbitmq的持久化
1、queue
channel.queueDeclare(, true, , , );
2、exchange
channel.exchangeDeclare(, , true);
3、消息
channel.basicPublish(, , MessageProperties.PERSISTENT_TEXT_PLAIN, );
问题:如何保证消费者把消息成功消费?
1、consumer业务会处理失败?手动ack
2、RabbitMQ会宕机?持久化
五、springboot整合rabbitmq
- 1、pom.xml
spring-boot-starter-amqp
spring-boot-starter-web
spring-boot-starter-test - 2、application.yml
spring:
rabbitmq:
host: 192.168.204.135
port: 5672
username: admin
password: 1111
virtual-host: /
- 3、Recver
@Component
public class Recver {
/**
* 接收消息的三要素:
* 1、queue
* 2、exchange
* 3、routing key
*/
@RabbitListener(bindings={@QueueBinding(
value = @Queue(value = "springboot_queue"),
exchange = @Exchange(value = "springboot_exchange", type = ExchangeTypes.TOPIC),
key = {"item.*"}
)})
public void listenMsg(String msg){
}
}
- 4、Sender
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {SpringbootRabbitMQApp.class})
public class Sender {
@Autowired
private AmqpTemplate amqpTemplate;
@Test
public void testSendMsg() throws InterruptedException {
String msg = "师姐你好!!!";
amqpTemplate.convertAndSend("springboot_exchange", "item.add", msg);
System.out.println("Sender for msg:" + msg);
Thread.sleep(100000);
}
}
- 5、手动ack
- application.yml
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: manual #前两种消息模型不自动ack
direct:
acknowledge-mode: manual #后三种消息模型不自动ack
- Recver
public void listenMsg(String msg, Channel channel, Message message){
try {
System.out.println("Recver for msg:" + msg);
int a = 6/0;
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}catch (Exception e){
e.printStackTrace();
}
}