1 直接模式(Direct)
1.1 什么是 Direct 模式
我们需要将消息发给唯一一个节点时使用这种模式,这是最简单的一种形式。
任何发送到 Direct Exchange 的消息都会被转发到 RouteKey 中指定的 Queue 。
1. 一般情况可以使用 rabbitMQ 自带的 Exchange : ”"( 该 Exchange 的名字为空字符串,下
文称其为 default Exchange) 。
2. 这种模式下不需要将 Exchange 进行任何绑定 (binding) 操作
3. 消息传递时需要一个 “RouteKey” ,可以简单的理解为要发送到的队列名字。
4. 如果 vhost 中不存在 RouteKey 中指定的队列名,则该消息会被抛弃。
1.2 创建队列
做下面的例子前,我们先建立一个叫 nbpuls 的队列。(前提运行docker下的rabbitmq)
Durability :是否做持久化 Durable (持久) transient (临时)
Auto delete : 是否自动删除
然后点击Add queue 添加,就会发现nbpuls已经添加成功
3 代码实现 - 消息生产者
( 1 )创建工程 rabbitmq_demo ,引入 amqp 起步依赖 , pom.xml 如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
(2)编写配置文件 application.yml
server:
port: 8002
spring:
rabbitmq:
host: 192.168.63.131
(3)编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RabbitApplication {
public static void main(String[] args) {
SpringApplication.run( RabbitApplication.class, args);
}
}
(4)编写测试类
import com.zhao588.rabbit.RabbitApplication;
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(classes = RabbitApplication.class)
public class ProductTest
{
@Autowired
private RabbitTemplate rabbitTemplate;
/*
* 直接模式
* */
@Test
public void sendMsg1(){
rabbitTemplate.convertAndSend("nbplus","直接模式测试");
}
}
(5)运行测试这个方法
(6)运行完毕之后查看浏览器,已经接收到发放发出的消息
.4 代码实现-消息消费者
( 1 )编写消息消费者类
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "nbplus")
public class Custmer1
{
@RabbitHandler
public void getMsg(String msg){
System.out.println("直接模式输出:"+msg);
}
}
(2)运行启动类,可以在控制台看到刚才发送的消息
已经成功输出
浏览器rabbitmq 消息数量归零,说明已经被消费。
5 测试
开启多个消费者工程,测试运行消息生产者工程,会发现只有一个消费者工程可以接收
到消息。
如何在 IDEA 中多次启动同一个程序呢?
( 1 )选择 IDEA右上角的类名称按钮
(2)选择 Edit Configurations
(3)在弹出窗口中取消单例模式 ,点击 OK
(4)每次运行前修改 application.yml ,指定不同的端口 ,修改三次端口号,运行三次启动类,相当于有三个消费者接受消息,最后运行生产者测试方法:
测试运行消息生产者工程,会发现只有一个消费者工程可以接收 到消息。
消费者工程可以接收 到消息。第三次运行也和第二种情况一样,说明这里遵循了负载均衡的规律。
2 分列模式(Fanout)
1 什么是分列(Fanout)模式
当我们需要将消息一次发给多个队列时,需要使用这种模式。如下图:
任何发送到 Fanout Exchange 的消息都会被转发到与该 Exchange 绑定 (Binding) 的所有
Queue 上。
1. 可以理解为路由表的模式
2. 这种模式不需要 RouteKey
3. 这种模式需要提前将 Exchange 与 Queue 进行绑定,一个 Exchange 可以绑定多个
Queue ,一个 Queue 可以同多个 Exchange 进行绑定。
4. 如果接受到消息的 Exchange 没有与任何 Queue 绑定,则消息会被抛弃。
2 交换器绑定队列
( 1 )在 queue 中添加队列 team1 和 team2
(2)新建交换器 boss
点击boss添加绑定 team1和team2
绑定后效果如下:
4 代码实现 - 消息消费者
创建消息监听类,用于监听 team1 的消息
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "team1")
public class Custmer1
{
@RabbitHandler
public void getMsg(String msg){
System.out.println("team1分裂模式输出:"+msg);
}
}
创建消息监听类,用于监听team2的消息
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "team2")
public class Custmer2
{
@RabbitHandler
public void getMsg(String msg){
System.out.println("team2分裂模式输出:"+msg);
}
}
5 测试
启动消费者工程,发送消息测试
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(classes = RabbitApplication.class)
public class ProductTest
{
@Autowired
private RabbitTemplate rabbitTemplate;
/*
* 分裂模式
* */
@Test
public void sendMsg2(){
rabbitTemplate.convertAndSend("boss","","分裂模式测试");
}
}
启动
启动后结果如下
3 主题模式(Topic)
.1 什么是主题模式
任何发送到 Topic Exchange 的消息都会被转发到所有关心 RouteKey 中指定话题的 Queue
上
如上图所示
此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模
糊匹配的意思,例如:上图中红色对列的 routekey 为 usa.# , # 代表匹配任意字符,但是
要想消息能到达此对列, usa. 必须匹配后面的 # 好可以随意。图中 usa.news
usa.weather, 都能找到红色队列,符号 # 匹配一个或多个词,符号 * 匹配不多不少一个
词。因此 usa.# 能够匹配到 usa.news.XXX ,但是 usa.* 只会匹配到 usa.XXX 。
注:
交换器说到底是一个名称与队列绑定的列表。当消息发布到交换器时,实际上是由你所
连接的信道,将消息路由键同交换器上绑定的列表进行比较,最后路由消息。
任何发送到 Topic Exchange 的消息都会被转发到所有关心 RouteKey 中指定话题的
Queue 上
1. 这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一
个 “ 标题 ”(RouteKey) , Exchange 会将消息转发到所有关注主题能与 RouteKey 模糊匹配的
队列。
2. 这种模式需要 RouteKey ,也许要提前绑定 Exchange 与 Queue 。
3. 在进行绑定时,要提供一个该队列关心的主题,如 “#.log.#” 表示该队列关心所有涉及
log 的消息 ( 一个 RouteKey 为 ”MQ.log.error” 的消息会被转发到该队列 ) 。
4.“#” 表示 0 个或若干个关键字, “ ” 表示一个关键字。如 “log. ” 能与 “log.warn” 匹配,无法
与 “log.warn.timeout” 匹配;但是 “log.#” 能与上述两者匹配。
5. 同样,如果 Exchange 没有发现能够与 RouteKey 匹配的 Queue ,则会抛弃此消息
2 创建队列与绑定
( 1 )新建一个交换器 ,类型选择 top
器
创建成功topicmodel后
点击topicmodel,绑定队列team1 这个里的Rounting key可 随意写,不过得记住,后面用。
就行绑定team2
一共就绑定这三个。
3 代码实现
编写测试类方法:先启动启动类
测试一 启动sendMsg3方法
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(classes = RabbitApplication.class)
public class ProductTest
{
@Autowired
private RabbitTemplate rabbitTemplate;
/*
* 主题模式测试
* */
@Test
public void sendMsg3(){
rabbitTemplate.convertAndSend("topicmodel","good.abc","主题模式测试");
}
}
结果:
测试二 启动sendMsg3方法
启动:
结果:
测试三启动sendMsg3方法
启动:
结果: