(转) RabbitMQ学习之工作队列(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887717
参考:http://blog.csdn.NET/lmj623565791/article/details/37620057
1.生产任务Task.Java
- package cn.slimsmart.rabbitmq.demo.workqueue;
- import com.rabbitmq.client.AMQP;
- import com.rabbitmq.client.Channel;
- import com.rabbitmq.client.Connection;
- import com.rabbitmq.client.ConnectionFactory;
- import com.rabbitmq.client.MessageProperties;
- public class Task {
- //队列名称
- private final static String QUEUE_NAME = "workqueue-durable";
- public static void main(String[] args) throws Exception {
- //创建连接和频道
- ConnectionFactory factory = new ConnectionFactory();
- factory.setHost("192.168.101.174");
- //指定用户 密码
- factory.setUsername("admin");
- factory.setPassword("admin");
- //指定端口
- factory.setPort(AMQP.PROTOCOL.PORT);
- Connection connection = factory.newConnection();
- Channel channel = connection.createChannel();
- boolean durable = true; //设置消息持久化 RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
- //声明队列
- channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
- //发送10条消息,依次在消息后面附加1-10个点
- for (int i = 5; i > 0; i--)
- {
- String dots = "";
- for (int j = 0; j <= i; j++)
- {
- dots += ".";
- }
- String message = "helloworld" + dots+dots.length();
- //MessageProperties.PERSISTENT_TEXT_PLAIN 标识我们的信息为持久化的
- channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
- System.out.println("Sent Message:'" + message + "'");
- }
- //关闭频道和资源
- channel.close();
- connection.close();
- }
- }
2.消费工作队列
- package cn.slimsmart.rabbitmq.demo.workqueue;
- import com.rabbitmq.client.AMQP;
- import com.rabbitmq.client.Channel;
- import com.rabbitmq.client.Connection;
- import com.rabbitmq.client.ConnectionFactory;
- import com.rabbitmq.client.QueueingConsumer;
- public class Work {
- //队列名称
- private final static String QUEUE_NAME = "workqueue-durable";
- public static void main(String[] args) throws Exception {
- //区分不同工作进程的输出
- int hashCode = Work.class.hashCode();
- //创建连接和频道
- ConnectionFactory factory = new ConnectionFactory();
- factory.setHost("192.168.101.174");
- //指定用户 密码
- factory.setUsername("admin");
- factory.setPassword("admin");
- //指定端口
- factory.setPort(AMQP.PROTOCOL.PORT);
- Connection connection = factory.newConnection();
- Channel channel = connection.createChannel();
- boolean durable = true; //设置消息持久化 RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
- //声明队列
- channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
- QueueingConsumer consumer = new QueueingConsumer(channel);
- /**
- * ack= true: Round-robin 转发 消费者被杀死,消息会丢失
- * ack=false:消息应答 ,为了保证消息永远不会丢失,RabbitMQ支持消息应答(message acknowledgments)。
- * 消费者发送应答给RabbitMQ,告诉它信息已经被接收和处理,然后RabbitMQ可以自由的进行信息删除。
- * 如果消费者被杀死而没有发送应答,RabbitMQ会认为该信息没有被完全的处理,然后将会重新转发给别的消费者。
- * 通过这种方式,你可以确认信息不会被丢失,即使消者偶尔被杀死。
- * 消费者需要耗费特别特别长的时间是允许的。
- *
- */
- boolean ack = false ; //打开应答机制
- // 指定消费队列
- channel.basicConsume(QUEUE_NAME, ack, consumer);
- //公平转发 设置最大服务转发消息数量 只有在消费者空闲的时候会发送下一条信息。
- int prefetchCount = 1;
- channel.basicQos(prefetchCount);
- while (true)
- {
- QueueingConsumer.Delivery delivery = consumer.nextDelivery();
- String message = new String(delivery.getBody());
- System.out.println(hashCode + " Received Message:'" + message + "'");
- doWork(message);
- System.out.println(hashCode + " Received Done");
- //发送应答
- channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
- }
- }
- /**
- * 每个点耗时1s
- * @param task
- * @throws InterruptedException
- */
- private static void doWork(String task) throws InterruptedException
- {
- for (char ch : task.toCharArray())
- {
- if (ch == '.')
- Thread.sleep(1000);
- }
- }
- }
多启动几个消费者工作进程,使用生产者发送消息,可以观察消费情况。
要了解RabbitMQ的路由机制,exchange是一个关键。exchange可以叫做交换机,也似乎可以叫做路由器,反正它是用来选择路由的。RabbitMQ的核心思想就是消息的发布者不是直接把消息发送到目标队列中的,事实上,通常它并不知道消息要发到哪个队列中,它只知道把消息队列发送到exchange中。exchange一边接收发送者发过来的消息,而另一边则把消息发送到目标队列中去。exchange一定知道哪些队列需要接收这个消息,是加到一个队列里还是加到好几个队列里,还是直接扔掉。
channel.BasicPublish("", "TaskQueue", properties, bytes);
direct exchange 发送消息是要看routingKey的。举个例子,定义了一个direct exchange 名字是X1,然后一个queue名字为Q1 用routingKey=K1 绑定到exchange X1上,当一个routeKey为 K2 的消息到达X1上,那么只有K1=K2的时候,这个消息才能到达Q1上。
fanout类型的exchange就比较好理解。就是简单的广播,而且是忽略routingKey的。所以只要是有queue绑定到fanout exchange上,通过这个exchange发送的消息都会被发送到那些绑定的queue中,不管你有没有输入routingKey。
Topic类型的exchange给与我们更大的灵活性。通过定义routingKey可以有选择的订阅某些消息,此时routingKey就会是一个表达式。exchange会通过匹配绑定的routingKey来决定是否要把消息放入对应的队列中。有两种表达式符号可以让我们选择:#和*。
*(星号):代表任意的一个词。 例:*.a会匹配a.a,b.a,c.a等
#(井号):代码任意的0个或多个词。 例:#.a会匹配a.a,aa.a,aaa.a等
topic exchange 有时候的行为会像其他类型的exchange,比如说:
当routingKey只是有#号的时候,它的行为和fanout的行为是一样的。
当routingKey什么的没有,空字符串的时候,它的行为是和direct是一样的。
要注意的是,符号代表的是词不是字符。RabbitMQ中在表达式中词的定义是以.(点号)分隔的。
Headers类型的exchange使用的比较少。以后再说。
下面主要用代码,实现一下direct、fanout、topic的效果。
(转) RabbitMQ学习之工作队列(java)的更多相关文章
- RabbitMQ学习总结 第三篇:工作队列Work Queue
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- (转) RabbitMQ学习之远程过程调用(RPC)(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887885 在一般使用RabbitMQ做RPC很容易.客户端发送一个请求消息然后服务器回复一个响 ...
- (转)RabbitMQ学习之Headers交换类型(java)
http://blog.csdn.net/zhu_tianwei/article/details/40923131 Headers类型的exchange使用的比较少,它也是忽略routingKey的一 ...
- (转)RabbitMQ学习之主题topic(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...
- (转)RabbitMQ学习之路由(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887755 参考:http://blog.csdn.NET/lmj623565791/artic ...
- (转) RabbitMQ学习之发布/订阅(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887733 参考:http://blog.csdn.NET/lmj623565791/artic ...
- RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)
1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...
- RabbitMQ学习总结 第二篇:快速入门HelloWorld
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
随机推荐
- docker安装部署
1. 如何安装 Epel源到 RHEL/CentOS 7/6/5? RHEL/CentOS rpm -ivh http://mirrors.ustc.edu.cn/epel/7/x86_64/Pack ...
- 洛谷11月月赛(284pts rank85)
https://www.luogu.org/contestnew/show/12006 我是比赛完后在去写的 这是我第一次打洛谷月赛,之前一次是比赛完才去看而且写了第一题就没写后面的了 284分,太水 ...
- Junit在SSH中的集成测试
测试Spring容器 在Junit的测试类中,继承AbstractJUnit4SpringContextTests就可以进行Spring容器测试, 例如下面测试用例, @RunWith(SpringJ ...
- lucene_03_索引的增删改查
lucene索引的添加见 http://www.cnblogs.com/getchen/p/8615276.html 入门代码. 公共代码 public <T extends Query> ...
- Spring Boot-定义拦截器(七)
在web项目 我们常常使用拦截器做权限验证和登陆验证 1.创建一个拦截器实现类 标注@Componet @Component public class LoginInterceputer implem ...
- [bzoj1070][SCOI2007]修车_费用流
修车 bzoj-1070 SCOI-2007 题目大意:有m个人要修n台车,每个工人修不同的车的时间不同,问将所有的车都修完,最少需要花费的时间. 注释:$2\le m\le 9$,$1\le n \ ...
- spring boot使用外部tomcat部署
1:pom里面的packaging修改为war(<packaging>war</packaging>) 2:在pom依赖spring-boot-starter-web排除内置的 ...
- POJ 1379
模拟退火算法. 随机MAX个点,然后,退火移动,选取距离所有点中最短中最长者即可.理解和我上一篇一样. #include <iostream> #include <cstdio> ...
- MongoDB 索引的使用, 管理 和优化
MongoDB 索引的使用, 管理 和优化 2014-03-25 17:12 6479人阅读 评论(0) 收藏 举报 分类: MongoDB(9) [使用explain和hint] 前面讲高级查询 ...
- 站点搭建从零開始(七) WordPress站点的完好
1.WordPress站点前后端经常使用语言简单介绍和执行过程 通常一个站点的整个构建过程中须要大量的技术支持,尤其是用到非常多种计算机语言.站点的构建主要分后端和前端两部分,后端代码在server上 ...