一: direct

上面我用采用了广播的模式进行消息的发送,现在我们采用路由的方式对不同的消息进行过滤

发送端代码

  1. public class RoutingSendDirect {
  2. private static final String EXCHANGE_NAME = "direct_logs";
  3. // 路由关键字
  4. private static final String[] routingKeys = new String[]{"info" ,"warning", "error"};
  5. public static void main(String[] args) throws IOException, TimeoutException {
  6. ConnectionFactory factory = new ConnectionFactory();
  7. factory.setHost("localhost");
  8. Connection connection = factory.newConnection();
  9. Channel channel = connection.createChannel();
  10. //声明交换机
  11. channel.exchangeDeclare(EXCHANGE_NAME,"direct");//注意是direct
  12. //发送信息
  13. for (String routingKey:routingKeys){
  14. String message = "RoutingSendDirect Send the message level:" + routingKey;
  15. channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes());
  16. System.out.println("RoutingSendDirect Send"+routingKey +"':'" + message);
  17. }
  18. channel.close();
  19. connection.close();
  20. }
  21. }
  1. ReceiveLogsDirect1 消费者代码
  1. public class ReceiveLogsDirect1 {
  2. // 交换器名称
  3. private static final String EXCHANGE_NAME = "direct_logs";
  4. // 路由关键字
  5. private static final String[] routingKeys = new String[]{"info" ,"warning"};
  6.  
  7. public static void main(String[] args) throws IOException, TimeoutException {
  8. ConnectionFactory factory = new ConnectionFactory();
  9. factory.setHost("localhost");
  10. Connection connection = factory.newConnection();
  11. Channel channel = connection.createChannel();
  12. //声明交换器
  13. channel.exchangeDeclare(EXCHANGE_NAME, "direct");
  14. //获取匿名队列名称
  15. String queueName=channel.queueDeclare().getQueue();
  16.  
  17. //根据路由关键字进行绑定
  18. for (String routingKey:routingKeys){
  19. channel.queueBind(queueName,EXCHANGE_NAME,routingKey);
  20. System.out.println("ReceiveLogsDirect1 exchange:"+EXCHANGE_NAME+"," +
  21. " queue:"+queueName+", BindRoutingKey:" + routingKey);
  22. }
  23. System.out.println("ReceiveLogsDirect1 Waiting for messages");
  24. Consumer consumer = new DefaultConsumer(channel) {
  25. @Override
  26. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
  27. String message = new String(body, "UTF-8");
  28. System.out.println("ReceiveLogsDirect1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
  29. }
  30. };
  31. channel.basicConsume(queueName, true, consumer);
  32. }
  1. ReceiveLogsDirect2消费者代码
  1. public class ReceiveLogsDirect2 {
  2. // 交换器名称
  3. private static final String EXCHANGE_NAME = "direct_logs";
  4. // 路由关键字
  5. private static final String[] routingKeys = new String[]{"error"};
  6.  
  7. public static void main(String[] argv) throws Exception {
  8. ConnectionFactory factory = new ConnectionFactory();
  9. factory.setHost("localhost");
  10. Connection connection = factory.newConnection();
  11. Channel channel = connection.createChannel();
  12. //声明交换器
  13. channel.exchangeDeclare(EXCHANGE_NAME, "direct");
  14. //获取匿名队列名称
  15. String queueName = channel.queueDeclare().getQueue();
  16. //根据路由关键字进行多重绑定
  17. for (String severity : routingKeys) {
  18. channel.queueBind(queueName, EXCHANGE_NAME, severity);
  19. System.out.println("ReceiveLogsDirect2 exchange:"+EXCHANGE_NAME+", queue:"+queueName+", BindRoutingKey:" + severity);
  20. }
  21. System.out.println("ReceiveLogsDirect2 Waiting for messages");
  22.  
  23. Consumer consumer = new DefaultConsumer(channel) {
  24. @Override
  25. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws UnsupportedEncodingException {
  26. String message = new String(body, "UTF-8");
  27. System.out.println("ReceiveLogsDirect2 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
  28. }
  29. };
  30. channel.basicConsume(queueName, true, consumer);
  31. }
  32. }

上面代码可以看出这里是通过路由来找个这个对列的。我们看下结果

二:Topics

这种应该属于模糊匹配

* :可以替代一个词

#:可以替代0或者更多的词

现在我们继续看看代码来理解

发送端

  1. public class TopicSend {
  2. private static final String EXCHANGE_NAME = "topic_logs";
  3.  
  4. public static void main(String[] args) throws IOException, TimeoutException {
  5. Connection connection = null;
  6. Channel channel = null;
  7. try{
  8. ConnectionFactory factory=new ConnectionFactory();
  9. factory.setHost("localhost");
  10. connection=factory.newConnection();
  11. channel=connection.createChannel();
  12.  
  13. //声明一个匹配模式的交换机
  14. channel.exchangeDeclare(EXCHANGE_NAME,"topic");
  15. //待发送的消息
  16. String[] routingKeys=new String[]{
  17. "quick.orange.rabbit",
  18. "lazy.orange.elephant",
  19. "quick.orange.fox",
  20. "lazy.brown.fox",
  21. "quick.brown.fox",
  22. "quick.orange.male.rabbit",
  23. "lazy.orange.male.rabbit"
  24. };
  25. //发送消息
  26. for(String severity :routingKeys){
  27. String message = "From "+severity+" routingKey' s message!";
  28. channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
  29. System.out.println("TopicSend Sent '" + severity + "':'" + message + "'");
  30. }
  31. }catch (Exception e){
  32. e.printStackTrace();
  33. if (connection!=null){
  34. channel.close();
  35. connection.close();
  36. }
  37. }finally {
  38. if (connection!=null){
  39. channel.close();
  40. connection.close();
  41. }
  42. }
  43. }
  44. }

消费者1:

  1. public class ReceiveLogsTopic1 {
  2. private static final String EXCHANGE_NAME = "topic_logs";
  3.  
  4. public static void main(String[] args) throws IOException, TimeoutException {
  5. ConnectionFactory factory = new ConnectionFactory();
  6. factory.setHost("localhost");
  7. Connection connection = factory.newConnection();
  8. Channel channel = connection.createChannel();
  9.  
  10. //声明一个匹配模式的交换机
  11. channel.exchangeDeclare(EXCHANGE_NAME, "topic");
  12. String queueName = channel.queueDeclare().getQueue();
  13. //路由关键字
  14. String[] routingKeys = new String[]{"*.orange.*"};
  15. //绑定路由
  16. for (String routingKey : routingKeys) {
  17. channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
  18. System.out.println("ReceiveLogsTopic1 exchange:" + EXCHANGE_NAME + ", queue:" + queueName + ", BindRoutingKey:" + routingKey);
  19. }
  20. System.out.println("ReceiveLogsTopic1 Waiting for messages");
  21.  
  22. Consumer consumer = new DefaultConsumer(channel) {
  23. @Override
  24. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
  25. String message = new String(body, "UTF-8");
  26. System.out.println("ReceiveLogsTopic1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
  27. }
  28. };
  29. channel.basicConsume(queueName, true, consumer);
  30. }
  31. }

消费者2:

  1. 复制代码
  2.  
  3. ublic class ReceiveLogsTopic2 {
  4. private static final String EXCHANGE_NAME = "topic_logs";
  5.  
  6. public static void main(String[] argv) throws IOException, TimeoutException {
  7. ConnectionFactory factory = new ConnectionFactory();
  8. factory.setHost("localhost");
  9. Connection connection = factory.newConnection();
  10. Channel channel = connection.createChannel();
  11. // 声明一个匹配模式的交换器
  12. channel.exchangeDeclare(EXCHANGE_NAME, "topic");
  13. String queueName = channel.queueDeclare().getQueue();
  14. // 路由关键字
  15. String[] routingKeys = new String[]{"*.*.rabbit", "lazy.#"};
  16. // 绑定路由关键字
  17. for (String bindingKey : routingKeys) {
  18. channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
  19. System.out.println("ReceiveLogsTopic2 exchange:"+EXCHANGE_NAME+", queue:"+queueName+", BindRoutingKey:" + bindingKey);
  20. }
  21.  
  22. System.out.println("ReceiveLogsTopic2 Waiting for messages");
  23.  
  24. Consumer consumer = new DefaultConsumer(channel) {
  25. @Override
  26. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws UnsupportedEncodingException {
  27. String message = new String(body, "UTF-8");
  28. System.out.println("ReceiveLogsTopic2 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
  29. }
  30. };
  31. channel.basicConsume(queueName, true, consumer);
  32. }
  33. }

三,远程调用

  1. public class RPCServer {
  2. private static final String RPC_QUEUE_NAME = "rpc_queue";
  3. private static int fib(int n) {
  4. if (n == 0) {
  5. return 0;
  6. }
  7. if (n == 1) {
  8. return 1;
  9. }
  10. return fib(n - 1) + fib(n - 1);
  11. }
  12. public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
  13. ConnectionFactory factory = new ConnectionFactory();
  14. factory.setHost("localhost");
  15. Connection connection = factory.newConnection();
  16. Channel channel = connection.createChannel();
  17. channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
  18. channel.basicQos(1);
  19. QueueingConsumer consumer = new QueueingConsumer(channel);
  20. channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
  21.  
  22. System.out.println("RPCServer Awating RPC request");
  23. while (true) {
  24. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  25. BasicProperties props = delivery.getProperties();
  26. BasicProperties replyProps = new AMQP.BasicProperties.Builder().
  27. correlationId(props.getCorrelationId()).build();
  28.  
  29. String message = new String(delivery.getBody(), "UTF-8");
  30. int n = Integer.parseInt(message);
  31.  
  32. System.out.println("RPCServer fib(" + message + ")");
  33. String response = "" + fib(n);
  34. channel.basicPublish( "", props.getReplyTo(), replyProps, response.getBytes());
  35. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  36. }
  37. }
  38. }

服务器代码比较简单
1:建立连接,通道,队列
2:我们可能运行多个服务器进程,为了分散负载服务器压力,我们设置channel.basicQos(1);
3:我们用basicconsume访问队列。然后进入循环,在其中我们等待请求消息并处理消息然后发送响应。

  1. public class RPCClient {
  2. private Connection connection;
  3. private Channel channel;
  4. private String requestQueueName = "rpc_queue";
  5. private String replyQueueName;
  6. private QueueingConsumer consumer;
  7. public RPCClient() throws IOException, TimeoutException {
  8. ConnectionFactory factory = new ConnectionFactory();
  9. factory.setHost("localhost");
  10. connection = factory.newConnection();
  11. channel = connection.createChannel();
  12.  
  13. replyQueueName = channel.queueDeclare().getQueue();
  14. consumer = new QueueingConsumer(channel);
  15. channel.basicConsume(replyQueueName, true, consumer);
  16. }
  17. public String call(String message) throws IOException, InterruptedException {
  18. String response;
  19. String corrID = UUID.randomUUID().toString();
  20. AMQP.BasicProperties props = new AMQP.BasicProperties().builder()
  21. .correlationId(corrID).replyTo(replyQueueName).build();
  22. channel.basicPublish("", requestQueueName, props, message.getBytes("UTF-8"));//发送消息等待服务端返回
  23. while (true) {
  24. QueueingConsumer.Delivery delivery = consumer.nextDelivery();//服务端响应后 阻塞解除
  25. if (delivery.getProperties().getCorrelationId().equals(corrID)) {
  26. response = new String(delivery.getBody(), "UTF-8");
  27. break;
  28. }
  29. }
  30. return response;
  31. }
  32. public void close() throws Exception {
  33. connection.close();
  34. }
  35. public static void main(String[] args) throws Exception {
  36. RPCClient rpcClient = null;
  37. String response;
  38. try {
  39. rpcClient = new RPCClient();
  40. System.out.println("RPCClient Requesting fib(20)");
  41. response = rpcClient.call("20");
  42. System.out.println("RPCClient Got '" + response + "'");
  43. } catch (Exception e) {
  44. e.printStackTrace();
  45. } finally {
  46. if (rpcClient != null) {
  47. rpcClient.close();
  48. }
  49. }
  50. }
  51. }

客户端代码解读
1:建立一个连接和通道,并声明了一个唯一的“回调”队列的答复
2:我们订阅回调队列,这样就可以得到RPC的响应
3:定义一个call方法用于发送当前的回调请求
4:生成一个唯一的correlationid,然后通过while循环来捕获合适的回应
5:我们请求信息,发送2个属性,replyTo 和correlationId
6:然后就是等待直到有合适的回应到达
7:while循环是做一个非常简单的工作,对于每一个响应消息,它检查是否有correlationid然后进行匹配。然后是就进行响应。
8:最后把响应返回到客户端。

rabbitMq交换机direct、topics的更多相关文章

  1. RabbitMQ交换机、RabbitMQ整合springCloud

    目标 1.交换机 2.RabbitMQ整合springCloud 交换机 蓝色区域===生产者 红色区域===Server:又称Broker,接受客户端的连接,实现AMQP实体服务 绿色区域===消费 ...

  2. RabbitMQ 交换机类型

    1,扇形交换机 fanout 2, 直连交换机 direct 3, 通配符交换机 topic

  3. SpringBoot应用操作Rabbitmq(direct高级操作)

    一.首先声明完成任务架构,通过direct订阅/发布的模式进行生产消费. a.消息生产指定交换器和路由key b.消费者绑定交换器,路由key和队列的关系(集群监控收到的消息不重复) 二.实战演练 1 ...

  4. rabbitmq 交换机模式一 直连模式 direct

    代码 <?php require_once "./vendor/autoload.php"; use PhpAmqpLib\Connection\AMQPStreamConn ...

  5. RabbitMQ交换机规则实例

    RabbitMQ Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct.fanout.topic.headers .headers 匹配 AMQP 消息的 header ...

  6. 认识RabbitMQ交换机模型

    前言 RabbitMQ是消息队列中间件(Message Queue Middleware)中一种,工作虽然有用到,但是却没有形成很好的整体包括,主要是一些基础概念的认识,这里通过阅读<Rabbi ...

  7. 关于RabbitMQ交换机的理解

    RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.消息中间件主要用于组件之间的解耦,消 ...

  8. spring boot整合RabbitMQ(Direct模式)

    springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. Direct Excha ...

  9. Rabbit的直连交换机direct

    直连交换机类型为:direct.加入了路由键routingKey的概念. 就是说 生产者投递消息给指定交换机的指定路由键. 只有绑定了此交换机指定路由键的消息队列才可以收到消息. 生产者: packa ...

随机推荐

  1. mysql having和where的区别

    having子句与where子句一样,都是用于条件判断的. 区别1 where是判断数据从磁盘读入内存的时候 having是判断分组统计之前的所有条件 区别原理 区别2 having子句中可以使用字段 ...

  2. Gparted Live分区调整

    由于年少无知,在安装ubuntu系统的时候,以为/temp是软件包安装时解压的缓冲,所以给/temp留了10G,而以为/var只是记录一些log而已,因此把仅存的1G分配给了它.随后在安装软件时出现“ ...

  3. ubuntu16.04 anaconda的安装和卸载

    第一次安装: 1.直接从官网下载了anaconda安装包,然后bash ...sh安装. 2.过程中主要需要选择安装路径,为了把安装的软件都放在一起,我新建了一个install_software在系统 ...

  4. 取消Fragment切换时间,Fragment+ViewPager静止滑动,去掉默认的滑动效果

    import android.content.Context; import android.support.v4.view.ViewPager; import android.util.Attrib ...

  5. 如何为Windows XP / Windows7-32bit / Windows7-64bit安装capicom.dll

    原文: http://164.100.181.16/ssdgsap/RegisterDLL.htm 1.根据操作系统的要求下载相应的文件夹安装capicom.dll for Windows XP的步骤 ...

  6. 解决:vue项目中多个echarts图表只有最后一个随浏览器变化改变大小

    window.onresize = () => { this.initChart()} 改为 window.addEventListener('resize', () => { this. ...

  7. LeetCode 78 - 子集

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3]输出:[ [3], [1], [2], [1, ...

  8. Random类 一般跟生成随机数有关

    public class MyRandom extends Random{ public static void main(String[] args) { // 随机数,生产随机数 // java提 ...

  9. docsis cm 上线过程(bigwhite)

    扫描与同步下行(SYNC消息) 获取上行参数(UCD消息.MAP消息)  通过测距完成时间偏移等的调整(RNG消息) 设备类型鉴定(可选,DCI消息) 建立IP通道(DHCP)  同步系统时间(TOD ...

  10. XP下ubuntu双系统安装方法

    利用u盘将iso刻录 从u盘启动 连续按alt+f2 进入ubuntu试用 打开终端 输入 sudo umount -l /cdrom sudo umount -l /isodevice 然后安装un ...