模型图

我们之前学习的都是一个消息只能被一个消费者消费,那么如果我想发一个消息 能被多个消费者消费,这时候怎么办? 这时候我们就得用到了消息中的发布订阅模型

在前面的教程中,我们创建了一个工作队列,都是一个任务只交给一个消费者。这次我们做 将消息发送给多个消费者。这种模式叫做“发布/订阅”。

举列:

类似微信订阅号 发布文章消息 就可以广播给所有的接收者。(订阅者)

那么咱们来看一下图,我们学过前两种有一些不一样,work 模式 是不是同一个队列 多个消费者,而 ps 这种模式呢,是一个队列对应一个消费者,pb 模式还多了一个 X(交换机 转发器) ,这时候我们要获取消息 就需要队列绑定到交换机上,交换机把消息发送到队列 , 消费者才能获取队列的消息

解读:
1、1 个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机(转发器)
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机,到达队列,实现,一个消息被多个消费者获取的目的

生产者

 package cn.wh.simple;

 import java.io.IOException;
import java.util.concurrent.TimeoutException; import cn.wh.util.RabbitMqConnectionUtil;
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, TimeoutException { Connection connection = RabbitMqConnectionUtil.getConnection(); Channel channel = connection.createChannel(); //声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");//分发 //发送消息
String msg="hello ps"; channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes()); System.out.println("Send :"+msg); channel.close();
connection.close();
}
}

消费者1

 package cn.wh.simple;

 import java.io.IOException;
import java.util.concurrent.TimeoutException; import cn.wh.util.RabbitMqConnectionUtil; 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="test_queue_fanout_email";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitMqConnectionUtil.getConnection();
final Channel channel = connection.createChannel(); //队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null); //绑定队列到交换机 转发器
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ""); channel.basicQos(1);//保证一次只分发一个 //定义一个消费者
Consumer consumer=new DefaultConsumer(channel){
//消息到达 触发这个方法
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException { String msg=new String(body,"utf-8");
System.out.println("[1] Recv msg:"+msg); try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("[1] done ");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
}; boolean autoAck=false;//自动应答 false
channel.basicConsume(QUEUE_NAME,autoAck , consumer);
}
}

消费者2

package cn.wh.simple;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import cn.wh.util.RabbitMqConnectionUtil;
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="test_queue_fanout_sms";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitMqConnectionUtil.getConnection();
final Channel channel = connection.createChannel(); //队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null); //绑定队列到交换机 转发器
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
channel.basicQos(1);//保证一次只分发一个 //定义一个消费者
Consumer consumer=new DefaultConsumer(channel){
//消息到达 触发这个方法
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException { String msg=new String(body,"utf-8");
System.out.println("[2] Recv msg:"+msg); try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("[2] done ");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
}; boolean autoAck=false;//自动应答 false
channel.basicConsume(QUEUE_NAME,autoAck , consumer);
}
}

测试

一个消息 可以被多个消费者

RabbitMQ 之 订阅模式 Publish/Subscribe的更多相关文章

  1. RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)

    RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...

  2. 观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别

    观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别 在翻阅资料的时候,有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe ...

  3. RabbitMQ(三) -- Publish/Subscribe

    RabbitMQ(三) -- Publish/Subscribe `rabbitmq`支持一对多的模式,一般称为发布/订阅.也就是说,生产者产生一条消息后,`rabbitmq`会把该消息分发给所有的消 ...

  4. RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)

    RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现) 在上一个教程中,我们创建了一个工作队列. 工作队列背后的假设是,每个任务都恰好交付给一个worker处理. 在这 ...

  5. Mina、Netty、Twisted一起学(七):发布/订阅(Publish/Subscribe)

    消息传递有很多种方式,请求/响应(Request/Reply)是最常用的.在前面的博文的例子中,很多都是采用请求/响应的方式,当服务器接收到消息后,会立即write回写一条消息到客户端.HTTP协议也 ...

  6. Mina、Netty、Twisted一起学(七):公布/订阅(Publish/Subscribe)

    消息传递有非常多种方式.请求/响应(Request/Reply)是最经常使用的.在前面的博文的样例中.非常多都是採用请求/响应的方式.当server接收到消息后,会马上write回写一条消息到clie ...

  7. 译: 3. RabbitMQ Spring AMQP 之 Publish/Subscribe 发布和订阅

    在第一篇教程中,我们展示了如何使用start.spring.io来利用Spring Initializr创建一个具有RabbitMQ starter dependency的项目来创建spring-am ...

  8. RabbitMQ入门:发布/订阅(Publish/Subscribe)

    在前面的两篇博客中 RabbitMQ入门:Hello RabbitMQ 代码实例 RabbitMQ入门:工作队列(Work Queue) 遇到的实例都是一个消息只发送给一个消费者(工作者),他们的消息 ...

  9. 【译】RabbitMQ:发布-订阅(Publish/Subscribe)

    在前一篇教程中,我们创建了一个工作队列,我们假设在工作队列后的每一个任务都只被调度给一个消费者.在这一部分,我们将做一些完全不一样的事情,调度同一条消息给多个消费者,也就是有名的“发布-订阅”模式.为 ...

随机推荐

  1. Shiro框架简介

    Apache Shiro是Java的一个安全框架.对比另一个安全框架Spring Sercurity,它更简单和灵活. Shiro可以帮助我们完成:认证.授权.加密.会话管理.Web集成.缓存等. A ...

  2. 汇智课堂 Node.js相关课程

    Node.js入门 Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的 易于扩展的网络应用· Node.js 借助事件驱动, 非阻塞I/O 模型 ...

  3. PAT 1048 Find Coins[比较]

    1048 Find Coins (25 分) Eva loves to collect coins from all over the universe, including some other p ...

  4. appium 智能滚动

  5. Linux服务器access_log日志分析及配置详解(二)

    默认nginx / Linux日志在哪个文件夹? 一般在 xxx.xxx.xxxx.com/home/admin 路径下面的error.log文件和access.log文件error_log logs ...

  6. Flask组件 flask_session

    flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存,该组件则将支持session保存到多个地方,如: redis memcac ...

  7. phpcms v9模板制作常用代码集合

    phpcms v9模板制作常用代码集合(个人收藏) 1.截取调用标题长度 {str_cut($r[title],36,'')} 2.格式化时间 调用格式化时间 2011-05-06 11:22:33 ...

  8. Java设计原则—开闭原则(转)

    原文出自:http://www.cnblogs.com/muzongyan/archive/2010/08/05/1793454.html 开闭原则(Open Closed Principle)是Ja ...

  9. Word 中将正文中的参考文件标号链接到参考文献具体条目

    一.概论 在论文撰写过程中,不可避免地引用到参考文献.通常,论文格式要求我们在引用的正文后,使用中括号将参考文献章节中对应的出处条目序号引起来,例如: 有时,我们要建立起这两者之间的链接关系. 二.设 ...

  10. ubuntu apt-get 安装 lnmp

    最近在 Ubuntu 14.04 LTS 安装 LNMP 一键安装包的时候出现了问题,PHP 5 服务没有启动,只好使用 Ubuntu 官方源进行安装: Nginx (读音 “engine x”)免费 ...