http://blog.csdn.net/zhu_tianwei/article/details/40887717

参考:http://blog.csdn.NET/lmj623565791/article/details/37620057

1.生产任务Task.Java

  1. package cn.slimsmart.rabbitmq.demo.workqueue;
  2. import com.rabbitmq.client.AMQP;
  3. import com.rabbitmq.client.Channel;
  4. import com.rabbitmq.client.Connection;
  5. import com.rabbitmq.client.ConnectionFactory;
  6. import com.rabbitmq.client.MessageProperties;
  7. public class Task {
  8. //队列名称
  9. private final static String QUEUE_NAME = "workqueue-durable";
  10. public static void main(String[] args) throws Exception {
  11. //创建连接和频道
  12. ConnectionFactory factory = new ConnectionFactory();
  13. factory.setHost("192.168.101.174");
  14. //指定用户 密码
  15. factory.setUsername("admin");
  16. factory.setPassword("admin");
  17. //指定端口
  18. factory.setPort(AMQP.PROTOCOL.PORT);
  19. Connection connection = factory.newConnection();
  20. Channel channel = connection.createChannel();
  21. boolean durable = true; //设置消息持久化  RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
  22. //声明队列
  23. channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
  24. //发送10条消息,依次在消息后面附加1-10个点
  25. for (int i = 5; i > 0; i--)
  26. {
  27. String dots = "";
  28. for (int j = 0; j <= i; j++)
  29. {
  30. dots += ".";
  31. }
  32. String message = "helloworld" + dots+dots.length();
  33. //MessageProperties.PERSISTENT_TEXT_PLAIN 标识我们的信息为持久化的
  34. channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
  35. System.out.println("Sent Message:'" + message + "'");
  36. }
  37. //关闭频道和资源
  38. channel.close();
  39. connection.close();
  40. }
  41. }

2.消费工作队列

  1. package cn.slimsmart.rabbitmq.demo.workqueue;
  2. import com.rabbitmq.client.AMQP;
  3. import com.rabbitmq.client.Channel;
  4. import com.rabbitmq.client.Connection;
  5. import com.rabbitmq.client.ConnectionFactory;
  6. import com.rabbitmq.client.QueueingConsumer;
  7. public class Work {
  8. //队列名称
  9. private final static String QUEUE_NAME = "workqueue-durable";
  10. public static void main(String[] args) throws Exception {
  11. //区分不同工作进程的输出
  12. int hashCode = Work.class.hashCode();
  13. //创建连接和频道
  14. ConnectionFactory factory = new ConnectionFactory();
  15. factory.setHost("192.168.101.174");
  16. //指定用户 密码
  17. factory.setUsername("admin");
  18. factory.setPassword("admin");
  19. //指定端口
  20. factory.setPort(AMQP.PROTOCOL.PORT);
  21. Connection connection = factory.newConnection();
  22. Channel channel = connection.createChannel();
  23. boolean durable = true; //设置消息持久化  RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
  24. //声明队列
  25. channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
  26. QueueingConsumer consumer = new QueueingConsumer(channel);
  27. /**
  28. * ack= true: Round-robin 转发   消费者被杀死,消息会丢失
  29. * ack=false:消息应答 ,为了保证消息永远不会丢失,RabbitMQ支持消息应答(message acknowledgments)。
  30. * 消费者发送应答给RabbitMQ,告诉它信息已经被接收和处理,然后RabbitMQ可以自由的进行信息删除。
  31. * 如果消费者被杀死而没有发送应答,RabbitMQ会认为该信息没有被完全的处理,然后将会重新转发给别的消费者。
  32. * 通过这种方式,你可以确认信息不会被丢失,即使消者偶尔被杀死。
  33. * 消费者需要耗费特别特别长的时间是允许的。
  34. *
  35. */
  36. boolean ack = false ; //打开应答机制
  37. // 指定消费队列
  38. channel.basicConsume(QUEUE_NAME, ack, consumer);
  39. //公平转发  设置最大服务转发消息数量    只有在消费者空闲的时候会发送下一条信息。
  40. int prefetchCount = 1;
  41. channel.basicQos(prefetchCount);
  42. while (true)
  43. {
  44. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  45. String message = new String(delivery.getBody());
  46. System.out.println(hashCode + " Received Message:'" + message + "'");
  47. doWork(message);
  48. System.out.println(hashCode + " Received Done");
  49. //发送应答
  50. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  51. }
  52. }
  53. /**
  54. * 每个点耗时1s
  55. * @param task
  56. * @throws InterruptedException
  57. */
  58. private static void doWork(String task) throws InterruptedException
  59. {
  60. for (char ch : task.toCharArray())
  61. {
  62. if (ch == '.')
  63. Thread.sleep(1000);
  64. }
  65. }
  66. }

多启动几个消费者工作进程,使用生产者发送消息,可以观察消费情况。

要了解RabbitMQ的路由机制,exchange是一个关键。exchange可以叫做交换机,也似乎可以叫做路由器,反正它是用来选择路由的。RabbitMQ的核心思想就是消息的发布者不是直接把消息发送到目标队列中的,事实上,通常它并不知道消息要发到哪个队列中,它只知道把消息队列发送到exchange中。exchange一边接收发送者发过来的消息,而另一边则把消息发送到目标队列中去。exchange一定知道哪些队列需要接收这个消息,是加到一个队列里还是加到好几个队列里,还是直接扔掉。

如果用空字符串去申明一个exchange,那么系统就会使用"amq.direct"这个exchange。前面我们使用的都是amq.direct类型。

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)的更多相关文章

  1. RabbitMQ学习总结 第三篇:工作队列Work Queue

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  2. (转) RabbitMQ学习之远程过程调用(RPC)(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887885 在一般使用RabbitMQ做RPC很容易.客户端发送一个请求消息然后服务器回复一个响 ...

  3. (转)RabbitMQ学习之Headers交换类型(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40923131 Headers类型的exchange使用的比较少,它也是忽略routingKey的一 ...

  4. (转)RabbitMQ学习之主题topic(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...

  5. (转)RabbitMQ学习之路由(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887755 参考:http://blog.csdn.NET/lmj623565791/artic ...

  6. (转) RabbitMQ学习之发布/订阅(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887733 参考:http://blog.csdn.NET/lmj623565791/artic ...

  7. RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)

    1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...

  8. RabbitMQ学习总结 第二篇:快速入门HelloWorld

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  9. RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

随机推荐

  1. 51nod1117 聪明的木匠【贪心+优先队列】

    一位老木匠需要将一根长的木棒切成N段.每段的长度分别为L1,L2,......,LN(1 <= L1,L2,-,LN <= 1000,且均为整数)个长度单位.我们认为切割时仅在整数点处切且 ...

  2. IDEA全局查找快捷键

    双击shift

  3. Apache2.4更改默认根目录并配置虚拟域名

    软件环境: 1.virtualbox中安装Ubuntu 16.04-server 2.window7下安装Xshell5 以上安装好后, 1.设置virtualbox网络为桥接网卡,启动Ubuntu. ...

  4. Problem 19

    Problem 19 You are given the following information, but you may prefer to do some research for yours ...

  5. 如何设置div自适应高度

    1.给div添加overflow属性 .div{ width:760px; overflow:hidden; } 2.其他的设置height:auto 等我测试没有效果

  6. python orm框架-----SQLALchemy-查询篇

    似乎ORM最难设计的部分是查询.特别是面向对象的查询,今天学习SQLAlchemy,发现SQLAlchemy的查询语法竟如此灵活,惊叹其如此强大的表达能力的同时也对Python也有了更深的认识.下面看 ...

  7. 运行npm run watch时报:events.js:182 throw er; // Unhandled 'error' event

    I had this issue i did the following steps and i have no issues anymore: Delete node_modules directo ...

  8. hdu 4612 双联通缩点+树形dp

    #pragma comment(linker,"/STACK:102400000,102400000")//总是爆栈加上这个就么么哒了 #include<stdio.h> ...

  9. 几种new

    http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new .operator new 和 placement new 区 ...

  10. hdu5326 Work

    题目链接:点击打开链接 题目大意:有n个人.各自管理不同的人,问有多少人管理k个人. 思路:先记录每一个人的直接上级.然后模拟路径压缩的过程进行计数求和. #include<stdio.h> ...