RabbitMq之WorkQueues
来源:互联网 发布:孔板迭代算法app 编辑:程序博客网 时间:2024/05/16 13:44
Round-robin dispatching
ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");Connection connection = factory.newConnection();Channel channel = connection.createChannel();//it will only be created if it doesn't exist alreadychannel.queueDeclare(QUEUE_NAME, true, false, false, null);String[] messages = new String[]{"11 message.","21 message..","31 message...","41 message....","51 message.....","61 message.....","71 message.....","81 message.....","91 message....."};for(String msg : messages){channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); //channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());System.out.println(" [x] Sent '" + msg + "'");}channel.close();connection.close();
编写两个rabbitmq-consumer端代码:(两个consumer是一样的即可)
package yzr.main;import java.io.IOException;import com.rabbitmq.client.AMQP;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.DefaultConsumer;import com.rabbitmq.client.Envelope;public class Worker {private final static String QUEUE_NAME = "hello";public static void main(String[] args) throws Exception {ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); boolean durable = true; channel.queueDeclare(QUEUE_NAME, durable, false, false, null); System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); //channel.basicQos(30); Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println(" [x] Received '" + message + "'"); try { doWork(message); } catch (Exception e) {e.printStackTrace();} finally { System.out.println(" [x] Done"); } } }; boolean autoAck = true; channel.basicConsume(QUEUE_NAME, autoAck, consumer);}private static void doWork(String task) throws InterruptedException { for (char ch: task.toCharArray()) { if (ch == '.') Thread.sleep(1000); }} }
[x] Sent '21 message..'
[x] Sent '31 message...'
[x] Sent '41 message....'
[x] Sent '51 message.....'
[x] Sent '61 message.....'
[x] Sent '71 message.....'
[x] Sent '81 message.....'
[x] Sent '91 message.....'
[x] Done
[x] Received '31 message...'
[x] Done
[x] Received '51 message.....'
[x] Done
[x] Received '71 message.....'
[x] Done
[x] Received '91 message.....'
[x] Done
[x] Received '21 message..'
[x] Done
[x] Received '41 message....'
[x] Done
[x] Received '61 message.....'
[x] Done
[x] Received '81 message.....'
[x] Done
Message acknowledgment
boolean autoAck = false;channel.basicConsume(QUEUE_NAME, autoAck, consumer);
将此处的autoAck的值设为false之后,我们发现当send端发送消息之后,当接受消息的consumer端挂掉之后,rabbitmq会将消息发往到正常的consumer,(消息不会丢失)
[x] Sent '21 message..'
[x] Sent '31 message...'
[x] Sent '41 message....'
[x] Sent '51 message.....'
[x] Sent '61 message.....'
[x] Sent '71 message.....'
[x] Sent '81 message.....'
[x] Sent '91 message.....'
rabbitmqctl.bat list_queues name messages_ready messages_unacknowledged
//确认消息消费 channel.basicAck(envelope.getDeliveryTag(), true);完整的代码:
package yzr.main;import java.io.IOException;import com.rabbitmq.client.AMQP;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.DefaultConsumer;import com.rabbitmq.client.Envelope;public class Worker2 {private final static String QUEUE_NAME = "hello";public static void main(String[] args) throws Exception {ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); boolean durable = false; channel.queueDeclare(QUEUE_NAME, durable, false, false, null); System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); //int prefetchCount = 100; //channel.basicQos(prefetchCount); Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println(" [x] Received '" + message + "'"); try { doWork(message); //确认消息消费 channel.basicAck(envelope.getDeliveryTag(), true); } catch (Exception e) {e.printStackTrace();} finally { System.out.println(" [x] Done"); } } @Override public void handleConsumeOk(String consumerTag) { System.out.println(consumerTag+" reisgter"); } }; boolean autoAck = false; channel.basicConsume(QUEUE_NAME, autoAck, consumer);}private static void doWork(String task) throws InterruptedException { for (char ch: task.toCharArray()) { if (ch == '.') Thread.sleep(1000); }} }
Message durability
消息持久化,比如当我们重启rabbitmqserver服务器的时候,send端发送的消息(已经保存在rabbitmq中的消息)将会全部丢失,为了保证服务器不正常(包括重启)的情况下,保存在服务器中的消息不会丢失,我们可以将发送的消息设置为持久化,即使重启服务器,只要服务器能正常工作的情况下,消息就可以正常获取到.boolean durable = true; channel.queueDeclare(QUEUE_NAME, durable, false, false, null); .... channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
[x] Sent '211 message..'
[x] Sent '311 message...'
[x] Sent '411 message....'
[x] Sent '511 message.....'
[x] Sent '611 message.....'
[x] Sent '711 message.....'
[x] Sent '811 message.....'
[x] Sent '911 message.....'
Marking messages as persistent doesn't fully guarantee that a message won't be lost. Although it tells RabbitMQ to save the message to disk, there is still a short time window when RabbitMQ has accepted a message and hasn't saved it yet. Also, RabbitMQ doesn't do fsync(2) for every message -- it may be just saved to cache and not really written to the disk. The persistence guarantees aren't strong, but it's more than enough for our simple task queue.
Fair dispatch
设置consumer接收消息的数量最大值:
int prefetchCount = 100; channel.basicQos(prefetchCount);
consumer只会最多接收指定的条数的消息,比如这里指定了100,那么即使send端发送了101条消息到这里,此consumer只会接收100条.超出的消息会发送到另外一个不忙的consumer中.
In order to defeat that we can use the basicQos method with the prefetchCount = 1 setting. This tells RabbitMQ not to give more than one message to a worker at a time. Or, in other words, don't dispatch a new message to a worker until it has processed and acknowledged the previous one. Instead, it will dispatch it to the next worker that is not still busy.
- RabbitMq之WorkQueues
- rabbitMq学习之--装RabbitMq(windows)
- RabbitMQ系列之RabbitMQ单机安装
- RabbitMQ之"Hello World!"
- RabbitMQ 之HelloWorld
- RabbitMQ之基础概念
- RabbitMQ之工作队列
- RabbitMQ之Exchange
- RabbitMQ学习之安装
- AMQP之RabbitMq
- 初学RabbitMQ之HelloWorld
- rabbitMq之:Hello World!
- RabbitMQ之路由选择
- RabbitMQ学习之安装
- 4.rabbitmq之路由
- 5.rabbitmq之topic
- 7.rabbitmq之GSON
- RabbitMq之Helloworld
- CodeForces 638 B.Making Genome in Berland(水~)
- PHP的运行模式
- Python 生产者消费者--队列实现
- Android Multimedia实战(四)MediaProjection实现截图,与MediaMuxer实现录屏为MP4,Gif格式
- Jedis使用
- RabbitMq之WorkQueues
- 通过Sqoop将Oracle中表导入到HDFS时报错Error during import: No primary key could be found
- awk
- CSU 1808 地铁【思维建图+最短路Dij+Heap】
- 业余开发了一款app
- 数论简单题pat光棍
- Nginx反向代理,负载均衡,redis session共享,keepalived高可用
- JavaScript学习笔记11-全局变量和局部变量
- 经验分享之tips(3)