RabbitMq worker Round-Robin
RabbitMq的轮询模式不会因为机器的带宽不同而导致不对等消费 比如A 处理需要10ms,B处理需要1000ms ,两个消费者去消费20条会各消费10条
以下demo实现了均衡消费
package com.wangbiao.work.lunxun; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description rout 路由 * @date 2021/3/22 21:54 */ public class Producer { public static void main(String[] args) throws IOException, TimeoutException { //所有的中间件的技术都是基于tcp/ip协议 ,只不过rabbitmq遵循的是amqp //1创建工程连接 ConnectionFactory connectionFactory=new ConnectionFactory(); connectionFactory.setHost("127.0.0.1"); connectionFactory.setPort(5672); connectionFactory.setPassword("guest"); connectionFactory.setUsername("guest"); connectionFactory.setVirtualHost("/"); Connection connection=null; Channel channel=null; //2创建连接 基于channel处理的原因是长连接 高并发的场景下会创建多个通道性能很高 如果是基于连接就会产生3次挥手等行为 很消耗性能 try { connection=connectionFactory.newConnection("生产者"); //3通过连接获取通道 channel=connection.createChannel(); for (int i = 0; i <=20 ; i++) { String msg="我要变强:"+i; channel.basicPublish("","queue1",null,msg.getBytes());//默认是rabbit-AMQP默认的direct直连路由 } System.out.println("消息发送成功"); } catch (IOException e) { e.printStackTrace(); System.out.println("消息发送异常"); } catch (TimeoutException e) { e.printStackTrace(); }finally { //7关闭连接 if(channel!=null&&channel.isOpen()){ channel.close(); } //8关闭通道 if(connection!=null&&connection.isOpen()){ connection.close(); } } } }
消费者1:
package com.wangbiao.work.lunxun; import com.rabbitmq.client.*; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.concurrent.TimeoutException; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description TODO * @date 2021/3/22 22:28 */ public class Worker1 { public static Runnable runable=new Runnable() { @Override public void run() { //所有的中间件的技术都是基于tcp/ip协议 ,只不过rabbitmq遵循的是amqp //1创建工程连接 ConnectionFactory connectionFactory=new ConnectionFactory(); connectionFactory.setHost("127.0.0.1"); connectionFactory.setPort(5672); connectionFactory.setPassword("guest"); connectionFactory.setUsername("guest"); connectionFactory.setVirtualHost("/"); Connection connection=null; Channel channel=null; //获取队列名字 final String queueName=Thread.currentThread().getName(); //2创建连接工程 try { connection=connectionFactory.newConnection("消费者-worker1"); //3通过连接获取通道 channel=connection.createChannel(); //4通过创建交换机,生命队列,绑定关系,路由key,发送消息,和接收消息 /** * 队列的名字 * 是否要持久化 所谓是否持久化消息是否存盘,false 非持久化 true持久化?非持久化会存盘?会存盘但随着服务器重启会丢失 * 是否自动删除,最后一个消息完毕以后是否把队列自动删除 * 队列的参数 */ channel.basicConsume(queueName, true,new DeliverCallback(){//实际业务中要改为false 因为如果设置为true一旦消息确认失败会造成死循环。 //为false就是要手动确认避免死信队列 public void handle(String consumerTag,Delivery message) throws UnsupportedEncodingException { System.out.println(message.getEnvelope().getDeliveryTag()); System.out.println(queueName+"收到的消息是:"+new String(message.getBody(),"utf-8")); } },new CancelCallback(){ public void handle(String consumerTag) throws UnsupportedEncodingException { System.out.println(queueName+"接收失败了"); } }); System.in.read(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); }finally { //7关闭连接 if(channel!=null&&channel.isOpen()){ try { channel.close(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } //8关闭通道 if(connection!=null&&connection.isOpen()){ try { connection.close(); } catch (IOException e) { e.printStackTrace(); } } } } }; public static void main(String[] args) throws IOException, TimeoutException { new Thread(runable,"queue1").start(); } }
消费者2:
package com.wangbiao.work.lunxun; import com.rabbitmq.client.*; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.concurrent.TimeoutException; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description TODO * @date 2021/3/22 22:28 */ public class Worker2 { public static Runnable runable=new Runnable() { @Override public void run() { //所有的中间件的技术都是基于tcp/ip协议 ,只不过rabbitmq遵循的是amqp //1创建工程连接 ConnectionFactory connectionFactory=new ConnectionFactory(); connectionFactory.setHost("127.0.0.1"); connectionFactory.setPort(5672); connectionFactory.setPassword("guest"); connectionFactory.setUsername("guest"); connectionFactory.setVirtualHost("/"); Connection connection=null; Channel channel=null; //获取队列名字 final String queueName=Thread.currentThread().getName(); //2创建连接工程 try { connection=connectionFactory.newConnection("消费者-worker1"); //3通过连接获取通道 channel=connection.createChannel(); //4通过创建交换机,生命队列,绑定关系,路由key,发送消息,和接收消息 /** * 队列的名字 * 是否要持久化 所谓是否持久化消息是否存盘,false 非持久化 true持久化?非持久化会存盘?会存盘但随着服务器重启会丢失 * 是否自动删除,最后一个消息完毕以后是否把队列自动删除 * 队列的参数 */ // channel.basicQos(1); channel.basicConsume(queueName, true,new DeliverCallback(){ public void handle(String consumerTag,Delivery message) throws UnsupportedEncodingException { System.out.println(message.getEnvelope().getDeliveryTag()); System.out.println(queueName+"收到的消息是:"+new String(message.getBody(),"utf-8")); } },new CancelCallback(){ public void handle(String consumerTag) throws UnsupportedEncodingException { System.out.println(queueName+"接收失败了"); } }); System.in.read(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); }finally { //7关闭连接 if(channel!=null&&channel.isOpen()){ try { channel.close(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } //8关闭通道 if(connection!=null&&connection.isOpen()){ try { connection.close(); } catch (IOException e) { e.printStackTrace(); } } } } }; public static void main(String[] args) throws IOException, TimeoutException { new Thread(runable,"queue1").start(); } }
可以看到两个消费者依次消费:1,3,5,7.。。。。0,。和0,2,4,6,8.。 实现均衡消费
一点点学习,一丝丝进步。不懈怠,才不会被时代淘汰