消息队列RabbitMQ基础详解以及入门Demo

1 为什么要使用RabbitMQ

1.1 RabbitMQ基础

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

1.2 同步变异步

1.2.1 逐一流程

下图所示的是,流程是依次发送的,即:下订单->订单服务->发短信->发email->发push,所以时间很多
在这里插入图片描述

1.2.2 线程池

如下图所示,在订单服务中开启一个线程池,线程不在等待其他线程的结果,可以将同步转换为异步,但是不能解耦合
在这里插入图片描述

1.2.3 用MQ系统

如下图所示,使用消息队列,MQ系统,也可以把同步变为异步:当用户下订单后,MQ系统返回订单id,不在管MQ系统,其实MQ系统在和其他系统交互就和订单服务没有什么影响了
在这里插入图片描述

1.3 解耦合服务

使用MQ服务还可以解除彼此间的耦合
在这里插入图片描述

1.4 流量削锋

互联网的秒杀服务,如果巨大请求量发送到秒杀服务, 可能让服务器瘫痪,这时候用消息队列,接收处理巨大的请求,因为它不处理秒杀请求,所以还要给秒杀服务。这时候可以在消息队列里面设置一个阀值,如果达到某个请求,就不在发送给秒杀服务,而发送给其他服务了
在这里插入图片描述

2 消息队列基础知识

2.1 Provider

消息生产者, 就是投递消息的程序。

2.2 Consumer

消息消费者, 就是接受消息的程序。

2.3 没有使用消息队列时消息传递方式

在这里插入图片描述

2.4 使用消息队列后消息传递方式

在这里插入图片描述

2.5 什么是队列

队列就像存放了商品的仓库或者商店,是生产商品的工厂和购买商品的用户之间的中转站

2.6 队列里存储了什么

rabbitMQ中, 信息流从你的应用程序出发, 来到Rabbitmq的队列,所有信息可以只存储在一个队列中。 队列可以存储很多信息, 因为它基本上是一个无限制的缓冲区, 前提是你的机器有足够的存储空间。

2.7 队列和应用程序的关系

多个生产者可以将消息发送到同一个队列中, 多个消息者也可以只从同一个队列接收数据

3 入门案例

3.1 RabbitMQ配置文件

3.1.1 RabbitMQ的坐标

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

3.1.2 添加RabbitMQ相关的配置

# 给应用起一个名字
spring.applicatin.name=springcloud-mq
# RabbitMQ的安装地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的访问端口,和页面的15672端口不一样
spring.rabbitmq.port=5672
# RabbitMQ的用户名
spring.rabbitmq.username=admin
# RabbitMQ的密码
spring.rabbitmq.password=123456

3.2 代码部分

3.2.1 创建队列

@Configuration
public class QueueConfig {
	//@Bean 方法的名字是默认的id名字,因此不要使用get+方法名
	@Bean
	// 注意:Queue要使用:org.springframework.amqp.core.Queue
	public Queue createQueue() {
		return new Queue("test_mq");
	}
	 /**
     * 机器人消息重启插件消息队列所绑定的交换机
     */
    @Bean
    CustomExchange chatPluginDirect() {
        //创建一个自定义交换机,可以发送延迟消息
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(QueueEnum.QUEUE_RESET_MESSAGE_CANCEL.getExchange(), "x-delayed-message", true, false, args);
    }

    /**
     * 机器人消息重启插件队列
     */
    @Bean
    public Queue chatPluginQueue() {
        return new Queue(QueueEnum.QUEUE_RESET_MESSAGE_CANCEL.getName());
    }

    /**
     * 将机器人消息重启插件队列绑定到交换机
     */
    @Bean
    public Binding chatPluginBinding(CustomExchange chatPluginDirect, Queue chatPluginQueue) {
        return BindingBuilder
                .bind(chatPluginQueue)
                .to(chatPluginDirect)
                .with(QueueEnum.QUEUE_RESET_MESSAGE_CANCEL.getRouteKey())
                .noargs();
    }
}

3.2.2 创建消息提供者

@Component
public class QueueSender {

	@Autowired
	private AmqpTemplate amqpTemplate;
	//普通消息
	public void send (String msg) {
		//向消息队列发送消息
		//参数一: 队列的名称。
		//参数二: 消息
		this.amqpTemplate.convertAndSend("test_mq",msg);
	}
	//延迟消息
	public void sendMessageToChat(Long cmid, final long delayTimes) {
        //给延迟队列发送消息
        amqpTemplate.convertAndSend(QueueEnum.QUEUE_RESET_MESSAGE_CANCEL.getExchange(), QueueEnum.QUEUE_RESET_MESSAGE_CANCEL.getRouteKey(), cmid, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setHeader("x-delay", delayTimes);
                return message;
            }
        });
    }
}

3.2.3 消息接收者

@Component
public class QueueReciver {
	//此处的注解用来检测某一个特定队列是否变化
	@RabbitListener(queues="test_mq")
	public void reciver(String msg) {
		System.out.println("=====================");
		System.out.println(msg);
		System.out.println("=====================");
	}
}

3.2.4 测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes=AppAction.class)
public class QueueTest {
	@Autowired
	private QueueSender sender;
	/*
	* 测试消息队列
	*/
	@Test
	public void test(){
		this.sender.send("Hello RabbitMQ");
	}
}

3.3 链接拒绝报错

3.3.1 用户名密码错误

报错:
ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.
解决:

  • 仔细检查下账号密码是否正确
  • 登录后把如下的Can access virtual hosts 修改为/
    在这里插入图片描述

3.3.2 Centos虚拟机的主机名问题

3.3.2.1 Centos7 改主机名两个地方一致

对于Centos7要修改主机名保持的话,用hostnamectl
在这里插入图片描述
还有在/etc/hosts这个文件也要改一下
在这里插入图片描述

3.3.2.2 Centos6 改主机名两个地方一致

修改/etc/hosts下的文件
在这里插入图片描述
还有/etc/sysconfig/network下的文件
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值