RabbitMQ任务分发机制

Round-robin(轮询分发)

使用任务队列的优点之一就是可以轻易的并行工作。如果我们积压了好多工作,我们可以通过增加工作者(消费者)来解决这一问题,使得系统的伸缩性更加容易。

修改一下NewTask,使用for循环模拟多次发送消息的过程:

for (int i = 0; i < 5; i++) {
	// 发送的消息
	String message = "Hello World"+Strings.repeat(".", i);
	// 往队列中发出一条消息
	channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
	System.out.println(" [x] Sent '" + message + "'");
}

我们先启动1个生产者实例,2个工作者实例,看一下如何执行:

从上述的结果中,我们可以得知,在默认情况下,RabbitMQ不会顾虑消息者处理消息的能力,即使其中有的消费者闲置有的消费者高负荷。RabbitMQ会逐个发送消息到在序列中的下一个消费者(而不考虑每个任务的时长等等,且是提前一次性分配,并非一个一个分配)。平均每个消费者获得相同数量的消息,这种方式分发消息机制称为Round-Robin(轮询)

Fair dispatch(公平分发)

      您可能已经注意到,任务分发仍然没有完全按照我们想要的那样。比如:现在有2个消费者,所有的奇数的消息都是繁忙的,而偶数则是轻松的。按照轮询的方式,奇数的任务交给了第一个消费者,所以一直在忙个不停。偶数的任务交给另一个消费者,则立即完成任务,然后闲得不行。而RabbitMQ则是不了解这些的。这是因为当消息进入队列,RabbitMQ就会分派消息。它不看消费者为应答的数目,只是盲目的将第n条消息发给第n个消费者。

     公平分发,则是根据消费者的处理能力来进行分发处理的。这里主要是通过设置prefetchCount 参数来实现的。这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理规定的数量级个数的Message。换句话说,在接收到该Consumer的ack前,它不会将新的Message分发给它。 比如prefetchCount=1,则在同一时间下,每个Consumer在同一个时间点最多处理1个Message,同时在收到Consumer的ack前,它不会将新的Message分发给它。

为了解决这个问题,我们使用basicQos( prefetchCount = 1)方法,来限制RabbitMQ只发不超过1条的消息给同一个消费者。当消息处理完毕后,有了反馈,才会进行第二次发送。

int prefetchCount = 1;
channel.basicQos(prefetchCount);

      注:如果所有的工作者都处于繁忙状态,你的队列有可能被填充满。你可能会观察队列的使用情况,然后增加工作者,或者使用别的什么策略。
     还有一点需要注意,使用公平分发,必须关闭自动应答,改为手动应答

整体代码如下:生产者NewTask.java

public class NewTask {
	private final static String QUEUE_NAME = "hello";
 
	public static void main(String[] args) throws IOException {
		/**
		 * 创建连接连接到MabbitMQ
		 */
		ConnectionFactory factory = new ConnectionFactory();
		// 设置MabbitMQ所在主机ip或者主机名
		factory.setHost("127.0.0.1");
		// 创建一个连接
		Connection connection = factory.newConnection();
		// 创建一个频道
		Channel channel = connection.createChannel();
		// 指定一个队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		int prefetchCount = 1;
		//限制发给同一个消费者不得超过1条消息
		channel.basicQos(prefetchCount);
		for (int i = 0; i < 5; i++) {
			// 发送的消息
			String message = "Hello World"+Strings.repeat(".",5-i)+(5-i);
			// 往队列中发出一条消息
			channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
			System.out.println(" [x] Sent '" + message + "'");
		}
		// 关闭频道和连接
		channel.close();
		connection.close();
	}
}

消费者Worker.java

public class Worker {
	private final static String QUEUE_NAME = "hello";
 
	public static void main(String[] argv) throws IOException, InterruptedException {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("127.0.0.1");
		// 打开连接和创建频道,与发送端一样
		Connection connection = factory.newConnection();
		final Channel channel = connection.createChannel();
 
		// 声明队列,主要为了防止消息接收者先运行此程序,队列还不存在时创建队列。
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
		channel.basicQos(1);//保证一次只分发一个
		// 创建队列消费者
		final 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 {
			    	for (char ch: message.toCharArray()) {
				        if (ch == '.') {
				        	Thread.sleep(1000);
				        }
				    }
				} catch (InterruptedException e) {
				} finally {
			      System.out.println(" [x] Done! at " +new Date().toLocaleString());
			      channel.basicAck(envelope.getDeliveryTag(), false);  
			    }
			  }
			};
			channel.basicConsume(QUEUE_NAME, false, consumer);
	}
}

文章来源:https://blog.csdn.net/a724888/article/details/80735185

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RabbitMQ是一个开源的消息代理系统,它能够用于构建高效、可靠的任务调度系统。以下是用RabbitMQ任务调度系统的一些主要优势。 首先,RabbitMQ基于AMQP (Advanced Message Queuing Protocol)协议,可以有效地处理大量的消息传递。通过将任务发布到RabbitMQ中的消息队列中,并使用消费者来消费这些任务,可以实现高效、并发的任务调度。 其次,RabbitMQ的消息队列具有强大的可靠性和可恢复性。当一个任务发布到队列中时,它被安全地存储在消息队列中,即使消费者不可用也不丢失。一旦消费者重新上线,它可以从队列中获取任务并执行。 此外,RabbitMQ还支持多种消息确认机制,包括消息的发布确认和消费确认。这些机制确保了任务的可靠传递和消费,可以提高任务调度系统的稳定性和可靠性。 另外,RabbitMQ还提供了灵活的交换器和路由器,可以根据任务的特性和需求进行灵活的路由和分发。这使得任务调度系统可以根据任务的优先级、类型或其他属性进行灵活的调度和分发。 最后,RabbitMQ提供了丰富的工具和API,方便开发人员进行集成和管理。可以使用各种编程语言和框架与RabbitMQ进行交互,并使用其提供的管理界面监控和管理消息队列的状态和性能。 综上所述,使用RabbitMQ作为任务调度系统可以提供高效、可靠的任务分发和执行机制,为复杂任务调度提供了强大的支持。无论是在云计算环境、分布式系统中还是在单机环境中,RabbitMQ都是一个可靠的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值