1 简单模式Hello World
功能:一个生产者P发送消息到队列Q,一个消费者C接收
生产者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,设置用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel向队列中发送消息,关闭通道和连接。
public class RabbitMQPublishTest {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
// * @param queue 队列名称
// * @param durable 是否持久队列(服务重启,队列是否会存在)
// * @param exclusive 该连接是否独占队列
// * @param autoDelete 服务器在不使用的时候是否删除该队列
// * @param arguments 多余参数
channel.queueDeclare("hello",false,false,false,null);
//发布消息
// * @param exchange 发布的交换机名称
// * @param routingKey 路由关键字 要注意 这个表示具体发送到哪个队列(和通道中的queue名称一致)
// * @param props 额外设置参数
// * @param body 消息体
//MessageProperties.PERSISTENT_TEXT_PLAIN 消息持久化
channel.basicPublish("","hello", MessageProperties.PERSISTENT_TEXT_PLAIN,"hello,rabbitMQ".getBytes());
System.out.println("消息发送完毕");
channel.close();
connection.close();
}
}
消费者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,设置用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue, 创建消费者并监听队列,从队列中读取消息。
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//消费消息
channel.basicConsume("hello",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
//消费端不要关闭连接和通道
}
2 工作队列模式Work Queue
功能:一个生产者,多个消费者,每个消费者获取到的消息唯一,多个消费者只有一个队列。
任务队列:避免立即做一个资源密集型任务,必须等待它完成,而是把这个任务安排到稍后再做。我们将任务封装为消息并将其发送给队列。后台运行的工作进程将弹出任务并最终执行作业。当有多个worker同时运行时,任务将在它们之间共享。
生产者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel向队列中发送消息,2条消息之间间隔一定时间,关闭通道和连接。
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//发布消息
for (int i = 1; i <=20 ; i++) {
String body = "send["+i+"] hello,rabbitMQ";
channel.basicPublish("","hello", MessageProperties.PERSISTENT_TEXT_PLAIN,body.getBytes());
}
System.out.println("消息发送完毕");
channel.close();
connection.close();
}
消费者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,创建两个消费队列。
2.1 平均分配消息
消费者1:
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//消费消息
channel.basicConsume("hello",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new String(body));
}
});
//消费端不要关闭连接和通道
}
}
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//消费消息
channel.basicConsume("hello",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
//消费端不要关闭连接和通道
}
}
从上面可以看到 默认情况下,消息会被平分到各个消费者来消费。
2.2 手动确认达到能者多劳
可以通过手动确认和限制消息数量来控制。
生产者:
public class RabbitMQPublishTest {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//发布消息
for (int i = 1; i <=20 ; i++) {
String body = "send["+i+"] hello,rabbitMQ";
channel.basicPublish("","hello", null,body.getBytes());
}
System.out.println("消息发送完毕");
channel.close();
connection.close();
}
}
消费者:
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//消费消息
channel.basicConsume("hello",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//消费端不要关闭连接和通道
}
}
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
channel.queueDeclare("hello",false,false,false,null);
//服务器只给该消费者一次只发一条
channel.basicQos(1);
//消费消息
channel.basicConsume("hello",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//参数2 是否开启多个消息同时确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//消费端不要关闭连接和通道
}
}
3 发布/订阅模式Publish/Subscribe
功能:一个生产者发送的消息会被多个消费者获取。一个生产者、一个交换机、多个队列、多个消费者
生产者:可以将消息发送到队列或者是交换机。
消费者:只能从队列中获取消息。
如果消息发送到没有队列绑定的交换机上,那么消息将丢失。
交换机不能存储消息,消息存储在队列中
生产者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel创建交换机并指定交换机类型为fanout,使用通道向交换机发送消息,关闭通道和连接。
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//声明交换机,交换机类型:
channel.exchangeDeclare("logs", BuiltinExchangeType.FANOUT);
channel.basicPublish("logs", "", null, "广播消息".getBytes());
channel.close();
connection.close();
System.out.println("消息发送完毕");
}
消费者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,绑定队列到交换机,创建多个消费者进行监听。
消费者1:
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机
channel.queueBind(queue, "logs", "");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者1: "+new String(body));
}
});
}
消费2:
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机
channel.queueBind(queue, "logs", "");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者2: "+new String(body));
}
});
}
4 路由模式Routing
说明:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key。
生产者实现思路:
创建连接工厂ConnectionFactory,设置服务地址,端口号,用户名、密码、virtual host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel创建交换机并指定交换机类型为direct,使用通道向交换机发送消息,关闭通道和连接。
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//声明交换机,交换机类型:
channel.exchangeDeclare("logs_direct", BuiltinExchangeType.DIRECT);
channel.basicPublish("logs_direct", "123456", null, "广播路由消息".getBytes());
channel.close();
connection.close();
System.out.println("消息发送完毕");
}
消费者实现:
customer1:
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机
channel.queueBind(queue, "logs_direct", "123456");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者1: "+new String(body));
}
});
}
}
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机
channel.queueBind(queue, "logs_direct", "");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者2: "+new String(body));
}
});
}
}
5 通配符模式Topics
注意:
*匹配一个单词,#匹配0个或多个单词,单词之间用.做分割
生产者:
public class RabbitMQPublishTest {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//声明交换机,交换机类型:
channel.exchangeDeclare("logs_Topics", BuiltinExchangeType.TOPIC);
channel.basicPublish("logs_Topics", "china.weather", null, "今天中国天气真好".getBytes());
channel.basicPublish("logs_Topics", "china.news", null, "今天中国中芯国际上市了".getBytes());
channel.basicPublish("logs_Topics", "usa.weather", null, "今天美国天气非常差".getBytes());
channel.basicPublish("logs_Topics", "usa.news", null, "今天美国疫情突破两百万".getBytes());
channel.close();
connection.close();
System.out.println("消息发送完毕");
}
}
消费者1:
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机 *匹配一个单词,#匹配0个或多个单词
channel.queueBind(queue, "logs_Topics", "usa.*");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者1: "+new String(body));
}
});
}
}
消费者2:
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.1.245");
connectionFactory.setPort(5672);
//设置访问的虚拟主机
connectionFactory.setVirtualHost("my_vhost");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
Connection connection = connectionFactory.newConnection();
//获取连接通道
Channel channel = connection.createChannel();
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//队列绑定交换机 *匹配一个单词,#匹配0个或多个单词
channel.queueBind(queue, "logs_Topics", "china.*");
channel.basicConsume(queue, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者2: "+new String(body));
}
});
}
}