一、出现背景
在我的前一篇博客中,我们简单说明了simple queue 简单队列的发送和接受操作,但总体看代码和流程,我们会发现存在很多不足。
简单队列存在的不足:
耦合性过高。
1、生产者和消费者必须保证一一对应,如果需要实现多个消费者共同消费同一个消息生产者生产的消息时,则会出问题。(消息一旦消费就没有了)
2、生产者的队列名称发生变更后,消息消费者的队列名也需要同时进行变更操作。
所以,我们今天一起共同学习另外一个消息队列work queue工作队列。
二、工作队列的模型
p:消息生产者
c1、c2:消息消费者
红色的则是消息队列
为什么会出现 work queue 工作队列?
simple queue 是 消息消费者和消息生产者一一对应的关系,在实际开发中,生产者发送消息是毫不费力的,而消费者一般是要跟业务相结合的,消费者收到消息就需要处理。可能需要花费时间,这时候队列中就会积压过多的消息。
三、实现方式
3.1、消息生产者
与上一篇博客的差别也就是命名不同,其次是发了多条消息。
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import cn.linkpower.util.MqConnectUtil;
public class Send {
private static final String queue_name = "test_work_queue";
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1、建立连接
Connection mqConnection = MqConnectUtil.getMqConnection();
//2、建立信道(通道)
Channel channel = mqConnection.createChannel();
//3、声明队列
channel.queueDeclare(queue_name, false, false, false, null);
//4、发送100条消息
for (int i = 0; i < 50; i++) {
String string = "hello xiangjiao "+i;
System.out.println("send msg = "+string);
//发送消息
channel.basicPublish("", queue_name, null, string.getBytes());
//消息发送慢一点
Thread.sleep(i*20);
}
//5、使用完毕后,需要及时的关闭流应用
channel.close();
mqConnection.close();
}
}
3.2、消费者一和消费者二
1、消费者一和二的区别只是在打印数据时,输出不同,一个是msg1,一个是msg2,这里只列出消费者一的代码。
2、消费者二的延迟相比消费者一而言,消费者一为1000ms,消费者二为2000ms。
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties;
import cn.linkpower.util.MqConnectUtil;
public class GetMsg1 {
private final static String queue_name="test_work_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//1、建立连接
Connection mqConnection = MqConnectUtil.getMqConnection();
//2、获取信道
Channel channel = mqConnection.createChannel();
//3、声明队列
channel.queueDeclare(queue_name, false, false, false, null);
//4、信访室接受消息
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" get msg new1 = " + message );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("get msg new1 done");
}
}
};
//5、创建监听
channel.basicConsume(queue_name,true, consumer);
}
}
四、运行测试
先运行消息消费者一和二,提前创建好监听。
再运行消息生产者代码,观察运行打印信息效果。
消息生产者运行效果
消息消费者一运行效果
消息消费者二运行效果
现象:
1、消费者一延时 1000ms,消费者二延时 2000ms,但消息数一致。
2、效益一为偶数,消息二为基数。
结论:
这种消息机制叫轮询分发,两者的延迟时间并不会影响到获取到的消息数目。
消息消费为分发处理----模。消息数%2、消息数%n