【Spring Boot 7,【原理+实战+视频+源码】

消息推送使用的通道。

3、RoutingKey(路由键)


用于把生产者的数据分配到交换器上。

4、Exchange(交换器)


用于接受、分配消息。

5、BindKey(绑定键)


用于把交换器的消息绑定到队列上

6、Queue(队列)


用于存储生产者的消息。

五、RabbitMQ的适用场景

===============

1、异步处理


场景说明:用户注册后,需要发送注册邮件和注册短信。

传统的做法有两种,①串行的方式;②并行的方式;

(1)串行方式

将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个动作顺序完成后才返回给客户端。

这种方式的问题是发送注册邮件和发送注册短信不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西,影响用户体验。

(2)并行方式

将注册信息写入数据库后,发送邮件的同时,发送短信,以上三种操作都完成后,返回给客户端,并行的方式能缩短处理的时间。

假设三种业务节点分别使用50ms,串行方式就是150ms,并行方式就是100ms。

虽然并行已经缩短了处理时间,但是前面说过,邮件和短信不是必须的,没有必要让客户等待响应,应该是写入数据库就直接返回。

(3) 消息队列RabbitMQ

引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后,响应时间大幅度缩减。

2、应用解耦


(1)场景

双11是购物狂欢节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统接口。

(2)缺点

由于订单系统和库存系统的高耦合,当库存系统出现故障时,订单就会失败。

(3)引入消息队列RabbitMQ

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:订阅下单的消息,获取下单消息,进行库操作。就算库存系统出现故障,消息队列也能保证订单消息的可靠传递,不会导致消息丢失。

3、流量削峰


流量削峰一般在秒杀活动中应用广泛

场景:秒杀活动,一般因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。

(1)作用

① 可以控制活动人数,超过此阈值的订单直接丢弃。一般秒杀就是这个原理。

② 可以缓解短时间内的高流量压垮应用(应用程序按照自己的最大处理能力获取订单)。

(2)用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面。

(3)秒杀业务根据消息队列中的请求信息,再做后续处理。

六、springboot集成RabbitMQ

======================

Spring Boot 集成 RabbitMQ 非常简单,如果只是简单的使用配置非常少,Spring Boot 提供了spring-boot-starter-amqp项目对消息各种支持。

1、pom.xml



<dependency>

	<groupId>org.springframework.boot</groupId>

	<artifactId>spring-boot-starter-amqp</artifactId>

</dependency>

2、配置 RabbitMQ 的安装地址、端口以及账户信息



spring.application.name=Spring-boot-rabbitmq

spring.rabbitmq.host=192.168.0.86

spring.rabbitmq.port=5672

spring.rabbitmq.username=admin

spring.rabbitmq.password=123456

3、队列配置



@Configuration

public class RabbitConfig {



    @Bean

    public Queue Queue() {

        return new Queue("hello");

    }

}

4、发送者


rabbitTemplate 是 Spring Boot 提供的默认实现


@component

public class HelloSender {

	@Autowired

	private AmqpTemplate rabbitTemplate;



	public void send() {

		String context = "hello " + new Date();

		System.out.println("Sender : " + context);

		this.rabbitTemplate.convertAndSend("hello", context);

	}

}

5、接收者



@Component

@RabbitListener(queues = "hello")

public class HelloReceiver {



    @RabbitHandler

    public void process(String hello) {

        System.out.println("Receiver  : " + hello);

    }

}

6、测试



@RunWith(SpringRunner.class)

@SpringBootTest

public class RabbitMqHelloTest {



	@Autowired

	private HelloSender helloSender;



	@Test

	public void hello() throws Exception {

		helloSender.send();

	}

}

发送者和接收者的queue name必须一致,否则不能接收

七、多对多使用

=======

一个发送者,N个接收者或者N个发送者和N个接收者会出现什么情况呢?

1、一对多发送


对上面的代码进行了小改造,接收端注册了两个 Receiver,Receiver1 和 Receiver2,发送端加入参数计数,接收端打印接收到的参数,下面是测试代码,发送一百条消息,来观察两个接收端的执行效果


@Test

public void oneToMany() throws Exception {

	for (int i=0;i<100;i++){

		neoSender.send(i);

	}

}

结果如下:


Receiver 1: Spring boot neo queue ****** 11

Receiver 2: Spring boot neo queue ****** 12

Receiver 2: Spring boot neo queue ****** 14

Receiver 1: Spring boot neo queue ****** 13

Receiver 2: Spring boot neo queue ****** 15

Receiver 1: Spring boot neo queue ****** 16

Receiver 1: Spring boot neo queue ****** 18

Receiver 2: Spring boot neo queue ****** 17

Receiver 2: Spring boot neo queue ****** 19

Receiver 1: Spring boot neo queue ****** 20

根据返回结果得到以下结论

一个发送者,N个接收者,经过测试会均匀的将消息发送到N个接收者中

2、多对多发送


复制了一份发送者,加入标记,在一百个循环中相互交替发送


@Test

public void manyToMany() throws Exception {

	for (int i=0;i<100;i++){

		neoSender.send(i);

		neoSender2.send(i);

	}

}

结果如下:


Receiver 1: Spring boot neo queue ****** 20

Receiver 2: Spring boot neo queue ****** 20

Receiver 1: Spring boot neo queue ****** 21

Receiver 2: Spring boot neo queue ****** 21

Receiver 1: Spring boot neo queue ****** 22

Receiver 2: Spring boot neo queue ****** 22

Receiver 1: Spring boot neo queue ****** 23

Receiver 2: Spring boot neo queue ****** 23

Receiver 1: Spring boot neo queue ****** 24

Receiver 2: Spring boot neo queue ****** 24

Receiver 1: Spring boot neo queue ****** 25

Receiver 2: Spring boot neo queue ****** 25

结论:和一对多一样,接收端仍然会均匀接收到消息。

八、高级使用

======

1、对象的支持


springboot完美的支持对象的发送和接收,不需要额外的配置。


//发送者

public void send(User user) {

	System.out.println("Sender object: " + user.toString());

	this.rabbitTemplate.convertAndSend("object", user);

}



...



//接收者

@RabbitHandler

public void process(User user) {

    System.out.println("Receiver object : " + user);

}

结果如下:


Sender object: User{name='neo', pass='123456'}

Receiver object : User{name='neo', pass='123456'}

2、Topic  Exchange


topic 是 RabbitMQ 中最灵活的一种方式,可以根据 routing_key 自由的绑定不同的队列

首先对 topic 规则配置,这里使用两个队列来测试


@Configuration

public class TopicRabbitConfig {



    final static String message = "topic.message";

    final static String messages = "topic.messages";



    @Bean

    public Queue queueMessage() {

        return new Queue(TopicRabbitConfig.message);

    }



    @Bean

    public Queue queueMessages() {

        return new Queue(TopicRabbitConfig.messages);

    }



    @Bean

    TopicExchange exchange() {

        return new TopicExchange("exchange");

    }



    @Bean

    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {

        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");

    }



    @Bean

    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {

        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");

    }

}

使用 queueMessages 同时匹配两个队列,queueMessage 只匹配 “topic.message” 队列


public void send1() {

	String context = "hi, i am message 1";

	System.out.println("Sender : " + context);

	this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);

}



public void send2() {

	String context = "hi, i am messages 2";

	System.out.println("Sender : " + context);

	this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);

}

发送send1会匹配到topic.#和topic.message 两个Receiver都可以收到消息,发送send2只有topic.#可以匹配所有只有Receiver2监听到消

3、 Fanout  Exchange


Fanout 就是我们熟悉的广播模式或者订阅模式,给 Fanout 交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。

Fanout 相关配置


@Configuration

public class FanoutRabbitConfig {



    @Bean

    public Queue AMessage() {

        return new Queue("fanout.A");

    }



    @Bean

    public Queue BMessage() {


# 总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!如果你需要这份完整版的**面试真题笔记**,只需你多多**支持**我这篇文章。

**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.csdn.net/m0_60958482/java-p7)**

opic.#和topic.message 两个Receiver都可以收到消息,发送send2只有topic.#可以匹配所有只有Receiver2监听到消



3、 Fanout  Exchange

-------------------



Fanout 就是我们熟悉的广播模式或者订阅模式,给 Fanout 交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。



Fanout 相关配置



@Configuration

public class FanoutRabbitConfig {

@Bean

public Queue AMessage() {

    return new Queue("fanout.A");

}



@Bean

public Queue BMessage() {

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!如果你需要这份完整版的面试真题笔记,只需你多多支持我这篇文章。

CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值