RabbitMQ
MQ基本概念
概念
-
MQ全称Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信
-
分布式系统通信方法两种:直接远程调用和借助第三方完成间接调用
-
由A系统传输消息到B系统通信,A系统为生产者,B系统为消费者,作为经过的第三方MQ则为中间件
优势与劣势
-
优势:
-
应用解耦:提升容错性和可维护性
-
异步提速:提升用户体验和系统吞吐量(单位时间内处理请求的数目)
-
削峰填谷:提高系统稳定性
-
-
劣势:
-
系统可用性降低:系统引入的外部依赖越多,系统稳定性越差
-
系统复杂度提高:暂时无法保证消息是否被重复消费,如何处理消息丢失情况,是否保证消息传递的顺序性
-
一致性问题:由MQ发消息数据给其他系统,如果其中存在一个系统处理失败,则暂时无法保证消息数据处理的一致性
-
常见的MQ产品
-
RabbitMQ
-
RocketMQ
-
ActiveMQ
-
Kafka
-
ZeroMQ
-
MetaMq
-
Redis充当消息队列
RabbitMQ简介
-
AMQP,全称Advanced Message Queuing Protocol(高级消息队列协议),是一个网络协议,是应用层协议的一个开发标准,为面向消息的中间件设计,类比HTTP
-
RabbitMQ是基于AMQP协议使用Erlang语言开发的一款消息队列产品
RabbitMQ基础架构
-
Broker:接收和分发消息的应用,RabbitMQ server就是message Broker
-
Virtual Host:出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念,当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等
-
Connection:生产者/消费者和broker之间的TCP连接
-
Channel:如果每一次访问RabbitMQ都建立一个connection,在消息量大时开销大,效率低,channel是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel之间是完全隔离的,Channel作为轻量级的Connection极大减少了系统建立TCP connection的开销
-
Exchange:message到达broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去,常用的类型有:direct(point-to-point),topic(publish-subscribe),fanout(multicast)
-
Queue:消息最终被送到这里等待消费者取走
-
Binding:exchange和queue之间的虚拟连接,binding中可以包含routing key,Binding信息被保存到exchange中的查询表中,用于message的分发依据
RabbitMQ的六种工作模式
-
简单模式
-
work queues
-
Publish/Subscribe发布与订阅模式
-
Routing路由模式
-
Topics主题模式
-
RPC远程调用模式(远程调用,不太算MQ)
JMS
-
JMS即Java消息服务(JavaMessage Service)应用程序接口,是一个Java平台中关于面向消息中间件的API
-
JMS是JavaEE规范中的一种,类比JDBC
-
RabbitMQ没有实现JMS规范,开源社区提供,ActiveMQ实现了JMS规范
RabbitMQ快速入门
简单模式完成消息队列
-
创建工程(生产者,消费者)
-
Producer
-
Consumer
-
-
添加依赖
-
<dependencies> <dependency> <!--RabbitMQ java客户端--> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.6.0</version> </dependency> </dependencies> <!--编译插件1.8版本--> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
-
-
编写生产者发送消息
-
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.创建队列Queue(简单模式不需要交换机Exchange) /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) 参数: 1. queue:队列名称 2. durable:是否持久化,当mq重启之后,还在 3. exclusive: (1)是否独占,只能有一个消费者监听这队列 (2)当Connection关闭时,是否删除队列 4. autoDelete:是否自动删除,当没有消费者时,自动删除掉 5. arguments:参数信息 */ //如果不存在名字叫做hello_world的队列,则会创建该队列 channel.queueDeclare("hello_world",true,false,false,null); // 6.发送消息 /* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) 参数: 1. exchange:交换机名称(简单模式下交换机会使用默认的""空字符串) 2. routingKey:路由名称 3. props:配置信息 4. body:发送消息数据 */ String body = "hello rabbitmq"; channel.basicPublish("","hello_world",null,body.getBytes()); // 7.释放资源 channel.close(); connection.close();
-
-
编写消费者接收消息
-
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.创建队列Queue(简单模式不需要交换机Exchange) /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) 参数: 1. queue:队列名称 2. durable:是否持久化,当mq重启之后,还在 3. exclusive: (1)是否独占,只能有一个消费者监听这队列 (2)当Connection关闭时,是否删除队列 4. autoDelete:是否自动删除,当没有消费者时,自动删除掉 5. arguments:参数信息 */ //如果不存在名字叫做hello_world的队列,则会创建该队列 channel.queueDeclare("hello_world",true,false,false,null); // 6.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("hello_world",true,consumer);
-
RabbitMQ工作模式
简单模式/经典模式
-
一个生产者对应一个消费者
Work Queues 工作队列模式
-
一个生产者对应多个消费者,消费者之间对于同一个消息的关系是竞争关系
-
Work Queues对于任务过重或任务较多情况使用工作队列可以提高任务处理速度,例如:短信服务部署多个,只需要有一个节点成功发送即可
Pub/Sub 订阅模式
-
Exchange:交换机(X),一方面,接收生产者发送的消息,另一方面,知道如何处理消息,交换机只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与交换机绑定,或者没有符合路由规则的队列,消息则会丢失
-
Exchange常见三种类型:
-
Fanout:广播,将消息交给所有绑定到交换机的队列
-
Direct:定向,将消息交给符合制定routing key的队列
-
Topic:通配符,将消息交给符合routing pattern(路由模式)的队列
-
订阅模式生产者代码
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.创建交换机Exchange /* exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) 参数: 1. exchange:交换机名称 2. type:交换机类型(枚举) DIRECT("direct"):定向 FANOUT("fanout"):扇形(广播) TOPIC("topic"):通配符 HEADERS("headers"):参数匹配 3. durable:是否持久化 4. autoDelete:是否自动删除 5. internal:内部使用 6. arguments:参数信息 */ channel.exchangeDeclare("test_fanout",BuiltinExchangeType.FANOUT,true,false,false,null); // 6.创建队列Queue /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) 参数: 1. queue:队列名称 2. durable:是否持久化,当mq重启之后,还在 3. exclusive: (1)是否独占,只能有一个消费者监听这队列 (2)当Connection关闭时,是否删除队列 4. autoDelete:是否自动删除,当没有消费者时,自动删除掉 5. arguments:参数信息 */ channel.queueDeclare("test_fanout_queue1",true,false,false,null); channel.queueDeclare("test_fanout_queue2",true,false,false,null); // 7.绑定交换机和队列 /* queueBind(String queue, String exchange, String routingKey) 参数: 1. queue:队列名称 2. exchange:交换机名称 3. routingKey:路由key,绑定规则(使用fanout类型默认路由key为""空字符串) */ channel.queueBind("test_fanout_queue1","test_fanout",""); channel.queueBind("test_fanout_queue2","test_fanout",""); // 8.发送消息 /* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) 参数: 1. exchange:交换机名称 2. routingKey:路由名称 3. props:配置信息 4. body:发送消息数据 */ String body = "hello rabbitmq"; channel.basicPublish("test_fanout","",null,body.getBytes()); // 9.释放资源 channel.close(); connection.close();
订阅模式消费者代码
test_fanout_queue1消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_fanout_queue1",true,consumer);
test_fanout_queue2消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_fanout_queue2",true,consumer);
Routing 路由模式
-
队列与交换机的绑定要制定一个RoutingKey(路由Key)
-
消息的发送方在向交换机发送消息时,也必须指定消息的RoutingKey
-
交换机不再把消息交给每一个绑定的队列,而是根据消息的RoutingKey进行判断,只有队列的RoutingKey与消息的RoutingKey完全一致,才会接收到消息
路由模式生产者代码
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.创建交换机Exchange /* exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) 参数: 1. exchange:交换机名称 2. type:交换机类型(枚举) DIRECT("direct"):定向 FANOUT("fanout"):扇形(广播) TOPIC("topic"):通配符 HEADERS("headers"):参数匹配 3. durable:是否持久化 4. autoDelete:是否自动删除 5. internal:内部使用 6. arguments:参数信息 */ channel.exchangeDeclare("test_direct",BuiltinExchangeType.DIRECT,true,false,false,null); // 6.创建队列Queue /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) 参数: 1. queue:队列名称 2. durable:是否持久化,当mq重启之后,还在 3. exclusive: (1)是否独占,只能有一个消费者监听这队列 (2)当Connection关闭时,是否删除队列 4. autoDelete:是否自动删除,当没有消费者时,自动删除掉 5. arguments:参数信息 */ channel.queueDeclare("test_direct_queue1",true,false,false,null); channel.queueDeclare("test_direct_queue2",true,false,false,null); // 7.绑定交换机和队列 /* queueBind(String queue, String exchange, String routingKey) 参数: 1. queue:队列名称 2. exchange:交换机名称 3. routingKey:路由key,绑定规则(使用fanout类型默认路由key为""空字符串) */ //test_direct_queue1的绑定 error channel.queueBind("test_direct_queue1","test_direct","error"); //test_direct_queue2的绑定 error info warning channel.queueBind("test_direct_queue2","test_direct","info"); channel.queueBind("test_direct_queue2","test_direct","error"); channel.queueBind("test_direct_queue2","test_direct","warning"); // 8.发送消息 /* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) 参数: 1. exchange:交换机名称 2. routingKey:路由名称 3. props:配置信息 4. body:发送消息数据 */ String body = "hello rabbitmq"; channel.basicPublish("test_direct","",null,body.getBytes()); // 9.释放资源 channel.close(); connection.close();
路由模式消费者代码
test_direct_queue1消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址");//IP 默认值为 localhost factory.setPort(5672);//端口 默认值为 5672 factory.setVirtualHost("/xiangxi");//虚拟机 默认值为 / factory.setUsername("xiangxi");//用户名 默认值为 guest factory.setPassword("123456");//密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_fanout_queue1",true,consumer);
test_direct_queue2消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址"); //IP 默认值为 localhost factory.setPort(5672); //端口 默认值为 5672 factory.setVirtualHost("/xiangxi"); //虚拟机 默认值为 / factory.setUsername("xiangxi"); //用户名 默认值为 guest factory.setPassword("123456"); //密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_direct_queue2",true,consumer);
Topics 通配符模式
通配符模式生产者代码
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址"); //IP 默认值为 localhost factory.setPort(5672); //端口 默认值为 5672 factory.setVirtualHost("/xiangxi"); //虚拟机 默认值为 / factory.setUsername("xiangxi"); //用户名 默认值为 guest factory.setPassword("123456"); //密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.创建交换机Exchange /* exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) 参数: 1. exchange:交换机名称 2. type:交换机类型(枚举) DIRECT("direct"):定向 FANOUT("fanout"):扇形(广播) TOPIC("topic"):通配符 HEADERS("headers"):参数匹配 3. durable:是否持久化 4. autoDelete:是否自动删除 5. internal:内部使用 6. arguments:参数信息 */ channel.exchangeDeclare("test_topic",BuiltinExchangeType.TOPIC,true,false,false,null); // 6.创建队列Queue /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) 参数: 1. queue:队列名称 2. durable:是否持久化,当mq重启之后,还在 3. exclusive: (1)是否独占,只能有一个消费者监听这队列 (2)当Connection关闭时,是否删除队列 4. autoDelete:是否自动删除,当没有消费者时,自动删除掉 5. arguments:参数信息 */ channel.queueDeclare("test_topic_queue1",true,false,false,null); channel.queueDeclare("test_topic_queue2",true,false,false,null); // 7.绑定交换机和队列 /* queueBind(String queue, String exchange, String routingKey) 参数: 1. queue:队列名称 2. exchange:交换机名称 3. routingKey:路由key,绑定规则 routingKey 系统名称.日志级别 * 对应一个单词 # 对应零-多个单词 */ //test_topic_queue1的绑定 #.error 任何一个的error级别信息 channel.queueBind("test_topic_queue1","test_topic","#.error"); //test_topic_queue1的绑定 order.* order下的所有级别信息 channel.queueBind("test_topic_queue1","test_topic","order.*"); //test_topic_queue2的绑定 *.* 所有级别的信息 channel.queueBind("test_topic_queue2","test_topic","*.*"); // 8.发送消息 /* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) 参数: 1. exchange:交换机名称 2. routingKey:路由名称 3. props:配置信息 4. body:发送消息数据 */ String body = "hello rabbitmq"; channel.basicPublish("test_topic","order.info",null,body.getBytes()); // 9.释放资源 channel.close(); connection.close();
通配符模式消费者代码
test_topic_queue1消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址"); //IP 默认值为 localhost factory.setPort(5672); //端口 默认值为 5672 factory.setVirtualHost("/xiangxi"); //虚拟机 默认值为 / factory.setUsername("xiangxi"); //用户名 默认值为 guest factory.setPassword("123456"); //密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_topic_queue1",true,consumer);
test_topic_queue2消费者
// 1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 2.设置参数 factory.setHost("IP地址"); //IP 默认值为 localhost factory.setPort(5672); //端口 默认值为 5672 factory.setVirtualHost("/xiangxi"); //虚拟机 默认值为 / factory.setUsername("xiangxi"); //用户名 默认值为 guest factory.setPassword("123456"); //密码 默认值为 guest // 3.创建连接Connection Connection connection = factory.newConnection(); // 4.创建Channel Channel channel = connection.createChannel(); // 5.接收消息 /* basicConsume(String queue, boolean autoAck, Consumer callback) 参数: 1. queue,:队列名称 2. autoAck:是否自动确认(接收到消息自动给mq确认消息) 3. callback:回调对象 */ Consumer consumer = new DefaultConsumer(channel){ /* 回调方法,当收到消息后,会自动执行该方法 参数: 1. consumerTag:标识 2. envelope:获取一些信息(交换机,路由key...) 3. properties:配置信息 4. body:数据 */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{ System.out.println("consumerTag:" + consumerTag); System.out.println("Exchange:" + envelope.getExchange()); System.out.println("RoutingKey:" + envelope.getRoutingKey()); System.out.println("properties" + properties); System.out.println("body" + new String(body)); } } channel.basicConsume("test_topic_queue2",true,consumer);
SpringBoot整合RabbitMQ
生产者
-
创建生产者SpringBoot工程
-
引入依赖坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
-
编写yml配置,基本信息配置
# 配置RabbitMQ的基本信息 spring: rabbitmq: host: 172.16.98.133 #ip port: 5672 #端口 username: guest password: guest virtual-host: /
-
定义交换机,队列以及绑定关系的配置类
@Configuration public class RabbitMQConfig { public static final String EXCHANGE_NAME = "boot_topic_exchange"; public static final String QUEUE_NAME = "boot_queue"; // 1.Exchange 交换机 @Bean("getExchange") public Exchange getExchange() { return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build(); } // 2.Queue 队列 @Bean("getQueue") public Queue getQueue() { return QueueBuilder.durable(QUEUE_NAME).build(); } // 3.Binding 交换机和队列的绑定关系 @Bean public Binding bindQueueExchange(@Qualifier("getQueue") Queue queue, @Qualifier("getExchange") Exchange exchange) { return BindingBuilder.bind(queue).to(exchange).with("boot.#").noargs(); } }
-
注入RabbitTemplate,调用方法,完成消息发送
//ProducerTest生产者测试类 //@RunWith是一个运行器,指定测试环境来运行 @SpringBootTest @RunWith(SpringRunner.class) public class ProducerTest { // 1.注入RabbitTemplate @Autowired private RabbitTemplate rabbitTemplate; @Test public void testSend(){ rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME,"boot.heihei","hello springboot"); } }
消费者
-
创建消费者SpringBoot工程
-
引入依赖坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
-
编写yml配置,基本信息配置
# 配置RabbitMQ的基本信息 spring: rabbitmq: host: 172.16.98.133 #ip port: 5672 #端口 username: guest password: guest virtual-host: /
-
定义监听类,使用@RabbitListener注解完成队列监听
@Component public class RabbitMQListener { @RabbitListener(queues = "boot_queue") public void ListenerQueue(Message message) { //System.out.println(message); System.out.println(message.getBody()); } }