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
1.浏览器rabbitmq上创建主题模式交换器
创建成功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方法
启动:
结果: