MQ消息队列:负责数据的传接受,存储和传递。性能要过于普通服务和技术
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lW0WwS9x-1659964424459)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716111756495.png)]
为什么消息中间件不直接使用http协议呢
AMQP:(全称: Advanced Message Queuing Protocol)是高级消息队列协议。由摩根大通集团联合其他公司共同设计。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。
特性
MQTT协议: (Message Queueing Telemetry Transport)消息队列是IBM开放的一个即时通讯协议,物联网系统架构中的重要组成部分。
特点:
应用场景:
适用于计算能力有限
低带宽
网络不稳定的场景。
Kafka协议是基于TCP/IP的二进制协议。消息内部是通过长度来分割,由一些基本数据类型组成。
特点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQqSH9EB-1659964424461)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716112854360.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a32rGb95-1659964424462)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716113022608.png)]
1.下载erlang的gz包,tar -zxvf 解压erlang包
2.进入到erlang目录下,使用make install安装
报错解决方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKt3nJLL-1659964424463)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716132130091.png)]
解决方法:
yum install gcc-c++
错误:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzkClLDL-1659964424463)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716132154446.png)]
解决方法:
yum install perl
错误:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThDiO5De-1659964424464)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716132216606.png)]
解决方法:
yum -y install ncurses-devel
然后执行一次make编译
最后配置环境变量
erl -version查看是否安装上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2o7go2CQ-1659964424465)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716132343286.png)]
rpm -Uvh erlang-23.2.7-2.el8.x86_64.rpm
yum install -y erlang
erl -v 查看版本
yum install -y socat
rpm -Uvh rabbitmq-server-3.8.14-1.el8.noarch.rpm
yum install -y rabbitmq-server
启动 rabbitmq :systemctl start rabbitmq-server
查看 rabbitmq状态 : systemctl status rabbitmq-server
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VDEznyNb-1659964424466)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716175716625.png)]
在/etc文件下使用rabbitmq-plugins enable rabbitmq_management开启web端访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-syZzW4fu-1659964424467)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716181120330.png)]
rabbitmqctl add_user 用户名 密码
set_user_tags 用户名 权限 设置用户权限
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ChK8708c-1659964424467)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716181303859.png)]
change_password 用户 新密码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1TuHUKR-1659964424468)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220716184317302.png)]
rabbitmqctl set_permissions -p / admin ‘.’ '.’ ‘.*’
给admin用户赋予‘/’目录的访问权限不然后续操作报错比如以下问题
com.rabbitmq.client.ShutdownSignalException: connection error;
com.rabbitmq
amqp-client
5.10.0
public class Producer extends Thread{
@Override
public void run() {
// 创建连接工程
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("tencent");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");//消息放在根结点上
// 创建连接Connection
Connection connection = null;
// 通过连接创建通道Channel
Channel channel = null;
try {
connection = connectionFactory.newConnection("生产者");
channel = connection.createChannel();
// 通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
final String EXCHANGE_NAME = "testfanout";
//创建交换机
/**
* 1.exchange:交换机名称
* 2.type:交换机的类型
* DIRECT("direct"):定向
* FANOUT("fanout"):广播
* TOPIC("topic"):通配符方式
* HEADERS("headers"):参数匹配
* 3.durable:是否持久化
* 4.autoDelete:自动删除
* 5.internal:内部使用:false
* 6.arguments:参数
*/
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT,false,false,false,null);
String queueName = "queue6";
String queueName2 = "queue7";
/**
* @param1 队列的名称
* @param2 是否持久化 false,消息是否存盘
* @param3 排他性,是否独占独立
* @param4 是否自动删除,随着最后一个消费者消息完毕信息以后是否把队列自动删除
* @param5 携带附属参数
*/
channel.queueDeclare(queueName,true,false,false,null);
channel.queueDeclare(queueName2,true,false,false,null);
/**
*
* 绑定交换机和队列的关系
* String queue, String exchange, String routingKey
* 参数
* 1.queue:队列名称
* 2.exchange:交换机名称
* 3.routingKey:路由键:绑定规则
* 如果交换机的类型是FANOUT,那么路由键为空
*/
channel.queueBind(queueName,EXCHANGE_NAME,"");
channel.queueBind(queueName2,EXCHANGE_NAME,"");
// 准备消息内容
String message = "hello rabbitmq";
// 发送消息给队列queue
/**
* @param1 交换机
* @param2 队列,路由
* @param3 消息的控制状态
* @param4 消息主题
* 不可能存在没有交换机的队列,虽然没有指定交换机但是一定会存在一个默认的交换机
*/
channel.basicPublish(EXCHANGE_NAME,"", null,message.getBytes());
System.out.println("消息发送成功");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
// 关闭通道
if(channel!=null && channel.isOpen()){
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
// 关闭连接
if(connection!=null && connection.isOpen()){
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Producer()).start();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8jUKYuC-1659964424468)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220719203629453.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bh9tfEBL-1659964424469)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220719210243636.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0bRxQGo-1659964424469)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220720172116371.png)]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:queue id="spring_queue" name="spring_queue" auto-declare="true"/>
<rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true" />
<rabbit:queue id="spring_fanout_queue_2" name="spring_fanout_queue_2" auto-declare="true"/>
<rabbit:fanout-exchange id="spring_fanout_exchange" name="spring_fanout_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="spring_fanout_queue_1" />
<rabbit:binding queue="spring_fanout_queue_2"/>
rabbit:bindings>
rabbit:fanout-exchange>
<rabbit:queue id="spring_direct_queue" name="spring_direct_queue" auto-declare="true"/>
<rabbit:direct-exchange name="spring_direct_exchange" >
<rabbit:bindings>
<rabbit:binding queue="spring_direct_queue" key="info">rabbit:binding>
rabbit:bindings>
rabbit:direct-exchange>
<rabbit:queue id="spring_topic_queue_star" name="spring_topic_queue_star" auto-declare="true"/>
<rabbit:queue id="spring_topic_queue_well" name="spring_topic_queue_well" auto-declare="true"/>
<rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding pattern="com.*" queue="spring_topic_queue_star"/>
<rabbit:binding pattern="wjh.#" queue="spring_topic_queue_well"/>
rabbit:bindings>
rabbit:topic-exchange>
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}"
password="${rabbitmq.password}" virtual-host="${rabbitmq.virtual-host}"/>
<bean id = "springQueueListener" class="com.wjh.rabbitmq.Listener"/>
<rabbit:listener-container connection-factory="connectionFactory" >
<rabbit:listener queue-names="spring_queue" ref="springQueueListener"/>
rabbit:listener-container>
beans>
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void shouldAnswerWithTrue() throws JsonProcessingException {
ObjectMapper objectMapper =new ObjectMapper();
Student s = new Student();
s.setAge(1);
s.setName("wjh");
String msg = objectMapper.writeValueAsString(s);
rabbitTemplate.convertAndSend("spring_queue",msg);//往队列里面发送消息
}
public class Listener implements MessageListener {
@Override
public void onMessage(Message message) {
//打印消息
ObjectMapper objectMapper = new ObjectMapper();
try {
Student student = objectMapper.readValue(message.getBody(),Student.class);
System.out.println(student);
} catch (IOException e) {
e.printStackTrace();
}
}
}
spring:
rabbitmq:
host: tencent
port: 5672
username: admin
password: admin
virtual-host: /
//开启手动应答,回调函数
publisher-confirm-type: correlated
publisher-returns: true
Exchange:
topicName: boot_Exchange
Queue:
name: boot_Queue
spring:
rabbitmq:
host: tencent
port: 5672
username: admin
password: admin
virtual-host: /
Exchange:
topicName: boot_Exchange
Queue:
name: boot_Queue
spring.rabbitmq.listener.simple.auto-startup=true: 是否启动时自动启动容器
spring.rabbitmq.listener.simple.acknowledge-mode: 表示消息确认方式,其有三种配置方式,分别是none、manual和auto;默认auto
spring.rabbitmq.listener.simple.concurrency: 最小的消费者数量
spring.rabbitmq.listener.simple.max-concurrency: 最大的消费者数量
spring.rabbitmq.listener.simple.prefetch: 一个消费者最多可处理的nack消息数量,如果有事务的话,必须大于等于transaction数量.
spring.rabbitmq.listener.simple.transaction-size: 当ack模式为auto时,一个事务(ack间)处理的消息数量,最好是小于等于prefetch的数量.若大于prefetch, 则prefetch将增加到这个值
spring.rabbitmq.listener.simple.default-requeue-rejected: 决定被拒绝的消息是否重新入队;默认是true(与参数acknowledge-mode有关系)
spring.rabbitmq.listener.simple.missing-queues-fatal=true 若容器声明的队列在代理上不可用,是否失败; 或者运行时一个多多个队列被删除,是否停止容器
spring.rabbitmq.listener.simple.idle-event-interval: 发布空闲容器的时间间隔,单位毫秒
spring.rabbitmq.listener.simple.retry.enabled=false: 监听重试是否可用
spring.rabbitmq.listener.simple.retry.max-attempts=3: 最大重试次数
spring.rabbitmq.listener.simple.retry.max-interval=10000ms: 最大重试时间间隔
spring.rabbitmq.listener.simple.retry.initial-interval=1000ms:第一次和第二次尝试传递消息的时间间隔
spring.rabbitmq.listener.simple.retry.multiplier=1: 应用于上一重试间隔的乘数
spring.rabbitmq.listener.simple.retry.stateless=true: 重试时有状态or无状态
spring.rabbitmq.listener.direct.acknowledge-mode= ack模式
spring.rabbitmq.listener.direct.auto-startup=true 是否在启动时自动启动容器
spring.rabbitmq.listener.direct.consumers-per-queue= 每个队列消费者数量.
spring.rabbitmq.listener.direct.default-requeue-rejected= 默认是否将拒绝传送的消息重新入队.
spring.rabbitmq.listener.direct.idle-event-interval= 空闲容器事件发布时间间隔.
spring.rabbitmq.listener.direct.missing-queues-fatal=false若容器声明的队列在代理上不可用,是否失败.
spring.rabbitmq.listener.direct.prefetch= 每个消费者可最大处理的nack消息数量.
spring.rabbitmq.listener.direct.retry.enabled=false 是否启用发布重试机制.
整个队列消息的存活时间
@Bean("bootQueue")
public Queue bootQueue(){
return QueueBuilder.durable(Queue_Name).ttl(30000).build();//设置ttl,单位ms
}
单个消息的存活时间
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("3000");//消息过期时间
return message;
}
};
rabbitTemplate.convertAndSend(Exchange_Name,"boot.haha","boot mq hello",messagePostProcessor);
两者都设置了时间以时间短的为准
n(“bootQueue”)
public Queue bootQueue(){
return QueueBuilder.durable(Queue_Name).ttl(30000).build();//设置ttl,单位ms
}
单个消息的存活时间
```java
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("3000");//消息过期时间
return message;
}
};
rabbitTemplate.convertAndSend(Exchange_Name,"boot.haha","boot mq hello",messagePostProcessor);
两者都设置了时间以时间短的为准