应公司大佬要求,学习一下SpringCloudStream,作为技术储备。这几天也看了这方面的资料,现在写一篇笔记,以做总结。文章会从RabbitMQ基础讲起,到SpringCloudStream结束,预计4篇左右结束。废话不多说,进入正文。

1.知识储备

消息队列:在消息的传输过程中保存消息的的容器。

这是一个较为经典的消费-生产者模型,说起来比较抽象,打个比方:A线程需要给B线程发送消息(A、B线程不一定是在同一台机器上的),A线程先把消息发送到消息队列服务器上,然后B线程去读取或是订阅消息服务器上消息队列中的消息,线程A和B之间并没有进行直接通信。MQ服务器在中间起到中继的作用。我们可以把MQ理解成为一个邮局+邮差的角色,只不过邮局传递消息用的是传统的信件,而MQ用的是二进制数据

RabbitMQ是AMQP(高级消息队列协议)的一个标准实现,关于它的快速入门,可以在这里查看:http://www.rabbitmq.com/getstarted.html

AMQP跟JMS::

JMS是SUN公司定义的一套规范,旨在为java应用提供统一的消息操作,包括create、send、receive等等,从使用角度看,JMS和JDBC担任差不多的角色,用户都是根据相应的接口可以和实现了JMS的服务进行通信,进行相关的操作。

JMS通常包含如下一些角色:

Elements Notes
JMS provider 实现了JMS接口的消息中间件,如ActiveMQ
JMS client 生产或者消费消息的应用
JMS producer/publisher JMS消息生产者
JMS consumer/subscriber JMS消息消费者
JMS message 消息,在各个JMS client传输的对象;
JMS queue Provider存放等待被消费的消息的地方
JMS topic 一种提供多个订阅者消费消息的一种机制;在MQ中常常被提到,topic模式。

AMQP(advanced message queuing protocol)在2003年时被提出,最早用于解决金融领不同平台之间的消息传递交互问题。顾名思义,AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。意味着我们可以使用Java的AMQP provider,同时使用一个python的producer加一个rubby的consumer。从这一点看,AQMP可以用http来进行类比,不关心实现的语言,只要大家都按照相应的数据格式去发送报文请求,不同语言的client均可以和不同语言的server链接。在AMQP中,消息路由(messagerouting)和JMS存在一些差别,在AMQP中增加了Exchange和binding的角色。producer将消息发送给Exchange,binding决定Exchange的消息应该发送到那个queue,而consumer直接从queue中消费消息。queue和exchange的bind有consumer来决定。

JMS和AMQP的各项对比如下:

  JMS AMQP
定义 Java api Wire-protocol
跨语言
跨平台
Model Peer-2-Peer(点对点),Pub/sub(发布订阅) 提供了五种消息模型:(后面会详细介绍) (1)、direct exchange (2)、fanout exchange (3)、topic change (4)、headers exchange (5)、system exchange 本质来讲,后四种和JMS的pub/sub模型没有太大差别,仅是在路由机制上做了更详细的划分; | | 支持消息类型 | 多种消息类型:TextMessage,MapMessage,BytesMessage,StreamMessage,ObjectMessage,Message (只有消息头和属性) | byte[]当实际应用时,有复杂的消息,可以将消息序列化后发送

综合评价 : JMS 定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差; AMQP定义了wire-level层的协议标准;天然具有跨平台、跨语言特性。

2.RabbitMQ基本结构

组成部分说明如下:

  1. Broker:消息队列服务进程,此进程包含两部分,交换机及队列

  2. Exchange:交换机,将消息按一定的路由规则转发到队列,对消息进行过滤

  3. Queue: 消息队列,储存消息的队列,消息到达队列并转发给指定的消费方

  4. Producer:生产者,将消息发送到MQ

  5. Consumer:消费者,接受MQ中的消息

3.运行流程

  1. 生产者

    • 生产者跟Broker建立TCP连接

    • 生产者跟Broker建立通道Channel

    • 生产者通过通道发送消息到Broker,由交换机将消息进行转发

    • 交换机将消息转发到指定的队列

  2. 消费者

    • 消费者跟Broker建立TCP连接

    • 消费者跟Broker建立通道Channel

    • 消费者监听指定的队列

    • 当有消息到达队列时,Broker将消息推送给消费者(没有经过交换机

    • 消费者接受到消息

4.入门案例

  1. 生产者代码

  1. public class RabbitmqApplication {

  2.    public static final String QUEUE_NAME = "queue";

  3.    public static void main(String[] args) {
  4.        // 建立连接
  5.        ConnectionFactory factory = new ConnectionFactory();
  6.        factory.setHost("127.0.0.1");
  7.        factory.setPort(5672);
  8.        factory.setUsername("guest");
  9.        factory.setPassword("guest");
  10.        // 设置虚拟机,一个虚拟机相当于一个独立的mq
  11.        factory.setVirtualHost("/");
  12.        Connection connection = null;
  13.        Channel channel = null;
  14.        try {
  15.            connection = factory.newConnection();
  16.            // 建立通道
  17.            channel = connection.createChannel();
  18.            // 交换机:不声明则为默认的交换机
  19.            // 声明队列
  20.            /**
  21.             * @params 参数列表:
  22.             * String queue: 声明的队列名称
  23.             * boolean durable:消息是否持久化,若设置为true,则MQ重启后,队列仍然存在
  24.             * boolean exclusive:是否独占连接,设置为true,连接关闭则队列被删除,一般用于临时队列的创建,跟autoDelete配合使用
  25.             * boolean autoDelete:是否自动删除,设置为true,则队列不使用就自动删除,一般用于临时队列的创建
  26.             * Map<String, Object> arguments:设置队列的一些扩展参数
  27.             */
  28.            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
  29.            // 生产者发送消息
  30.            String message = "Hello World!";
  31.            /**
  32.             * @params
  33.             *String exchange, 交换机名称
  34.             *String routingKey, 路由key
  35.             *BasicProperties props, 消息的一些属性
  36.             *byte[] body 消息体
  37.             *
  38.             */
  39.            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
  40.            System.out.println(" [x] Sent '" + message + "'");
  41.       } catch (Exception e) {
  42.            e.printStackTrace();
  43.       }
  44.   }
  45. }
  1. 消费者代码

  1. public class ConsumerApplication {

  2.    public static final String QUEUE_NAME = "queue";

  3.    public static void main(String[] args) {
  4.        // 建立连接
  5.        ConnectionFactory factory = new ConnectionFactory();
  6.        factory.setHost("127.0.0.1");
  7.        factory.setPort(5672);
  8.        factory.setUsername("guest");
  9.        factory.setPassword("guest");
  10.        // 设置虚拟机,一个虚拟机相当于一个独立的mq
  11.        factory.setVirtualHost("/");
  12.        Connection connection = null;
  13.        Channel channel = null;
  14.        try {
  15.            connection = factory.newConnection();
  16.            // 建立通道
  17.            channel = connection.createChannel();
  18.            // 声明队列
  19.            /**
  20.             * 这一步声明的队列必须跟我们在生产者中声明的队列一样,参数也必须一样,否则会报错
  21.             * 对队列的声明是幂等的,之所以在这里再次申明是为了方便启动服务
  22.             * 有时候,生产者还没启动,我们消费者已经启动了
  23.             */
  24.            channel.queueDeclare(QUEUE_NAME, true
  25.                   , false, false, null);
  26.            // 监听队列
  27.            /**
  28.             * String queue,
  29.             * boolean autoAck,
  30.             * String consumerTag,
  31.             * Consumer callback
  32.             */
  33.            channel.basicConsume(QUEUE_NAME, true, new DefaultConsumer(channel) {
  34.                /**
  35.                 * 复写这个方法,处理从mq中获取的消息
  36.                 * @param consumerTag 消费者标记,可设可不设
  37.                 * @param envelope 信封
  38.                 * @param properties 消息属性,我们在生产者发送消息时可以设置
  39.                 * @param body 消息体
  40.                 * @throws IOException
  41.                 */
  42.                @Override
  43.                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
  44.                    String exchange = envelope.getExchange();
  45.                    long deliveryTag = envelope.getDeliveryTag();
  46.                    System.out.println("MQ中消息id:" + deliveryTag);
  47.                    System.out.println("交换机:" + exchange);
  48.                    System.out.println("receive:" + new String(body, Charset.defaultCharset()));
  49.               }
  50.           });
  51.       } catch (Exception e) {
  52.            e.printStackTrace();
  53.       }
  54.   }
  55. }

SpringCloudStream学习(一)RabbitMQ基础的更多相关文章

  1. 一篇学习完rabbitmq基础知识,springboot整合rabbitmq

    一   rabbitmq 介绍 MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced MessageQueue 高级消息队列协议 ...

  2. C#RabbitMQ基础学习笔记

    RabbitMQ基础学习笔记(C#代码示例) 一.定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发).MQ是一种应用程序对应用程序的通信方法. ...

  3. RabbitMQ基础教程之基本使用篇

    RabbitMQ基础教程之基本使用篇 最近因为工作原因使用到RabbitMQ,之前也接触过其他的mq消息中间件,从实际使用感觉来看,却不太一样,正好趁着周末,可以好好看一下RabbitMQ的相关知识点 ...

  4. RabbitMq基础教程之基本概念

    RabbitMq基础教程之基本概念 RabbitMQ是一个消息队列,和Kafka以及阿里的ActiveMQ从属性来讲,干的都是一回事.消息队列的主要目的实现消息的生产者和消费者之间的解耦,支持多应用之 ...

  5. RabbitMQ基础教程之Spring&JavaConfig使用篇

    RabbitMQ基础教程之Spring使用篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 RabbitMQ基础 ...

  6. RabbitMQ基础教程之使用进阶篇

    RabbitMQ基础教程之使用进阶篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 I. 背景 前一篇基本使用篇 ...

  7. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  8. ASP.NET Core消息队列RabbitMQ基础入门实战演练

    一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...

  9. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

随机推荐

  1. 利用Ajax实现异步请求

    Ajax 1.课程引入      静态网站和动态网站都是同步的,但同步方式有缺点:页面请求响应式阻塞,影响用户体验      为了解决这个问题,可以通过变通的手段实现页面的局部更新(隐藏帧),由于隐藏 ...

  2. PAS

    一.概念 二.安装 打开Delphi,在主菜单上选择Component,单击Install Component,出现图所示的对话框.有两个选择,装到已经存在的包里面和装到新的包里面.我们选择后者,单击 ...

  3. python这门语言为什么要起这个名字

    我只是一只可爱的小虫 前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Liz喵 PS:如有需要Python学习资料的小 ...

  4. 8. input限制手机输入

    1. 只能输入数字: <input id="num" type="number" value="0" onkeyup="va ...

  5. 简谈” Top K“

    Top K 快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题. 题见215. Kth Largest Element in an Array (Medium) ...

  6. python安装pil库,操作流程以及安装中出现的问题。

    0.用管理员方式打开cmd窗口. 1.跳转到python对应目录 比我: ***或者直接在该路径下输入cmd直接跳转.**** 例如: 直接回车搞定!! 2.输入 pip install pillow ...

  7. 8个超好用的Python内置函数,提升效率必备(小白必看)

    python中有许多内置函数,不像print那么广为人知,但它们却异常的强大,用好了可以大大提高代码效率. 这次来梳理下8个好用的python内置函数. 1.set() 当需要对一个列表进行去重操作的 ...

  8. Python快速编程入门,打牢基础必须知道的11个知识点 !

    Python被誉为全世界高效的编程语言,同时也被称作是“胶水语言”,那它为何能如此受欢迎,下面我们就来说说Python入门学习的必备11个知识点,也就是它为何能够如此受欢迎的原因. Python 简介 ...

  9. AWR发现TOP Event log file sequential read

    对客户DB进行巡检,发现TOP EVENT是LOG FILE Sequential read 等待事件说明 https://www.xuebuyuan.com/zh-hant/1743045.html ...

  10. 百度云虚拟空间(BCH)

    百度云虚拟空间(BCH)上的一些默认配置 :first-child { margin-top: 0;}blockquote > :last-child { margin-bottom: 0;}i ...