2.rabbitmq之工作队列
来源:互联网 发布:sqlserver bit 默认值 编辑:程序博客网 时间:2024/05/17 02:30
本节主要理解ack,与prefetchCount
ack,设置为false,表示取消自动删除消息,需要手动告诉mq去删除对应的消息,如果当前报错,消息不会丢失
设置为treu,处理后自动删除,如果但钱报错,消息会丢失
prefetchCount:同事处理的数量
与发布订阅的明显区别在于不设置exchange
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;
-
- channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
-
-
- for (int i = 5; i > 0; i--)
- {
- String dots = "";
- for (int j = 0; j <= i; j++)
- {
- dots += ".";
- }
- String message = "helloworld" + dots+dots.length();
-
- 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;
-
- channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
-
- QueueingConsumer consumer = new QueueingConsumer(channel);
-
-
-
-
-
-
-
-
-
-
-
- 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);
-
- }
- }
-
-
-
-
-
-
- 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一定知道哪些队列需要接收这个消息,是加到一个队列里还是加到好几个队列里,还是直接扔掉。
如果用空字符串去申明一个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的效果
0 0