后面慢慢补充
有道云笔记原版
一个生产者对应一个消费者
graph LR
生产者-->Queue
Queue-->消费者
先启动消费者,再启动生产者
<dependency>
<groupId>com.rabbitmqgroupId>
<artifactId>amqp-clientartifactId>
<version>5.2.0version>
dependency>
public class Producer {
private static final String QUEUE_NAME = "hello";
public static void main(String[] args) {
// 初始化消息队列
ConnectionFactory factory = new ConnectionFactory();
// 设置IP
factory.setHost("118.126.117.177");
// 设置端口
factory.setPort(5672);
try {
// 获取连接
Connection connection = factory.newConnection();
// 创建渠道
Channel channel = connection.createChannel();
// 声明一个队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 添加消息
for (int i = 0; i < 10; i++) {
channel.basicPublish("", QUEUE_NAME, null, (UUID.randomUUID().toString() + "丈夫是否").getBytes("UTF-8"));
System.out.println(" [x] Sent ");
}
// 释放资源
channel.close();
connection.close();
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
}
public class Recv {
private static final String QUEUE_NAME="hello";
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("118.126.117.177");
factory.setPort(5672);
try {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
System.out.println("stop");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
一个生产者对应于多个消费者,但一个消息只有一个消费者可以处理,多个消费者不可以处理同一个消息
graph LR
生产者-->消息队列
消息队列-->消费者A
消息队列-->消费者B
消息队列-->消费者C
简单队列是意义对应的,而实际开发中消息的生产者发送消息是比较简单的,消费者需要在业务逻辑中使用,消费者接收到消息后就需要处理消息,可能会花费时间,这时候就会造成队列中的消息积压
轮训分发:不管两个消费者是否空闲或忙碌,两个消费者都只消费所有消息的一半
package com.springinaction.controller.MessageQueueWork;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author lhc
* @Title: Recv1
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/9下午 5:50
*/
public class Recv1 {
private static final String QUEUE_NAME = "test_work";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String result = new String(body, "utf-8");
System.out.println("[*] result1 " + result);
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.springinaction.controller.MessageQueueWork;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author lhc
* @Title: Recv2
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/9下午 5:59
*/
public class Recv2 {
private static final String QUEUE_NAME = "test_work";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String result = new String(body, "utf-8");
System.out.println("[*] result2 " + result);
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
能者多劳,即任何一个消费者在处理完上一个消息之后,向消息队列返回完成任务的标志,再由消息队列分配下一个给当前消费者
sequenceDiagram
生产者->>消费者: 分配消息数据
消费者->>生产者: 处理完了,索要下一个消息数据
package com.springinaction.controller.MessageQueueWork;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author lhc
* @Title: Send
* @ProjectName springinaction
* @Description: 消息发送方
* @date 2018/12/9下午 5:38
*/
public class Send {
private static final String QUEUE_NAME = "test_work";
public static void main(String[] args) {
// 获取连接
Connection connection = GetConnection.getConn();
try {
// 获取channel
Channel channel = connection.createChannel();
channel.basicQos(1);
// 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 100; i++) {
String message = "hello" + i;
// 发送消息
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
}
channel.close();
connection.close();
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
}
}
package com.springinaction.controller.MessageQueueWork;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author lhc
* @Title: Recv1
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/9下午 5:50
*/
public class Recv1 {
private static final String QUEUE_NAME = "test_work";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String result = new String(body, "utf-8");
System.out.println("[*] result1 " + result);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
// 自动应答改为false
channel.basicConsume(QUEUE_NAME, false, consumer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.springinaction.controller.MessageQueueWork;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author lhc
* @Title: Recv2
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/9下午 5:59
*/
public class Recv2 {
private static final String QUEUE_NAME = "test_work";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String result = new String(body, "utf-8");
System.out.println("[*] result2 " + result);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
channel.basicConsume(QUEUE_NAME, false, consumer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 默认为true
boolean autoask = false;
// 自动应答改为false
channel.basicConsume(QUEUE_NAME, autoask, consumer);
boolean durable = false;
channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
一个生产者对多个消费者,且一个消息可被多个消费者处理
graph LR
生产者-->交换机
交换机-->消息队列1
交换机-->消息队列2
消息队列1-->消费者1
消息队列2-->消费者2
Total
字段显示有200
条消息,是因为消息会被送到两个不同的队列中/**
* @author lhc
* @Title: PsSend
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/11下午 9:09
*/
public class PsSend {
private static final String EXCHANGE_DECLARE = "text_chage_channel";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_DECLARE, "fanout");
for (int i = 0; i < 10000; i++) {
channel.basicPublish(EXCHANGE_DECLARE, "", null, String.valueOf(i).getBytes());
System.out.println("[*] Send " + i);
}
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
/**
* @author lhc
* @Title: PSRece1
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/11下午 9:24
*/
public class PSRece1 {
private static final String QUUE_NAME = "test_exchange_queue1";
private static final String EXCHANGE_DECLARE = "text_chage_channel";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUUE_NAME, false, false, false, null);
channel.queueBind(QUUE_NAME, EXCHANGE_DECLARE, "");
channel.basicQos(1);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String str = new String(body, "utf-8");
System.out.println("[*] Rece1: " + str);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
channel.basicConsume(QUUE_NAME,false,consumer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @author lhc
* @Title: PSRece2
* @ProjectName springinaction
* @Description: TODO
* @date 2018/12/11下午 9:31
*/
public class PSRece2 {
private static final String QUUE_NAME = "test_exchange_queue2";
private static final String EXCHANGE_DECLARE = "text_chage_channel";
public static void main(String[] args) {
Connection connection = GetConnection.getConn();
try {
Channel channel = connection.createChannel();
channel.queueDeclare(QUUE_NAME,false,false,false,null);
channel.queueBind(QUUE_NAME,EXCHANGE_DECLARE,"");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String str = new String(body,"utf-8");
System.out.println("[2] Rece2: "+str);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
channel.basicConsume(QUUE_NAME,false,consumer);
channel.basicQos(1);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Fanout(不处理路由键) 只要数据经过了该路由模式,则所有的消息会到达与该交换机绑定的队列中
Direct(路由模式) 首先消息到达交换机,交换机将
routingKey
值与消息队列进行对比,如果消息的key值与消息队列的key值相同,则将消息进入该队列
将
routekey
值相同的,放到消息队列中