学习笔记(十)、消息中间件RabbitMQ

消息队列中间件

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量 削锋等问题实现高性能,高可用,可伸缩和最终一致性架构

RabbitMQ简介

RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

架构图

概念

  • RabbitMQ Server 

也叫broker server,它是一种传输服务。 他的角色就是维护一条 从Producer到Consumer的路线,保证数据能够按照指定的方式进行传输。

  • Producer

消息生产者,消息生产者连接RabbitMQ服 务器然后将消息投递到Exchange。

  • Consumer

消息消费者,消息消费者订阅队列, RabbitMQ将Queue中的消息发送到消息消费者。

  • Exchange

生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个 或多个Queue中(或者丢弃)。Exchange并不存储消息。RabbitMQ中的Exchange有 direct、fanout、topic、headers四种类型,每种类型对应不同的路由规则。

  • Queue

(队列)是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅 队列来获取消息的,RabbitMQ中的消息都只能存储在Queue中,生产者生产消息并最终 投递到Queue中,消费者可以从Queue中获取消息并消费。多个消费者可以订阅同一个 Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者 都收到所有的消息并处理。

  • RoutingKey

生产者在将消息发送给Exchange的时候,一般会指定一个routing key, 来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联 合使用才能最终生效。在Exchange Type与binding key固定的情况下(在正常使用时一 般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过 指定routing key来决定消息流向哪里。RabbitMQ为routing key设定的长度限制为255 bytes。 

特性

  • 可靠性(Reliability)

 RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

  • 灵活的路由(Flexible Routing)

在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

  • 消息集群(Clustering)

多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。

  • 高可用(Highly Available Queues)

队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。 5.多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。

  • 多语言客户端(Many Clients)

RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。

  • 管理界面(Management UI)

RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方 面。

  • 跟踪机制(Tracing)

如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。

  • 插件机制(Plugin System)

RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

 

 RabbitMQ安装(Windows)

因为RabbitMQ 是基于Erlang 语言开发的,要先安装Erlang 像安装JDK一样。

Erlang  下载地址:http://erlang.org/download/  根据操作系统选择相应版本,下载完成安装直接下一步即可。

RabbitMQ 下载地址:http://www.rabbitmq.com/download.html 下载完成直接安装即可,避开中文安装目录

安装管理界面:

进入RabbitMQ安装目录的sbin目录,输入命令:rabbitmq‐plugins enable rabbitmq_management

找到Windows服务中的RabbitMQ服务重启即可,浏览器访问地址:http://localhost:15672/ 进入管理界面,用户名和密码为guest。

直接模式(Direct)

我们需要将消息发给唯一一个节点时使用这种模式,这是最简单的一种形式(默认使用)。

代码测试:

1、先在图形化界面创建一个队列mqtest:

Durability:是否做持久化 Durable(持久) transient(临时) Auto delete : 是否自动删除

2、创建一个Spring Boot项目rabbitmq_demo 引入如下依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wdg</groupId>
    <artifactId>rabbitmq_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rabbitmq_demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties文件配置mq:

spring.rabbitmq.host=127.0.0.1

3、消息生产者实现:

package com.wdg.rabbitmq;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqTest {


    //注入RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Test
    public void doMQTest() {
        //直接模式可以看成没有通过交换器Exchange直接与Queue绑定,发送消息只需要带上参数routingKey, object
        rabbitTemplate.convertAndSend("mqtest","MQ测试");

    }

}

 运行测试类:发送消息

4、消息消费者实现:

package com.wdg.rabbitmq;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author WDG
 * @date 2019-2-15
 */
@Component
@RabbitListener(queues="mqtest")//绑定队列
public class MQConsumer1 {

    @RabbitHandler
    public void doHandler(String message){
        System.out.println("接收到消息:"+message);
    }

}

运行启动类,MQConsumer1监听到mqtest队列的消息后消费:

分列模式(Fanout)

当我们需要将消息一次发给多个队列时,需要使用这种模式。

任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有 Queue上。

1.可以理解为路由表的模式

2.这种模式不需要RouteKey

3.这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个 Queue,一个Queue可以同多个Exchange进行绑定。

4.如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。

 代码实现:

1、创建两个队列,man、women

2、创建一个交换器,type选择fanout类型:person

3、将man、women两个队列绑定到交换器person上:

4、消息生产者测试方法:

    @Test
    public void doFanoutTest(){
        rabbitTemplate.convertAndSend("person","","分裂模式测试");
    }

运行测试方法:

5、消息消费者 consumer2:

package com.wdg.rabbitmq;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author WDG
 * @date 2019-2-15
 */
@Component
@RabbitListener(queues="man")
public class MQConsumer2 {

    @RabbitHandler
    public void manQueues(String message){
        System.out.println("man接收到消息:"+message);
    }
}

6、消息消费者consumer3:

package com.wdg.rabbitmq;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author WDG
 * @date 2019-2-15
 */
@Component
@RabbitListener(queues="women")
public class MQConsumer3 {

    @RabbitHandler
    public void womenQueues(String message){
        System.out.println("women接收到消息:"+message);
    }
}

运行启动类:

主题模式(Topic)

任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue 上

1.这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一 个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的 队列。

2.这种模式需要RouteKey,也许要提前绑定Exchange与Queue。

3.在进行绑定时,要提供一个该队列关心的主题,如“#.hello.#”表示该队列关心所有涉及 hello的消息(一个RouteKey为”MQ.hello.Success”的消息会被转发到该队列)。

4.“#”表示0个或若干个关键字,“”表示一个关键字。如“hello.”能与“hello.world”匹配,无法 与“hello.world.ok”匹配;但是“hello.#”能与上述两者匹配。

5.同样,如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息

1、创建一个交换器topictest,type类型选择topic类型:

2、将man、women、mqtest队列与topictest交换器绑定 ,定义RouteKey规则:

3、主题模式消息生产者1测试:

    @Test
    public void testSendTopic1(){
        rabbitTemplate.convertAndSend("topictest","hello.world","主题模式测试");
    }

控制台(三个队列都匹配消费了消息):

4、主题模式消息生产者2测试:

     @Test
    public void testSendTopic2(){
        rabbitTemplate.convertAndSend("topictest","hello.ok","主题模式测试");
    }

控制台(只有women队列匹配成功并消费了消息):

5、主题模式消息生产者3测试:

     @Test
    public void testSendTopic3(){
        rabbitTemplate.convertAndSend("topictest","error.world","主题模式测试");
    }

控制台(只有man队列匹配成功并消费了消息):

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值