一、MQ介绍
MQ全称 Message Queue([kjuː])(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。
二、MQ的优势和劣势
1.优势
- 应用解耦:提高系统容错性和可维护性。
- 异步提速:提升用户体验和系统吞吐量。
- 削峰填谷:提高系统稳定性。
2.劣势
- 系统可用性降低
系统引入的外部依赖越多,系统稳定性越差。一旦 MQ 宕机,就会对业务造成影响。如何保证MQ的高可用?
- 系统复杂度提高
MQ 的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过 MQ 进行异步调用。如何保证消息没有被重复消费?怎么处理消息丢失情况?那么保证消息传递的顺序性?
- 一致性问题
A 系统处理完业务,通过 MQ 给B、C、D三个系统发消息数据,如果 B 系统、C 系统处理成功,D 系统处理失败。如何保证消息数据处理的一致性?
三、常见MQ产品
四、RabbitMQ基本介绍
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、 安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
五、RabbitMQ 基础架构
Broker 中间者 服务
procedure 和consumer都是客户端
客户端通过链接和服务端进行通信 所以需要建立起来连接 然后进行通信a
使用channel(管道)节省资源
一个rabbitmq里面有很多的虚拟机 相当于mysql里面有很多数据库,数据库里面有很多表,都是独立的。
每个虚拟机里面有很多的exchange和queue 独立分区的作用
六、RabbitMQ的安装和配置
1.安装包准备
2.安装依赖环境
yum -y install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz
3.安装Erlang
rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm
4.安装RabbitMQ
1.安装依赖的包
rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpm
2.安装rabbitmq
rpm -ivh rabbitmq-server-3.7.18-1.el7.noarch.rpm
5. 开启管理界面及配置
rabbitmq-plugins enable rabbitmq_management
6.修改默认配置信息
vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.18/ebin/rabbit.app
7.启动RabbitMQ
- systemctl start rabbitmq-server # 启动服务
- systemctl stop rabbitmq-server # 停止服务
- systemctl restart rabbitmq-server # 重启服务
- systemctl status rabbitmq-server #查看状态
8.打开客户端
ipxxx:15672
使用guest/guest登录之后出现如下即为安装成功
七、 添加用户
1.给用户添加权限
即可
八、RabbitMQ工程搭建
1.简单模式
1.添加pom
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
2. 生产者
public class productTest {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
/**
* String queue, 队列的名称
* boolean durable, 持久化
* boolean exclusive, 是否独占
* boolean autoDelete, 受否自动删除
* Map<String, Object> arguments 参数
*/
// 创建队列
channel.queueDeclare("test1",false,false,false,null);
// 发布消息
channel.basicPublish("","test1",null,"hello".getBytes());
}
}
3.消费者
public class Consumer {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body);
System.out.println("消息队列:"+s);
}
};
channel.basicConsume("test1",true,defaultConsumer);
}
}
2.竞争消费者模式
1.生产者
public class productTest1 {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
/**
* String queue, 队列的名称
* boolean durable, 持久化
* boolean exclusive, 是否独占
* boolean autoDelete, 受否自动删除
* Map<String, Object> arguments 参数
*/
// 创建队列
channel.queueDeclare("test1",false,false,false,null);
for (int i = 0; i < 10; i++) {
// 发布消息
channel.basicPublish("","test1",null,("hello"+i).getBytes());
}
}
}
2.消费者
1.消费者1
public class Consumer1 {
public static void main(String[] args) throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body);
System.out.println("消息队列:" + s);
}
};
channel.basicConsume("test1", true, defaultConsumer);
}
}
2.消费者
public class Consumer2 {
public static void main(String[] args) throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body);
System.out.println("消息队列:"+s);
}
};
channel.basicConsume("test1",true,defaultConsumer);
}
}
项目结构
3.订阅模式
1.生产者
public class productTest2 {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 创建交换机
channel.exchangeDeclare("myjhj", BuiltinExchangeType.FANOUT,false);
// 创建队列
channel.queueDeclare("testj3",false,false,false,null);
channel.queueDeclare("testj4",false,false,false,null);
// 交换机绑定
channel.queueBind("testj3","myjhj","");
channel.queueBind("testj4","myjhj","");
// 消息
channel.basicPublish("myjhj","",null,"testex".getBytes());
}
}
消费者同上
4.路由模式
1.消费者
public class productTest3 {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 创建交换机
channel.exchangeDeclare("myjhj1", BuiltinExchangeType.DIRECT,false);
// 创建队列
channel.queueDeclare("testj5",false,false,false,null);
channel.queueDeclare("testj6",false,false,false,null);
// 交换机绑定队列
channel.queueBind("testj5","myjhj1","error");
channel.queueBind("testj6","myjhj1","test6666");
channel.queueBind("testj6","myjhj1","test7777");
// 消息
channel.basicPublish("myjhj1","test7777",null,"测试".getBytes());
}
}
消费者同上
5.通配符模式
Topic
类型与Direct
相比,都是可以根据RoutingKey
把消息路由到不同的队列。只不过Topic
类型Exchange
可以让队列在绑定Routing key
的时候使用通配符
!
通配符规则:
#
:匹配一个或多个词
*
:匹配不多不少恰好1个词 test.* test.insert
Routingkey
一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如:item.insert
举例:
item.#
:能够匹配item.insert.abc
或者item.insert
item.*
:只能匹配item.insert
1.生产者
public class productTest3 {
@Test
public void product() throws Exception {
ConnectionFactory continuation = new ConnectionFactory();
continuation.setHost("192.168.64.33");
continuation.setPort(5672);
continuation.setPassword("ww");
continuation.setUsername("ww");
// 设置对应的虚拟主机
continuation.setVirtualHost("/ww");
// 物理连接
Connection connection = continuation.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 创建交换机
channel.exchangeDeclare("myjhj3", BuiltinExchangeType.TOPIC,false);
// 创建队列
channel.queueDeclare("testj9",false,false,false,null);
channel.queueDeclare("testj10",false,false,false,null);
// 交换机绑定队列
channel.queueBind("testj9","myjhj3","test.#");
channel.queueBind("testj10","myjhj3","test.*");
channel.queueBind("testj10","myjhj3","*.aaa");
// 消息
//受作用的为9和10
channel.basicPublish("myjhj3","test.aaa",null,"测试111".getBytes());
}
}
消费者同上