MySQL
概述(含安装)
MQ (Message Quene):翻译为消息队列,通过典型的生产者和消费者模型,生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,轻松的实现系统间解耦。别名为消息中间件通过利用高效可靠的消息传递机制进行平 台无关的数据交流,并基于数据通信来进行分布式系统的集成。
MQ的分类
当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。
MQ特点
ActiveMQ
ActiveMQ是Apache出品, 最流行的,能力强劲的开源消息总线。它是一一个完全支持JMS规范的的消息中间件。丰富的API, 多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
Kafka
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0. 8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
RocketMQ
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
RabbitMQ
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。 AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RabbitMQ比Kafka可靠,Kafka更适合I0高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟), 可靠性 (少量丢数据)要求稍低的场景使用,比如EK日志收集。
安装
1. RabbitMQ下载地址:https://www.rabbitmq.com/download.html;
2. erlang下载地址:http://www.erlang.org/downloads;
3. 输入指令激活插件:rabbitmq-plugins.bat enable rabbitmq_management
4. 在文件里点击sbin:rabbitmq-server.bat 开启RabbitMQ;
5. 输入网址验证:http://localhost:15672;
6. RabbitMQ命名行输入注意:
1、要在sbin文件内打开cmd
2、(查找的输入记得加上.bat)rabbitmqctl.bat help
模型
第一种模型(直连)
在上图的模型中,有以下概念:
P:生产者:也就是要发送消息的程序
C:消费者:消息的接受者,会一直等待消息的到来
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
生产者类
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 14:48
*/
public class Provide {
// 生产消息
@Test
public void TestSendMessage() throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,
// ---参数5:额外附件参数,
channel.queueDeclare("hello",false,false,false,null);
// 发布消息 参数1:交换机名称 ;
// 参数2:队列名称 ;
// 参数3:传递消息额外设置(可设置队列中的数据持久化) ;
// 参数4:消息的具体内容
channel.basicPublish("","hello",null,"hello Rabbitmq".getBytes());
channel.close();
connection.close();
}
}
消费者类
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 16:10
*/
public class Customer {
// 这里使用main方法是为了能打印System.out.println("****************"+new String(body));
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,
// ---参数5:额外附件参数,
channel.queueDeclare("hello",false,false,false,null);
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( "hello",true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("****************"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
工具类(简化连接的创建)
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 17:03
*/
public class RabbitMQUtils {
// 定义提供连接的对象
public static Connection getConnection(){
try {
// 创建mq的连接工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接rabbitmq的主机
connectionFactory.setHost("127.0.0.1");
// 设置端口号
connectionFactory.setPort(5672);
// 连接虚拟主机名
connectionFactory.setVirtualHost("/ems");
// 设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123456");
// 获取连接对象
return connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return null;
}
// 关闭连接和通道
public static void closeConnection(Channel channel,Connection connection){
try {
if (channel!=null)
{
channel.close();
}
if (connection!=null){
connection.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
注意事项
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,(当消费者结束即断开连接时触发)
// ---参数5:额外附件参数,
channel.queueDeclare("hello",false,false,false,null);
*********生产者和消费者所绑定的消息队列里面的参数设置必须一一对应*********
第二种模型(work quene)能者多劳:
work quene,也被称为(Task queues)任务模型。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。长久以往,消息就会堆积越来越多,无法及时处理。此时就可以使用work模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。
在上图的模型中,有以下概念:
P:生产者:也就是要发送消息的程序
C1:消费者1:消息的接受者,会一直等待消息的到来,假设完成速度较慢
C2:消费者2:消息的接受者,会一直等待消息的到来,假设完成速度快
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
生产者
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 14:48
*/
public class Provide {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,
// ---参数5:额外附件参数,
channel.queueDeclare("work",true,false,false,null);
for (int i = 0; i <= 20; i++) {
// 发布消息 参数1:交换机名称 ;参数2:队列名称 ;参数3:传递消息额外设置 ;参数4:消息的具体内容
channel.basicPublish("","work", null,(i+"hello Rabbitmq").getBytes());
}
RabbitMQUtils.closeConnection(channel,connection);
}
}
消费者1
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 22:33
*/
public class Customer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 每次只能消费一个消息,其余消息在消息队列等待---
channel.basicQos(1);
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,
// ---参数5:额外附件参数,
channel.queueDeclare("work",true,false,false,null);
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( "work",false,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("*******111******"+new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
消费者2
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 22:33
*/
public class Customer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 通道绑定对应的消息队列
// ---参数1:队列名称,如果队列不存在自动创建,
// ---参数2:用来定义队列的特性是否要持久化
// ---参数3:是否独占队列,
// ---参数4:是否在消费完成时自动删除队列,
// ---参数5:额外附件参数,
channel.queueDeclare("work",true,false,false,null);
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( "work",false,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******222*******"+new String(body));
//手动确认参 数1:手动确认消息标识参 数2:false每次确认一个
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
工具类(简化连接的创建)
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 17:03
*/
public class RabbitMQUtils {
// 定义提供连接的对象
public static Connection getConnection(){
try {
// 创建mq的连接工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接rabbitmq的主机
connectionFactory.setHost("127.0.0.1");
// 设置端口号
connectionFactory.setPort(5672);
// 连接虚拟主机名
connectionFactory.setVirtualHost("/ems");
// 设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123456");
// 获取连接对象
return connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return null;
}
// 关闭连接和通道
public static void closeConnection(Channel channel,Connection connection){
try {
if (channel!=null)
{
channel.close();
}
if (connection!=null){
connection.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
第三种模型(fanout)广播:
在广播模式下,消息发送流程是这样的:
可以有多个消费者
每个消费者有自己的queue (队列)
每个队列都要绑定到Exchange (交换机)
生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
交换机把消息发送给绑定过的所有队列
队列的消费者都能拿到消息。实现一条消息被多个消费者消费
生产者
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 14:48
*/
public class Provide {
// 生产消息
@Test
public void TestSendMessage() throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--fanout广播类型
channel.exchangeDeclare("log","fanout");
// 发送消息
channel.basicPublish("log","",null,"fanout type message".getBytes());
// 释放资源
RabbitMQUtils.closeConnection(channel,connection);
}
}
消费者1
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 16:10
*/
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--fanout广播类型
channel.exchangeDeclare("log","fanout");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"log","");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******111*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
消费者2
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 0:00
*/
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--fanout广播类型
channel.exchangeDeclare("log","fanout");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"log","");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******222*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
消费者3
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 0:01
*/
public class Customer3 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--fanout广播类型
channel.exchangeDeclare("log","fanout");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"log","");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******333*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
工具类(简化连接的创建)
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 17:03
*/
public class RabbitMQUtils {
// 定义提供连接的对象
public static Connection getConnection(){
try {
// 创建mq的连接工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接rabbitmq的主机
connectionFactory.setHost("127.0.0.1");
// 设置端口号
connectionFactory.setPort(5672);
// 连接虚拟主机名
connectionFactory.setVirtualHost("/ems");
// 设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123456");
// 获取连接对象
return connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return null;
}
// 关闭连接和通道
public static void closeConnection(Channel channel,Connection connection){
try {
if (channel!=null)
{
channel.close();
}
if (connection!=null){
connection.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
第四种模型(Routing)路由:
Routing之订阅模型:
在Fanout模式中,一条消息会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在Direct模型下:
队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey (路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的RoutingKey。
Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的Routing key完全一致,才会接收到消息
P:生产者:向Exchange发送消息, 发送消息时,会指定一 个routing key;
X:Exchange (交换机):接收生产者的消息,然后把消息递交给与routing key完全匹配的队列;
C1:消费者:其所在队列指定了需要routing key为error的消息;
C2:消费者:其所在队列指定了需要routing key为info、error、warning的消息。
生产者
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 8:55
*/
public class Provide {
// 生产消息
@Test
public void TestSendMessage() throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--direct路由模式
channel.exchangeDeclare("login","direct");
// 设置路由
String routingKey="info";
// 发送消息
channel.basicPublish("login",routingKey,null,"这是基于direct模型发布的routing".getBytes());
// 释放资源
RabbitMQUtils.closeConnection(channel,connection);
}
}
消费者1
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 8:56
*/
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--direct路由模式
channel.exchangeDeclare("login","direct");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"login","error");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******111*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
消费者2
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 8:56
*/
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--direct路由模式
channel.exchangeDeclare("login","direct");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"login","info");
channel.queueBind(queue,"login","error");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******222*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
工具类(简化连接的创建)
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 17:03
*/
public class RabbitMQUtils {
// 定义提供连接的对象
public static Connection getConnection(){
try {
// 创建mq的连接工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接rabbitmq的主机
connectionFactory.setHost("127.0.0.1");
// 设置端口号
connectionFactory.setPort(5672);
// 连接虚拟主机名
connectionFactory.setVirtualHost("/ems");
// 设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123456");
// 获取连接对象
return connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return null;
}
// 关闭连接和通道
public static void closeConnection(Channel channel,Connection connection){
try {
if (channel!=null)
{
channel.close();
}
if (connection!=null){
connection.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
第五种模型(Topics)动态路由:
Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!这种模型Routingkey一般都是由一个或多个单词组成,多个单词之间以"."分割,例如: item.insert;
#统配符
* (star) can substitute for exactly one word. 匹配不多不少恰好一个词
# (hash) can substitute for zero or more words. 匹配一个或多个词
#如:
audit.# 匹配audit.irs.corporate或者audit.irs等
audit.* 只能匹配audit.irs
生产者
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 9:17
*/
public class Provide {
// 生产消息
@Test
public void TestSendMessage() throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--topic动态路由模式
channel.exchangeDeclare("topics","topic");
// 设置路由
String routingKey="user.save";
// 发送消息
channel.basicPublish("topics",routingKey,null,"这是基于topic模型发布的动态routing".getBytes());
// 释放资源
RabbitMQUtils.closeConnection(channel,connection);
}
}
消费者1
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 9:17
*/
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--topic动态路由模式
channel.exchangeDeclare("topics","topic");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"topics","user.*");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******111*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
消费者2
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 9:18
*/
public class Customer2 {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取连接中的通道
Channel channel = connection.createChannel();
// 绑定交换机 参数1:交换机名称 参数2:交换机类型--topic动态路由模式
channel.exchangeDeclare("topics","topic");
// 临时队列
String queue = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queue,"topics","user.#");
// 消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
channel.basicConsume( queue,true,new DefaultConsumer(channel){
// byte[] body--消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("******222*******"+new String(body));
}
});
// 如果通道不关闭会一直监听我们的队列
// channel.close();
// connection.close();
}
}
工具类(简化连接的创建)
/**
* @author zehao
* @version 1.0
* @date 2020/10/22 17:03
*/
public class RabbitMQUtils {
// 定义提供连接的对象
public static Connection getConnection(){
try {
// 创建mq的连接工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接rabbitmq的主机
connectionFactory.setHost("127.0.0.1");
// 设置端口号
connectionFactory.setPort(5672);
// 连接虚拟主机名
connectionFactory.setVirtualHost("/ems");
// 设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123456");
// 获取连接对象
return connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return null;
}
// 关闭连接和通道
public static void closeConnection(Channel channel,Connection connection){
try {
if (channel!=null)
{
channel.close();
}
if (connection!=null){
connection.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
整合SpringBoot项目
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置配置文件(RabbitTemplate用来简化操作)
spring:
application:
name: springboot_r abbi tmq
rabbitmq:
host: 10.15.0.9
port: 5672
username: ems
password: 123
virtual-host: /ems
直连模式
/**生产者(直连模式)
* @author zehao
* @version 1.0
* @date 2020/10/23 14:41
*/
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)
public class TestRabbitMQ {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void Test(){
rabbitTemplate.convertAndSend("hello","hello word");
}
}
/**消费者(直连模式)
* @author zehao
* @version 1.0
* @date 2020/10/23 14:48
*/
@Component
@RabbitListener(queuesToDeclare = @Queue("hello"))
public class HelloCustomer {
@RabbitHandler
public void receive(String Message){
System.out.println("Message"+Message);
}
}
(work quene)默认是公平调度,如果实现能者多劳需要额外的配置
/**生产者(work quene)
* @author zehao
* @version 1.0
* @date 2020/10/23 14:41
*/
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)
public class TestRabbitMQ {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void TestWork(){
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("Work","Work 模型");
}
}
}
/**消费者(work quene)
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 15:07
*/
@Component
public class WorkCustomer {
@RabbitListener(queuesToDeclare = @Queue("hello"))
public void receive(String Message){
System.out.println("work"+Message);
}
@RabbitListener(queuesToDeclare = @Queue("hello"))
public void receive2(String Message){
System.out.println("work2"+Message);
}
}
(fanout)广播
/**生产者(fanout)
* @author zehao
* @version 1.0
* @date 2020/10/23 14:41
*/
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)
public class TestRabbitMQ {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void fanout(){
rabbitTemplate.convertAndSend("log","","fanout 模型");
}
}
/**消费者(fanout)
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 15:17
*/
@Component
public class FanoutCustomer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue, //创建临时队列
exchange = @Exchange(value = "log",type = "fanout") //绑定交换机
)
})
public void receive(String Message){
System.out.println("fanout"+Message);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue, //创建临时队列
exchange = @Exchange(value = "log",type = "fanout") //绑定交换机
)
})
public void receive2(String Message){
System.out.println("fanout2"+Message);
}
}
(Routing)路由
/**生产者(fanout)
* @author zehao
* @version 1.0
* @date 2020/10/23 14:41
*/
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)
public class TestRabbitMQ {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void routing(){
rabbitTemplate.convertAndSend("login","info","routing 模型");
}
}
/**消费者(fanout)
/**
* @author zehao
* @version 1.0
* @date 2020/10/23 15:29
*/
@Component
public class RoutingCustomer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue, //创建临时队列
exchange = @Exchange(value = "login",type = "direct") , //绑定交换机
key = {"info","error"}
)
})
public void receive(String Message){
System.out.println("direct"+Message);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue, //创建临时队列
exchange = @Exchange(value = "login",type = "direct") , //绑定交换机
key = {"info"}
)
})
public void receive2(String Message){
System.out.println("direct2"+Message);
}
}
(Topics)动态路由