RabbitMQ简单应用の订阅模式
订阅模式
公众号-->订阅之后才会收到相应的文章。
解读:
1.一个生产者,多个消费者
2.每个消费者都有自己的队列
3.生产者没有将消息直接发送到队列里,而是发送给了交换机(转发器)exchange
4.每个队列都要绑定到交换机(转发器)上
5.生产者发送的消息记过交换机然后到达队列,然后就能实现被多个消费者消费
图例:
|-------------|-----Q-----C3
P------------X-------------|-----Q-----C3
|-------------|-----Q-----C3
注册--->发邮件--->发短信
MQ工厂类Connection
package com.mmr.rabbitmq.util; import java.io.IOException; import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class ConnectionUtils {
/**
* @desc 获取Mq 的链接
* @author zp
* @throws IOException
* @date 2018-7-19
*/
public static Connection getConnection() throws IOException {
// 1.定义一个链接工厂
ConnectionFactory factroy = new ConnectionFactory(); // 2.设置服务地址
factroy.setHost("127.0.0.1"); // 3.设置端口号
factroy.setPort(5672); // 4.vhost 设置数据库
factroy.setVirtualHost("vhtest"); // 5.设置用户名
factroy.setUsername("jerry"); // 6. 设置密码
factroy.setPassword("123456"); // 7.返回链接
return factroy.newConnection();
}
}
消息生产者类Send,这个时候,运行代码再到控制台去查看,并没有发现我们的消息,因为在MQ中只有队列可以存储消息,而交换机不可以存储消息,下面这段代码并没有将交换机和队列进行绑定,所以数据就丢失了。
package com.mmr.rabbitmq.ps; import java.io.IOException; import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; public class Send {
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws IOException {
// 创建连接
Connection connection = ConnectionUtils.getConnection(); // 获取通道
Channel channel = connection.createChannel(); // 声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");// fanout 分发 // 发送消息
String msg = "hello ps"; channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());
System.out.println("send:"+msg);
channel.close();
connection.close(); }
}
代码运行后的控制台:

由于交换机不能存储数据,那么我们就需要考虑如何将交换机和队列进行绑定。因为只要将两者进行绑定之后,那么数据存储问题就迎刃而解。
消费者Recv1 Recv2
package com.mmr.rabbitmq.ps; import java.io.IOException; import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Recv1 {
private static final String QUEUE_NAME_STRING="test_queue_fanout_email";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws IOException {
// 创建连接
Connection connection = ConnectionUtils.getConnection(); // 创建通道
final Channel channel = connection.createChannel(); // 声明队列
channel.queueDeclare(QUEUE_NAME_STRING, false, false, false, null); // 绑定队列,绑定到交换机/转发器
channel.queueBind(QUEUE_NAME_STRING, EXCHANGE_NAME, ""); // 保证每次只分发一个
channel.basicQos(1); // 定义一个消费者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// TODO Auto-generated method stub
String msg = new String(body,"utf-8");
System.out.println("[1]Recv msg:"+msg);
try {
// 每次休息一会儿
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
System.out.println("recv1 done");
//回执
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
boolean autoAck = false;// 不自动应答
channel.basicConsume(QUEUE_NAME_STRING, autoAck,consumer); }
}
package com.mmr.rabbitmq.ps; import java.io.IOException; import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Recv2 {
private static final String QUEUE_NAME_STRING="test_queue_fanout_sms";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws IOException {
// 创建连接
Connection connection = ConnectionUtils.getConnection(); // 创建通道
final Channel channel = connection.createChannel(); // 声明队列
channel.queueDeclare(QUEUE_NAME_STRING, false, false, false, null); // 绑定队列,绑定到交换机/转发器
channel.queueBind(QUEUE_NAME_STRING, EXCHANGE_NAME, ""); // 保证每次只分发一个
channel.basicQos(1); // 定义一个消费者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// TODO Auto-generated method stub
String msg = new String(body,"utf-8");
System.out.println("[2]Recv msg:"+msg);
try {
// 每次休息一会儿
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
System.out.println("recv2 done");
//回执
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
boolean autoAck = false;// 不自动应答
channel.basicConsume(QUEUE_NAME_STRING, autoAck,consumer); }
}
运行上述代码进行监听,再通过运行Send发送消息,我们可以在MQ-管理平台上看到:

进过这样的使用,我们的消息订阅就完成了。
RabbitMQ简单应用の订阅模式的更多相关文章
- RabbitMQ的发布订阅模式(Publish/Subscribe)
一.发布/订阅(Publish/Subscribe)模式 发布订阅是我们经常会用到的一种模式,生产者生产消息后,所有订阅者都可以收到.RabbitMQ的发布/订阅模型图如下: 1.该模式下生产者并不是 ...
- RabbitMQ入门-消息订阅模式
消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...
- RabbitMQ入门-发布订阅模式
兔子的Publish/Subscribe是这样的: 有个生产者P,X代表交换机,交换机绑定队列,消费者从队列中取得消息.每次有消息,先发到交换机中,然后由交换机负责发送到它已知的队列中. 生产者代码: ...
- RabbitMQ简单应用の主题模式(topic)
Topic exchange(主题转发器) 发送给主题转发器的消息不能是任意设置的选择键,必须是用小数点隔开的一系列的标识符.这些标识符可以是随意,但是通常跟消息的某些特性相关联.一些合法的路由选择键 ...
- 用BlockingQueue实现的简单发布订阅模式
- Go RabbitMQ(三)发布订阅模式
RabbitMQ 在上一节中我们创建了工作队列,并且假设每一个任务都能够准确的到达对应的worker.在本节中我们将介绍如何将一个消息传递到多个消费者,这也就是所说的发布订阅模式 为了验证该模式我们使 ...
- RabbitMQ指南之三:发布/订阅模式(Publish/Subscribe)
在上一章中,我们创建了一个工作队列,工作队列模式的设想是每一条消息只会被转发给一个消费者.本章将会讲解完全不一样的场景: 我们会把一个消息转发给多个消费者,这种模式称之为发布-订阅模式. 为了阐述这个 ...
- RabbitMQ六种队列模式-发布订阅模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- RabbitMQ学习第三记:发布/订阅模式(Publish/Subscribe)
工作队列模式是直接在生产者与消费者里声明好一个队列,这种情况下消息只会对应同类型的消费者. 举个用户注册的列子:用户在注册完后一般都会发送消息通知用户注册成功(失败).如果在一个系统中,用户注册信息有 ...
随机推荐
- (链表 set) leetcode 817. Linked List Components
We are given head, the head node of a linked list containing unique integer values. We are also give ...
- Oracle提权
1.创建JAVA包 select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immed ...
- CentOS 6.x 最小化安装推荐安装的依赖包和修改内核参数
CentOS 6.x 最小化安装推荐安装的依赖包 我在日常工作中,新建的xenserver的虚拟机,CentOS release 6.9 (Final)操作系统,采用最小化安装,后续很多操作需要各种依 ...
- 关于mac 系统如何通过终端 连接linux服务器 并传文件!
首先要打开终端 mac远程链接服务器 输入 : ssh root@xxx.xx.xxx.xx xxx.xx.xxx.xx是端口号 后面会要求你输入password 即可远程连接 mac通过终端给 ...
- sklearn-标准化标签LabelEncoder
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- Java项目中,如何限制每个用户访问接口的次数
转自:https://blog.csdn.net/qq_30947533/article/details/78844709 方法1:数据访问量大的话 用redis来做,用户在调用短信接口时,先根据用户 ...
- JAVA核心技术I---JAVA基础知识(单例模式和final关键字)
一:单例模式 C++设计模式中提及,不再赘述设计模式---对象性能模式之单例模式(Singleton) public class single{ static single Instance=new ...
- try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案
如题,ajax请求报错:try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案 要么是404,要么是40 ...
- IT术语
目录: 心跳检测 故障切换 主从配置 负载均衡 集群LVS 多集群横向扩容 纵向扩容 CDN DOS DDOS 会话跟踪 CSRF
- C#中ICollection介绍
ICollection 接口是 System.Collections 命名空间中类的基接口,ICollection 接口扩展 IEnumerable,IDictionary 和 IList 则是扩展 ...