工作队列:Working Queue
 
工作队列这个概念与简单的发送/接收消息的区别就是:接收方接收到消息后,可能需要花费更长的时间来处理消息,这个过程就叫一个Work/Task。
 
几个概念
分配:多个接收端接收同一个Queue时,如何分配?
消息确认:Server端如何确定接收方的Work已经对消息进行了完整的处理?
消息持久化:发送方、服务端Queue如何对未处理的消息进行磁盘持久化?
 
Round-robin分配
多个接收端接收同一个Queue时,采用了Round-robin分配算法,即轮叫调度——依次分配给各个接收方。
 
消息确认
默认开启了消息确认(接收方接收到消息后,立即向服务器发回确认)。消息接收方处理完消息后,向服务器发送消息确认,服务器再删除该消息。
 
对于耗时的work,可以先关闭自动消息确认,在work完成后,再手动发回确认。
channel.basicConsume("hello",false/*关闭自动消息确认*/,consumer);
// ...work完成后
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
 
持久化
 
1. Server端的Queue持久化
注意的是,如果已经声明了同名非持久化的Queue,则再次声明无效。
发送方和接收方都需要指定该参数。
boolean durable = true;
channel.queueDeclare("task_queue", durable, false, false, null); 
 
2. Message持久化
channel.basicPublish("", "task_queue", MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
 
负载分配
 
为了解决各个接收端工作量相差太大的问题(有的一直busy,有的空闲比较多),突破Round-robin。
int prefetchCount = 1;
channel.basicQos(prefetchCount);
意思为,最多为当前接收方发送一条消息。如果接收方还未处理完毕消息,还没有回发确认,就不要再给他分配消息了,应该把当前消息分配给其它空闲接收方。
 

固定关键词路由:Routing
 
使用类型为direct的exchange,发送特定关键词(RoutingKey)的消息给订阅该关键词的Queue。
 
场景示例:消息发送方发送了类型为[error][info]的两种消息,写磁盘的消息接受者只接受error类型的消息,Console打印的接收两者。
 
(上图采用了不同颜色来作为routingKey)
 
发送方
 
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "direct"/*exchange类型为direct*/); channel.basicPublish(EXCHANGE_NAME, "info"/*关键词=info*/, null, message.getBytes());
channel.close();
connection.close();
 
接收方
 
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "direct"/*exchange类型为direct*/);
// 创建匿名Queue
String queueName = channel.queueDeclare().getQueue();
// 订阅某个关键词,绑定到匿名Queue中
channel.queueBind(quueName,EXCHANGE_NAME,"error");
channel.queueBind(quueName,EXCHANGE_NAME,"info"); QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer); QueueingConsumer.Delivery delivery = consumer.nextDelivery(); // Blocking...
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey(); // 可获取路由关键词

关键词模式路由:Topics
 
这种模式可以看做对Routing的扩展。Routing只能使用固定关键词,而Topics模式可以订阅模糊关键词。
 
关键词必须是一组word,由点号分割。例如"xxx.yyy.zzz",限定255bytes。
* 表示一个word;
# 表示0个或者多个word;
 
 
发送方
 
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic"/*exchange类型*/); channel.basicPublish(EXCHANGE_NAME, "xxx.yyy"/*关键词routingKey*/, null, message.getBytes());
channel.close();
connection.close();
接收方
 
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic"/*exchange类型*/);
// 创建匿名Queue
String queueName = channel.queueDeclare().getQueue();
// 订阅某个关键词,绑定到匿名Queue中
channel.queueBind(quueName,EXCHANGE_NAME,"*.yyy"); QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer); QueueingConsumer.Delivery delivery = consumer.nextDelivery(); // Blocking...
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey(); // 可获取路由关键词

Refs
 

RabbitMQ的工作队列和路由的更多相关文章

  1. RabbitMQ六种队列模式-路由模式

    前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...

  2. 【译】RabbitMQ:工作队列(Work Queue)

    在第一篇我们写了两个程序通过一个命名的队列分别发送和接收消息.在这一篇,我们将创建一个工作队列在多个工作线程间分发耗时的工作任务. 工作队列的核心思想是避免立刻处理资源密集型任务导致必须等待其执行完成 ...

  3. RabbitMQ 笔记-工作队列

    工作队列的主要思想是不用等待资源密集型的任务处理完成, 为了确保消息或者任务不会丢失,rabbitmq 支持消息确信 ACK.ACK机制是消费者端从rabbitmq收到消息并处理完成后,反馈给rabb ...

  4. RabbitMQ之工作队列

    工作队列 工作队列(又称:任务队列Task Queues)是为了避免等待一些占用大量资源.时间的操作,当我们把任务Task当做消息发送队列中,一个运行在后台的工作者worker进程就会取出任务然后处理 ...

  5. [译]RabbitMQ教程C#版 - 路由

    先决条件 本教程假定 RabbitMQ 已经安装,并运行在localhost标准端口(5672).如果你使用不同的主机.端口或证书,则需要调整连接设置. 从哪里获得帮助 如果您在阅读本教程时遇到困难, ...

  6. rabbitmq系列四 之路由

    1.路由 在上一个的教程中,我们构建了一个简单的日志记录系统.我们能够向许多接收者广播日志消息. 在本次教程中,我们向该系统添加一些特性,比如,我只需要严重错误(erroe级别)的部分日志打印到磁盘文 ...

  7. rabbitMQ的三种路由模式

    rabbitMQ工作流程: 1.声明交换机 2.声明消息队列 3.绑定交换机和队列 4.生产者往交换机里发送新消息 5.交换机根据所选的模式和routingKey决定消息发往哪条消息队列 6.一个消费 ...

  8. RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)

    在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者.在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息.例如,我们希望只将error级别的错误存储到硬盘中,同时可以将 ...

  9. RabbitMQ处理未被路由的消息

    我们经常使用消息队列进行系统之间的解耦,日志记录等等.但是有时候我们在使用 RabbitMQ时,由于exchange.bindKey.routingKey没有设置正确,导致我们发送给交换器(excha ...

随机推荐

  1. Odoo10尝鲜:出勤登记

    非常的cool,使用一个 联网的PAD 就能使用超级潮的 出勤登记功能     扫描 工牌条码,或者 从员工目录选择 员工, 例如 输入 PIN 密码, 防止"代打卡"       ...

  2. python学习之路-day2-pyth基础2

    一.        模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...

  3. HLSL之镜面反射光照

    今天学习的是镜面的反射光照,其实一般在场景中基本环境光和漫反射光照已经可以表现出一个不错的照明了,今天的镜面反射光照其实仅仅适合于需要在表面添加抛光或者闪耀的物体上,例如金属.玻璃等等,同时也是基于之 ...

  4. php 消息实时推送(反ajax推送)

    入口文件index.html <!DOCTYPE HTML> <html> <head> <title>反ajax推送</title> &l ...

  5. 【筛法求素数】【质因数分解】bzoj2721 [Violet 5]樱花

    http://www.cnblogs.com/rausen/p/4138233.html #include<cstdio> #include<iostream> using n ...

  6. Replace Pioneer 续用2

    软件介绍(摘自百度百科) Replace Pioneer(中文名:替换先锋)是Mind Pioneer出品的一款共享软件.    Replace Pioneer是一款与众不同的专业文本批量替换和处理软 ...

  7. (转)EntityFrameword “Reverse Engineer Code First” 连接 MySql

    转自:http://stackoverflow.com/questions/19676624/error-trying-to-reverse-engineer-code-first-mysql-dat ...

  8. (并查集)~APTX4869(fzu 2233)

    http://acm.fzu.edu.cn/problem.php?pid=2233 Problem Description 为了帮助柯南回到一米七四,阿笠博士夜以继日地研究APTX4869的解药.他 ...

  9. [算法]——全排列(Permutation)以及next_permutation

    排列(Arrangement),简单讲是从N个不同元素中取出M个,按照一定顺序排成一列,通常用A(M,N)表示.当M=N时,称为全排列(Permutation).从数学角度讲,全排列的个数A(N,N) ...

  10. php后台开发(一)hello world

    php后台开发(一)hello world 环境安装 开发环境为Ubuntu 12.04,选择linux+apache+php的开发环境 安装 apache2 sudo apt-get install ...