【SpringCloud】SpringAMQP

文章目录

  • 1、AMQP
  • 2、基本消息模型队列
  • 3、WorkQueue模型
  • 4、发布订阅模型
  • 5、发布订阅-Fanout Exchange
  • 6、发布订阅-DirectExchange
  • 7、发布订阅-TopicExchange

1、AMQP

Advanced Message Queuing Protocol,高级消息队列协议。是用于在应用程序之间传递业务消息的开放标准。

该协议与语言和平台无关,更符合微服务中独立性的要求。

在这里插入图片描述

Spring AMQP是基于AMQP协议定义的一套API规范,提供了模板来发送和接收消息。

它包含两部分,其中spring-amqp是基础抽象,spring-rabbit是底层的默认实现。

在这里插入图片描述

接下来对几种常见的MQ模型,用SpringAMQP来演示一下具体实现。

2、基本消息模型队列

消息发送

  • 引入AMQP依赖(publisher和consumer服务都需要amqp依赖,因此这里把依赖直接放到父工程)
<!--AMQP依赖,包含RabbitMQ-->
<dependency><groupId>org.springframework.boot</groupId>    		<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 在publisher服务中编写application.yml,添加mq连接信息
spring:rabbitmq:host: 192.168.150.101 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机 username: root # 用户名password: 123321 # 密码
  • 在publisher服务中新建一个测试类,注入RabbitTemplate,调用convertAndSend方法,传入队列名称和消息内容即可
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testSimpleQueue() { String queueName = "simple.queue";String message = "hello, spring amqp!";rabbitTemplate.convertAndSend(queueName, message);}
}

消息接收

  • 在consumer服务中编写application.yml,添加mq连接信息
spring:rabbitmq:host: 192.168.150.101 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机 username: root # 用户名password: 123321 # 密码
  • 在consumer服务中新建一个类,编写消费逻辑
//定义类,添加@Component注解
@Component
public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")    public void listenSimpleQueueMessage(String msg) throws InterruptedException {        System.out.println("spring 消费者接收到消息 :【" + msg + "】");    }
}

类中声明方法,添加@RabbitListener注解,注解上写明要消费的队列名称,此时,方法的参数就是消息。

在这里插入图片描述

3、WorkQueue模型

和基本模型不一样,WorkQueue模型,即工作队列,有多个消费者。可以提高消息处理速度,避免队列消息堆积。

在这里插入图片描述

案例:实现一个队列绑定多个消费者

思路如下:

  • 在publisher服务中定义测试方法,每秒产生50条消息,发送到队列simple.queue
  • 在consumer服务中定义两个消息监听者,都监听simple.queue队列,但消费者1每秒能处理50条消息,而消费者2每秒只能处理10条消息

演示代码如下,先写生产者:

//在publisher服务中添加一个测试方法,循环发送50条消息到simple.queue队列@Test
public void testWorkQueue() throws InterruptedException {    // 队列名称    String queueName = "simple.queue";    // 消息   String message = "hello, message__";    for (int i = 0; i < 50; i++) {        // 发送消息rabbitTemplate.convertAndSend(queueName, message + i);// 避免发送太快        Thread.sleep(20);    }
}

接下来编写两个消费者,都监听上面的队列simple.queue:

@RabbitListener(queues = "simple.queue")
public void listenSimpleQueueMessage1(String msg) throws InterruptedException {System.out.println("spring 消费者1接收到消息:【" + msg + "】");Thread.sleep(25);
}@RabbitListener(queues = "simple.queue") 
public void listenSimpleQueueMessage2(String msg) throws InterruptedException {    System.err.println("spring 消费者2接收到消息:【" + msg + "】");    Thread.sleep(100);}

上面一个用System.out.println一个用System.error.println,这样一红一白,在控制台查看消费的效果:

在这里插入图片描述

可以看到,消费者2处理消息慢(代码里用处理一次休眠的旧来模拟),但它从队列里拿的消息却和消费者1一样,因此导致消费总时间过长。对消费者2来说,这就是没有那个金刚钻,却揽了这么多瓷器活儿。这个现象的原因是 ⇒ 消息预取机制

预取机制,通俗说就是消息到了队列后,消费者通过通道一人一个先拿过来,能不能快速处理完的另说,先取走再说。

接下来加一个消费预取限制。通过设置prefetch来控制消费者预取的消息数量。修改消费者的application.yml文件,设置preFetch这个值,可以控制预取消息的上限:

spring:rabbitmq:host: 192.168.150.101 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机 username: root # 用户名password: 123321 # 密码listener:      simple:        prefetch: 1  # 每次只能获取一条消息,处理完成才能获取下一个消息

prefetch默认无限,这里改为1,即 每次只能获取一条消息,处理完成才能获取下一个消息。重启,这次同样生产50条消息,消费总时间变短了,可以看到消费者2处理的慢,取的也慢。

在这里插入图片描述

4、发布订阅模型

和前面两种模型不同,一个消息被一个消费者消费完就没了。发布订阅模式允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)。 当前上一章说的支付功能的实现,就得用这个模型。

在这里插入图片描述

消息被路由到哪些队列中,由exchange决定。常见exchange类型包括:

  • Fanout:广播
  • Direct:路由
  • Topic:话题

注意:exchange负责消息路由,而不是存储,路由失败则消息丢失

5、发布订阅-Fanout Exchange

Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue

在这里插入图片描述

SpringAMQP提供了声明交换机、队列、绑定关系的API:

在这里插入图片描述

接下来写演示代码:

  • 步骤1:在消费consumer服务声明Exchange、Queue,并Binding绑定
//在consumer服务配置目录下创建一个类,添加@Configuration注解
@Configuration
public class FanoutConfig {// 声明FanoutExchange交换机@Bean    public FanoutExchange fanoutExchange(){return new FanoutExchange("exchange.fanout");}    // 声明第1个队列@Bean    public Queue fanoutQueue1(){        return new Queue("fanout.queue1");    }   //绑定队列1和交换机,方法形参就是队列和交换机类型的参数  @Bean    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);    }    //以相同方式声明第2个队列,并完成绑定到上面的交换机@Bean    public Queue fanoutQueue2(){        return new Queue("fanout.queue2");    }   //绑定队列2和交换机  @Bean    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange){        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);    }    
}//将来Spring读到这些Bean,就会向RabbitMQ去声明这些队列和交换机,并绑定

启动消费服务,可以看到队列创建并且绑定到了交换机,以后交换机有消息,和交换机绑定的队列都能收到一份!

在这里插入图片描述

  • 步骤2:在consumer服务声明两个消费者,即添加两个方法,分别监听fanout.queue1和fanout.queue2
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {System.out.println("消费者1接收到fanout.queue1的消息:【" + msg + "】");
}@RabbitListener(queues = "fanout.queue2") 
public void listenFanoutQueue2(String msg) {System.out.println("消费者2接收到fanout.queue2的消息:【" + msg + "】");
}//这里在一个服务里用两个消费者方法模拟被多个服务消费
//到此,两个队列就分别和这两个消费者方法勾搭上了
//重启消费者服务。
  • 步骤3:在publisher服务发送消息到FanoutExchange
//这次不再是send到队列,而是发到交换机
@Test
public void testFanoutExchange() {    // 队列名称    String exchangeName = "itcast.fanout";    // 消息    String message = "hello, everyone!";    // 发送消息,参数分别是:交互机名称、RoutingKey(暂时为空)、消息     rabbitTemplate.convertAndSend(exchangeName, "", message);}//执行这段测试代码,往交换机发消息

查看消费者服务控制台,可以看到一次发送,被多个消费者收到

在这里插入图片描述

小总结:

交换机的作用是什么?

➢ 接收publisher发送的消息
➢ 将消息按照规则路由到与之绑定的队列
➢ 不能缓存消息,路由失败,消息丢失
➢FanoutExchange的会将消息路由到每个绑定的队列

6、发布订阅-DirectExchange

Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。

  • 每一个Queue都与Exchange设置一个BindingKey
  • 发布者发送消息时,指定消息的RoutingKey
  • Exchange将消息路由到BindingKey与消息RoutingKey一致的队列

在这里插入图片描述

当然两个队列可以设置同一个key,此时的效果就和上面的Fanout Exchange一样了。

在这里插入图片描述

步骤1:在consumer服务声明Exchange、Queue。这里不再用Bean,而是利用@RabbitListener声明Exchange、Queue、RoutingKey

@RabbitListener(bindings = @QueueBinding(        value = @Queue(name = "direct.queue1"),        exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),       key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者1接收到Direct消息:【"+msg+"】");
}@RabbitListener(bindings = @QueueBinding(        value = @Queue(name = "direct.queue2"),        exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),        key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者2接收到Direct消息:【"+msg+"】 ");
}

看IDEA的提示类型写就行:exchange的type属性默认就是direct类型,这里不加也行。

在这里插入图片描述
启动消费者服务,到此,队列和交换机都被创建和绑定好了,查看RabbitMQ控制台:

在这里插入图片描述

步骤2:在publisher服务发送消息到DirectExchange,此时convertAndSend方法的第二个参数就要写Routing key了

//在publisher服务的SpringAmqpTest类中添加测试方法
@Test
public void testDirectExchange() {    // 队列名称    String exchangeName = "itcast.direct";    // 消息     String message = "hello,blue!";    // 发送消息,参数依次为:交换机名称,RoutingKey,消息rabbitTemplate.convertAndSend(exchangeName, "blue", message);
}

运行这个测试方法,查看消费服务:

在这里插入图片描述

小总结:

Direct交换机与Fanout交换机的差异?
➢ Fanout交换机将消息路由给每一个与之绑定的队列
➢ Direct交换机根据RoutingKey判断路由给哪个队列
➢ 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

基于@RabbitListener注解声明队列和交换机的常用注解有:
@Queue
@Exchange

7、发布订阅-TopicExchange

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/253345.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

黑马Redis视频教程实战篇(一)

目录 一、短信登录 1.1、导入黑马点评项目 &#xff08;1&#xff09;导入黑马点评sql脚本 &#xff08;2&#xff09;导入后端项目 &#xff08;3&#xff09;导入前端项目 1.2、基于Session实现登录流程 1.3 、实现发送短信验证码功能 1.4 、实现登录拦截功能 1.5 、隐…

创建第一个.NET MAUI应用

1.打开VS2022,创建新项目,并选择.NET MAUI应用,然后点击下一步 2.输入项目相关配置,然后点击下一步 3. 选择框架版本,然后点击创建 4.项目创建成功后会自动打开概述页 5.平台框架切换 6.启动应用,如有下图提示,启动开发者模式 成功启动应用 7.修改应用 修改MainPage.xml如下图…

阿里直播平台面临的技术挑战

大流量、高并发场景下&#xff0c;大型直播的技术挑战一般体现在如下几个方面&#xff1a; 视频流的处理、分发 播放质量保障 视频可用性监控 超大直播间实时弹幕及聊天互动 高性能消息通道 内容控制&#xff0c;如算法鉴黄、文本过滤 系统可用性、稳定性保障 本文将针对其中的…

龙珠直播php,斗鱼、全民TV、龙珠等直播平台排行榜 看视频直播发展趋势

从2015年下半年起&#xff0c;视频直播市场便显露出了火爆之势。除了越来越多的人喜欢观看、愿意参与直播之外&#xff0c;直播类 App也如雨后春笋般不断涌出。 而2016年&#xff0c;视频直播领域更是出现了火爆场面&#xff0c;尤其是刚刚过去的一个月&#xff1a;先是卷土重来…

短视频和直播,哪个会火得更久呢

短视频和直播&#xff0c;哪个会火得更久呢 曾经&#xff0c;电视剧和综艺节目是人们在工作之余放松的主要方式&#xff0c;目前越来越多的电视剧和网剧依靠着当红明星、大 IP 能够在前期获得大量的热度&#xff0c;但在播出之后收视率往往不理想。随着时间的增长&#xff0c;…

怎么创建直播平台

现在直播应用非常火爆&#xff0c;它以生动直观的方式向用户传达最真实的现场信息&#xff0c;受到广大用户的普遍欢迎。小编作为一名技术人员&#xff0c;经常开发各种直播平台&#xff0c;&#xff08;娱乐直播、游戏直播、教育直播、财经直播等&#xff09;下面我把自己积累…

关于linux的ssh(出现的问题以及ubuntu的ssh配置和ssh连接超时问题)

目录 Ubuntu进行ssh连接 关于ssh报错排错 备注&#xff1a;防火墙和selinux可能对ssh连接存在限制&#xff0c;但是我在操作的时候并没对我照成影响 查看selinux状态 ssh_config和sshd_config的区别 Ubuntu进行ssh连接 1.首先需要安装SSH服务器&#xff0c;在ubuntu终端输…

matlab机器人画圆轨迹规划

在这里插入图片描述 function Untitled()clear;clc; L(1)Link([0 0.15055 0 pi/2]); L(2)Link([0 -0.115 0.246 0]); L(3)Link([0 0.1163 0.190 0]); L(4)Link([0 -0.1175 0 pi/2]); L(5)Link([0 0.1175 0 -pi/2]); L(6)Link([0 0.105 0 0]);ZU3SerialLink(L,name,JAKA Z…

Ps制造图标

&#xff08;作者&#xff1a;翟正兴&#xff0c;撰写时间&#xff1a;2019年6月17日&#xff09; 首先我们打开ps新建一个文档 &#xff0c;然后在文档里面用椭圆工具画一个圆出来&#xff0c;画圆的时候把填充禁掉&#xff0c;把描边大小调成30像素首先我们打开ps新建一个文档…

怎么用PS软件图层样式制作图标

1. 2.圆角60px 3. 4.添加图层样式【渐变叠加】 5. 添加【斜面和浮雕】 6. 7.再画一个圆角矩形并添加【图层样式】【渐变叠加】【描边】 8.画圆再次添加【图层样式】【渐变叠加】【内阴影】 9.画圆形并填充黑色【图层样式】【描边】 10. 11.复制圆形最后得到效果图 编辑&#xf…

chatgpt赋能python:Python中最大公约数的函数介绍

Python中最大公约数的函数介绍 在数学中&#xff0c;最大公约数&#xff08;GCD&#xff09;是两个或多个整数的最大公约数。 Python是一种高级编程语言&#xff0c;具有内置的GCD函数。在本篇文章中&#xff0c;我们将介绍Python中的最大公约数函数&#xff0c;以及如何使用它…

Python OpenCV画圆

Python OpenCV画圆 PS: 也是从网上各个帖子中学习的Python&#xff0c;因此代码的格式以及内容有粘贴网上其他大神的代码&#xff0c;如有侵权请告知删除 在图片中检测圆&#xff0c;并进行标注 #!/usr/bin/python # -*- coding: UTF-8 -*-import cv2# 加载图片 img cv2.im…

PS-切图

ps学习 1.改设置 新建ctrN &#xff0c;网页默认选web大小宽度1920 移动工具:设置选择图层 选择自动选择或者按Ctrl鼠标左键可选中 视图&#xff1a;勾标尺显示智能参考线 关掉一些窗口&#xff0c;只留下图层、历史、信息、字符 改信息窗口的面板选项&#xff1a; 改编辑…

C语言画圆(详细解释易懂)

代码 #include<iostream> #include<cmath> using namespace std; int main() { for(double y10;y>-10;y-1){for(int i0;i<10;i) cout<<" ";double x2.5*(10-sqrt(100-y*y)),t;for(t0;t<x;t1) cout<<" ";cout<<…

中点画圆算法----计算机图形学

圆的对称特性&#xff1a; 一个八分圆上的点可以映射为其余七个八分圆的点 利用圆的对称性可以减少计算量&#xff0c;只需要计算出一个八分之一圆上需要画的点&#xff0c;就可以映射出整个圆 中点画圆算法&#xff1a; &#xff08;对于原点为(xc,yc)的圆&#xff0c;假定圆…

Android 自定义View 画圆(奥运五环)

效果图 前言 你会画画吗&#xff1f;你会写代码吗&#xff1f;你会用代码画画吗&#xff1f; 正文 自定义View&#xff0c;实际开发过程中&#xff0c;因为涉及用户体验的时候&#xff0c;UI通常会弄一些骚操作出来&#xff0c;这个时候就有两个选择&#xff0c;你是用GIF…

PS小知识(三)——画圆滑线及虚线

一&#xff1a;画一个圆滑线 1、利用“套索工具”沿着地物画一个圈&#xff1b;或者利用“磁性套索工具”画圈&#xff08;这个的特点是可以大致按照不同的颜色自动追踪&#xff09;。 2、右击进行“描边” 3、进行下面的“平滑”操作 二&#xff1a;画一个圆滑且各段等长的…

html画布里面画圆,html5 canvas 画布画圆

什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。javascript 画布是一个矩形区域,您能够控制其每一像素。css canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。html 浏览器支持 Internet Explorer 9+, Firefox, Opera, Chrome 以及 Sa…

Bresenham 画圆算法原理

文章目录 前言Bresenham 画圆算法原理两个近似构造判别式圆与网格点的关系关系由来关系含义 p i p_i pi​ 递推画圆程序伪码 圆与网格点的关系图示 前言 首先简要介绍一下生成圆的方法&#xff1a; 直接利用圆的方程生成圆利用圆的对称性生成圆 方法一由于会涉及到浮点运算等…

C++ deque类成员函数介绍

目录 &#x1f914;deque模板介绍&#xff1a; &#x1f914;deque特点&#xff1a; &#x1f914;deque内存结构图解&#xff1a; &#x1f914;deque各操作地址指向&#xff1a; &#x1f914; deque的成员函数&#xff1a; deque构造函数&#xff1a; &#x1f50d;代…