RabbitMQ介绍以及基本使用
文章目录
一、什么是消息队列?
二、消息队列的作用(优点)
1、解耦
2、流量削峰
3、异步
4、顺序性
三、RabbitMQ基本结构
四、RabbitMQ队列模式
1、简单队列模式
2、工作队列模式
3、发布/订阅模式
4、路由模式
5、主题模式
6、RPC模式
7、发布者确认模式
五、RabbitMQ相关属性描述
总结
一、什么是消息队列?
消息队列是一种用于在分布式系统中进行通信的技术。它是一种存储和转发消息的中间件,可以用
于将应用程序之间的通信解耦,从而实现高效的异步通信。消息队列允许发送者将消息发送到队列
中,而接收者则可以从队列中获取消息并进行处理。这种方式可以帮助系统实现高可用性、高性
能、松耦合和可伸缩性。消息队列通常包括生产者(发送消息的应用程序)、消费者(接收消息的
应用程序)和队列(存储消息的缓冲区)。
RabbitMQ:是由erlang语言开发,基于AMQP(高级消息队列协议)协议实现的一种消息队列。市面
上还有很多消息队列,比如Kafka、RocketMQ、Redis等,各有优劣,本文主要介绍RabbitMQ。
官方文档:RabbitMQ Tutorials | RabbitMQ
二、消息队列的作用(优点)
1、解耦
应用程序解耦,通过引入消息队列,不同的应用程序之间可以通过消息队列进行通信,而无需直接
调用对方的接口或方法。这样可以降低系统中各个应用程序之间的耦合度,使得它们可以独立演化
和扩展,而不会因为对方的变化而受到影响。
2、流量削峰
消息队列可以作为一个缓冲区,暂时存储流入的消息,直到系统有足够的资源来处理它们。当系统
出现流量高峰时,消息队列可以暂时存储过多的消息,以平滑处理流量的波动,避免系统被突发的
高负载压垮。
3、异步
发送者在发送消息后可以立即继续执行其他操作,而不需要等待接收者的响应。这样可以提高系统
的并发性和响应速度。也可以帮助提高系统的吞吐量,特别是在面对大量请求或处理复杂计算时。
发送者可以并行地向多个接收者发送消息,而不会因为等待接收者的响应而阻塞。
4、顺序性
虽然并不是所有消息队列都能保证消息的绝对顺序性,但是在许多情况下,消息队列可以保证消息
的相对顺序性。即按照发送顺序进行处理,对某些场景要求顺序执行很适合。
三、RabbitMQ基本结构
名称
描述
Connection(连接 )
连接是生产者和消费者与RabbitMQ之间的连接。每个生产者和消费者都需要与RabbitMQ建立一个连接,以便发送和接收消息。连接通常是长连接,可以重用以提高性能和效率。
Channel(信道)
Channel是连接(Connection)内的逻辑通道,用于完成大部分 AMQP 操作,如声明队列、发送和接收消息等。在 RabbitMQ 中引入 Channel(信道)的主要目的是为了提高系统的性能、灵活性和效率。使用 Channel 可以避免频繁地创建和销毁连接,因为一个连接可以包含多个 Channel。这样可以减少连接的开销,节省系统资源,并提高性能。
Exchange(交换机)
交换机是消息的接收和分发中心,负责接收生产者发送的消息,并根据指定的路由规则发送到一个或多个队列中。
(Exchange相当于Queue的代理,可以设置不同的写入策略,写入到对应的队列中。对于队列的写入,更加灵活)
交换机的类型有:fanout扇出、topic主题、direct直接
Queue(队列)
队列是消息的缓存区,用于存储交换机发送的消息。生产者发送的消息最终会被存储在队列中,等待消费者进行消费。队列可以持久化到磁盘,以确保消息不会在RabbitMQ宕机或重启后丢失。
Producer(生产者)
生产者是发送消息到RabbitMQ的应用程序。生产者负责创建消息并将其发送到RabbitMQ的消息队列中。
Consumer(消费者)
消费者是从RabbitMQ队列中接收消息并进行处理的应用程序。消费者可以订阅一个或多个队列,并在消息到达队列时接收并处理它们。消费者负责监听队列中的消息,并将其取出进行处理。
四、RabbitMQ队列模式
基于Exchange交换机,RabbitMQ截至目前有七种队列模式。
1、简单队列模式
一个消息生产者,一个消息消费者,一个队列。也称为点对点模式。
图中P代表生产者,C代表消费者,Queue是队列名称。
我们看到是没有Exchange的,但是RabbitMQ也会有一个默认的交换机。这个默认的交换机通常被
称为"amq.default"或者""(空字符串),是RabbitMQ自动创建的,用于在没有指定交换机的情况
下将消息发送到队列。
//生产者
var factory = new ConnectionFactory { HostName = "localhost"}; //初始化连接信息
using var connection = factory.CreateConnection(); //创建连接
using var channel = connection.CreateModel(); //创建信道//声明一个队列,并将信道与队列绑定
channel.QueueDeclare(queue: "hello",durable: false,exclusive: false,autoDelete: false,arguments: null);
//发送消息的内容
string message = $"Hello World!";
var body = Encoding.UTF8.GetBytes(message);//信道绑定交换机
channel.BasicPublish(exchange: string.Empty,routingKey: string.Empty,basicProperties: null,body: body);Console.WriteLine($" [x] Sent {message}");Console.WriteLine(" Press [enter] to exit.");//消费者
var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.QueueDeclare(queue: "hello",durable: false,exclusive: false,autoDelete: false,arguments: null);Console.WriteLine(" [*] Waiting for messages.");var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{var body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);Console.WriteLine($" [x] Received {message}");
};
channel.BasicConsume(queue: "hello",autoAck: true,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");
此时就会生产者发送一条消息,消费者就会接收一条消息。
2、工作队列模式
_工作队列又叫做任务队列,正常_会按顺序把消息发送给每一个订阅的消费者,平均而言,每个消费
者将获得相同数量的消息。(不是P发送一条消息,C1和C2都会收到,而是第一条C1消费,第二
条C2消费。每个消息只会被一个消费者接收和处理)。
这样的好处是可以提高吞吐量,因为生产者发送了很多消息,但是消费者只有一个,消费者处理很
慢,就会造成消息积压。
//生产者
var factory = new ConnectionFactory { HostName = "localhost"};
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.QueueDeclare(queue: "task_queue",durable: true,exclusive: false,autoDelete: false,arguments: null);var message = $"work queue";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: string.Empty,routingKey: string.Empty,basicProperties: null,body: body);
Console.WriteLine($" [x] Sent {message}");Console.WriteLine(" Press [enter] to exit.");//消费者
var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.QueueDeclare(queue: "task_queue",durable: true,exclusive: false,autoDelete: false,arguments: null);Console.WriteLine(" [*] Waiting for messages.");var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{byte[] body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);Console.WriteLine($" [x] Received {message}");channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
};
channel.BasicConsume(queue: "task_queue",autoAck: false,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");
工作队列与简单队列一致,会有一个默认的交换机。
3、发布/订阅模式
发布/订阅模式是一种消息传递模式,它允许发送者(发布者)将消息发布到多个接收者(订阅
者)。消息传递模型的核心思想是生产者从不直接向队列发送任何消息。实际上,生产者通常根本
不知道消息是否会被传递到任何队列。
所以消息传递模式,发布者不需要指定队列。
发布/订阅模式交换机类型为Fanout。
//发布者
var factory = new ConnectionFactory { HostName = "localhost"};
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();//声明一个交换机,叫做logs,并且交换机的类型是Fanout
channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);var message = "publish_subscribe";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "logs",routingKey: string.Empty,basicProperties: null,body: body);
Console.WriteLine($" [x] Sent {message}");Console.WriteLine(" Press [enter] to exit.");//接收者
var factory = new ConnectionFactory { HostName = "localhost"};
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);//创建一个具有生成名称的非持久、独占、自动删除队列
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName,exchange: "logs",routingKey: string.Empty);Console.WriteLine(" [*] Waiting for logs.");var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{byte[] body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);Console.WriteLine($" [x] {message}");
};
channel.BasicConsume(queue: queueName,autoAck: false,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");
注:如果发布者已经发布消息到交换机,但还没有队列绑定到交换机,消息将会丢失。
4、路由模式
路由模式也是一种消息传递模式,是基于消息的路由键(routing key)来将消息从交换机
(exchange)发送到一个或多个队列中。相比较于发布/订阅模式,路由模式多了一个routing key
的概念。
路由模式交换机类型为Direct。
//生产者
var factory = new ConnectionFactory { HostName = "localhost"};
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();//定义交换机名称以及类型为Direct
channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);//定义路由键
string routingKey = "direct_test";//发送消息体
string message = "direct_message";
var body = Encoding.UTF8.GetBytes(message);channel.BasicPublish(exchange: "direct_logs",routingKey: routingKey,basicProperties: null,body: body);
Console.WriteLine($" [x] Sent '{routingKey}':'{message}'");Console.WriteLine(" Press [enter] to exit.");//消费者
var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);//创建一个具有生成名称的非持久、独占、自动删除队列
var queueName = channel.QueueDeclare().QueueName;//路由键集合
var routeKeyArr = new string[] { "direct_test", "direct_test2" };foreach (var routeKey in routeKeyArr)
{channel.QueueBind(queue: queueName,exchange: "direct_logs",routingKey: routeKey);
}Console.WriteLine(" [*] Waiting for messages.");var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{var body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);var routingKey = ea.RoutingKey;Console.WriteLine($" [x] Received '{routingKey}':'{message}'");
};
channel.BasicConsume(queue: queueName,autoAck: true,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");
路由模式,消费者可以监听多个路由键。
5、主题模式
基于路由模式,仍然有局限性——它不能基于多个标准进行路由。也就是一个消费者只能接收完全
与routing key相匹配的交换机。主题模式主要解决路由模式的不足,可以模糊匹配routing key。
路由模式交换机类型为Topic。
在生产者方面,基于 . 作为分隔符,用于routing key。比如“stock.usd.nyse
”、“nyse.vmw
”、
“quick.orange.rabbit
”。可以是任何单词,但最多只有255 个字节。
在消费者方面,绑定routing key有两种重要的情况:
(1)*(星号):匹配一个单词。
具体语法:
var routeing_key = "info.debug.error";//匹配 info
"info.*.*"
//匹配debug
"*.debug.*"
//匹配error
"*.*.error"
(2)#(散列):匹配零个或多个单词。
具体语法:
var routeing_key = "info.debug.error";//匹配 info
"info.#"
//匹配debug
"#.debug.#"
//匹配error
"*.*.error"
6、RPC模式
RPC模式又叫"请求/回复模式"。
RPC(Remote Procedure Call,远程过程调用)是一种用于在分布式系统中进行通信的技术。它
允许一个进程(或线程)调用另一个进程(或线程)的过程(函数或方法),就像调用本地函数一
样,而不需要开发者显式处理底层通信细节。
(就是生产者发送一条消息,消费者端执行某个方法,获取值的同时,并返回到生产者。)
//生产者
var factory = new ConnectionFactory { HostName = "localhost"};
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();//定义接收返回结果的队列
var replyQueueName = channel.QueueDeclare().QueueName;
var consumer = new EventingBasicConsumer(channel);consumer.Received += (model, ea) =>
{var body = ea.Body.ToArray();var response = Encoding.UTF8.GetString(body);Console.WriteLine(" [.] Got '{0}'", response);
};//发送消息
var correlationId = Guid.NewGuid().ToString(); //消息唯一性
var props = channel.CreateBasicProperties();
props.CorrelationId = correlationId;
props.ReplyTo = replyQueueName; //回调队列名称string message = "30";
var messageBytes = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "",routingKey: "rpc_queue",basicProperties: props,body: messageBytes);channel.BasicConsume(consumer: consumer,queue: replyQueueName,autoAck: true);//消费者
var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.QueueDeclare(queue: "rpc_queue",durable: false,exclusive: false,autoDelete: false,arguments: null);
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
var consumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: "rpc_queue",autoAck: false,consumer: consumer);
Console.WriteLine(" [x] Awaiting RPC requests");
consumer.Received += (model, ea) =>
{string response = string.Empty;var body = ea.Body.ToArray();var props = ea.BasicProperties;var replyProps = channel.CreateBasicProperties();replyProps.CorrelationId = props.CorrelationId;try{var message = Encoding.UTF8.GetString(body);int n = int.Parse(message);Console.WriteLine($" [.] Fib({message})");response = FibHelper.Fib(n).ToString();}catch (Exception e){Console.WriteLine($" [.] {e.Message}");response = string.Empty;}finally{//回调到生产者队列var responseBytes = Encoding.UTF8.GetBytes(response);channel.BasicPublish(exchange: string.Empty,routingKey: props.ReplyTo,basicProperties: replyProps,body: responseBytes);channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);}
};//执行函数,并返回结果
public class FibHelper
{public static int Fib(int n){if (n == 0 || n == 1)return n;return Fib(n - 1) + Fib(n - 2);}
}
RPC模式不是消息传递模式,消息只会被一个消费者消费。
7、发布者确认模式
发布者确认模式(Publisher Confirmation)是 RabbitMQ 提供的一种机制,用于确保消息被成功
发送到交换机(exchange)并被接收到,以及确保消息被正确地路由到队列中。在传统的消息发
布过程中,发布者发送消息到交换机后,并不知道消息是否已经被正确地处理。为了解决这个问
题,RabbitMQ 提供了发布者确认模式,允许发布者确认消息是否已经被成功接收到。
//生产者
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{// 设置信道为确认模式channel.ConfirmSelect();// 声明一个队列channel.QueueDeclare(queue: "hello",durable: false,exclusive: false,autoDelete: false,arguments: null);// 消息内容string message = "Hello World!";var body = Encoding.UTF8.GetBytes(message);try{// 发送消息channel.BasicPublish(exchange: "",routingKey: "",basicProperties: null,body: body);// 等待消息确认if (channel.WaitForConfirms()){Console.WriteLine(" [x] Sent {0}", message);}else{Console.WriteLine(" [x] Failed to send {0}", message);}}catch (Exception ex){Console.WriteLine($"An error occurred: {ex.Message}");}
}Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();//消费者
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{// 声明一个队列channel.QueueDeclare(queue: "hello",durable: false,exclusive: false,autoDelete: false,arguments: null);// 创建消费者var consumer = new EventingBasicConsumer(channel);// 消费消息consumer.Received += (model, ea) =>{var body = ea.Body;var message = Encoding.UTF8.GetString(body);Console.WriteLine(" [x] Received {0}", message);};// 消费者开始接收消息channel.BasicConsume(queue: "hello",autoAck: true,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");Console.ReadLine();
}
五、RabbitMQ相关属性描述
上述代码中,有很多属性的设置,下面解释一下。
名称
值
描述
durable
布尔
队列是否持久化。如果将队列声明为持久化,那么当 RabbitMQ 服务器重启时,队列将被重新声明。持久化队列中的消息会被存储在磁盘上,因此即使在服务器重启后,消息也不会丢失。
exclusive
布尔
是否为排他队列。当队列被声明为排他时,只有声明该队列的连接(connection)才能使用它。一旦连接关闭,排他队列就会被删除。这种队列通常是用于临时任务,只允许声明它的连接使用,不会被其他连接访问。
autoDelete
布尔
队列是否自动删除。如果将队列声明为自动删除,则在最后一个连接订阅它的消费者取消订阅后,队列将被自动删除。这种属性通常与临时队列一起使用,以确保在不再需要队列时它会被清理。
arguments
类
用于设置队列或交换机的额外参数的选项。这些参数可以用于定制化队列或交换机的行为,以满足特定的需求。比如,设置队列的最大长度、消息在队列中的最大存活时间。
autoAck
布尔
消息是否自动确认。它是指在消费者从队列中接收到消息后,是否自动确认消息的消费。当设置为 true
时,表示消费者会自动确认收到的消息,此时队列中表示该消息已被消费成功了。当设置为 false
时,表示消费者需要显式地调用确认方法来告知 RabbitMQ 已经成功处理了消息,否则消息将被重新放回队列,等待其他消费者处理。
basicProperties
类
是指在发布消息时可以携带的消息属性。这些属性包含了有关消息的元数据信息,例如消息的优先级、消息的过期时间、消息的类型等等。
总结
RabbitMQ 是一个消息队列,主要作用就是异步、顺序性、削峰等。
七种队列模式,可以根据不同的场景具体使用。
1. 简单队列模式
最简单的消息模式。一个生产者发送消息到一个队列,一个消费者从队列中接收消息并处理。适用
于单个生产者-单个消费者的简单场景。
2. 工作队列模式
多个消费者共同消费消息。消费者从队列中取出消息并处理,消息会平均地分配给消费者。
是基于简单队列模式的缺点,做了提升。适用于负载均衡和任务分发的场景。
3. 发布/订阅模式
生产者将消息发送到交换机,交换机将消息广播到所有与之绑定的队列。多个消费者可以订阅不同
的队列,从而接收消息的副本。适用于消息广播和通知的场景。
4. 路由模式
生产者发送消息到交换机,并使用路由键指定消息的目标队列。交换机根据消息的路由键将消息路
由到与之匹配的队列中。适用于根据消息内容进行精确路由的场景。
5. 主题模式
类似于路由模式,但是路由键可以使用通配符进行匹配。适用于消息的多样化路由和灵活的匹配需
求。
6. RPC模式
客户端(RPC请求者)发送请求消息到队列中,并等待服务器(RPC响应者)返回响应消息。
服务器监听请求队列,处理请求并将响应发送回客户端指定的队列。适用于需要请求-响应式通信
的场景,类似于远程调用。
7. 发布者确认模式
发布者确认模式是 RabbitMQ 提供的一种机制,用于确保消息在发送到交换机并被路由到队列时的
可靠性。
相关文章:

RabbitMQ介绍以及基本使用
文章目录 一、什么是消息队列? 二、消息队列的作用(优点) 1、解耦 2、流量削峰 3、异步 4、顺序性 三、RabbitMQ基本结构 四、RabbitMQ队列模式 1、简单队列模式 2、工作队列模式 3、发布/订阅模式 4、路由模式 5、主题模式 6、…...

C++演示中介模式
避免两个模块之间的耦合,使用中介模式解决。下面是C代码 #include <iostream> #include <vector>using namespace std;class client;//中介 class mediator { public:void addclient(client* client) {clientVec.push_back(client);}void send(const s…...

Vue的简单入门 一
声明:本版块根据B站学习,创建的是vue3项目,用的是vue2语法风格,仅供初学者学习。 目录 一、Vue项目的创建 1.已安装15.0或更高版本的Node.js 2.创建项目 二、 简单认识目录结构 三、模块语法中的指令 1.v-html 1.文本插值…...

【免费送书活动】《MySQL 9从入门到性能优化(视频教学版)》
本博主免费赠送读者3本书,书名为《MySQL 9从入门到性能优化(视频教学版)》。 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 这本书已经公开…...
export default与export区别
1.定义: export default:用于导出模块中的默认成员。一个模块中只能有一个export default,通常用于导出模块的主要功能或对象。导入时可以使用任意名称,因为它没有具体的名称 export:用于导出模块中的多个成…...
最佳的出牌方法
最佳的出牌方法 真题目录: 点击去查看 E 卷 200分题型 题目描述 手上有一副扑克牌,每张牌按牌面数字记分(J=11,Q=12,K=13,没有大小王),出牌时按照以下规则记分: 出单张,记牌面分数,例如出一张2,得分为2出对或3张,记牌面分数总和再x2,例如出3张3,得分为(3+3+3)x2=1…...
Kotlin 2.1.0 入门教程(二十一)数据类
数据类 数据类主要用于存储数据。 对于每个数据类,编译器会自动生成一些额外的成员函数,这些函数支持将实例打印为易读的输出、比较实例、复制实例等操作。 数据类使用 data 关键字标记: data class User(val name: String, val age: Int…...

30天开发操作系统 第 20 天 -- API
前言 大家早上好,今天我们继续努力哦。 昨天我们已经实现了应用程序的运行, 今天我们来实现由应用程序对操作系统功能的调用(即API, 也叫系统调用)。 为什么这样的功能称为“系统调用”(system call)呢?因为它是由应用程序来调用(操作)系统中的功能来完…...
WEB安全--SQL注入--floor报错注入
一、原理: floor()报错注入需要组合count()、rand()、group by()等函数使用,通过一些手段使数据库在处理语句时产生主键重复的报错,从而达到爆出信息的目的 二、内容: ?id-1 or (select 1 from (select count(*),concat(databa…...
【java面向对象的三大特性】封装、继承和多态
目录标题 一、封装(Encapsulation):二、继承(Inheritance):三、多态(Polymorphism):1. 多态的三个必要条件:2.多态的具体实现:3.多态的使用场景&a…...
Hermite 插值
Hermite 插值 不少实际问题不但要求在节点上函数值相等,而且还要求它的导数值相等,甚至要求高阶导数值也相等。满足这种要求的插值多项式就是 Hermite 插值多项式。 下面只讨论函数值与导数值个数相等的情况。设在节点 a ≤ x 0 < x 1 < ⋯ <…...

【推理llm论文精度】DeepSeek-R1:强化学习驱动LLM推理能力飞跃
最近deepseek R1模型大火,正好复习一下他家的技惊四座的论文https://arxiv.org/pdf/2501.12948 近年来,大型语言模型(LLM)在推理能力上取得了显著进展,但如何进一步有效提升仍然是研究热点。DeepSeek-AI发布了 DeepS…...

arm linux下的中断处理过程。
本文基于ast2600 soc来阐述,内核版本为5.10 1.中断gic初始化 start_kernel() -> init_IRQ() -> irqchip_init() of_irq_init()主要是构建of_intc_desc. 489-514: 从__irqchip_of_table中找到dts node中匹配的of_table(匹配matches->compatible)…...

C语言:指针详解
C语言:指针详解 1:指针的基本概念1:什么是指针2:为什么要引入指针3:指针的作用4:指针的类型 2:指针的声明与初始化1: 指针的声明2: 指针的初始化 3:指针的操作…...

github用户名密码登陆失效了
问题: git push突然推代码需要登陆,但是用户名和密码正确输入后,却提示403 git push# Username for https://github.com: **** #Password for https://gyp-programmergithub.com: #remote: Permission to gyp-programmer/my-app.git denie…...
【删除tomcat默认管理控制台】
停止Tomcat: ./catalina.sh stop 删除管理控制台应用: 进入Tomcat的webapps目录: cd /path/to/tomcat/webapps List item 删除manager和host-manager文件夹: rm -rf manager host-manager 启动Tomcat: ./catali…...
动态库与静态库:深入解析与应用
在软件开发中,库(Library)是预编译的代码集合,用于在多个程序之间共享功能。根据链接方式的不同,库主要分为两种类型:静态库(Static Library) 和 动态库(Dynamic Library…...

【鱼眼镜头12】Scaramuzza的鱼眼相机模型实操,不依赖于具体的相机几何结构,直接从图像数据出发,因此更具灵活性。
文章目录 Scaramuzza相机模型标定效果2、原理和代码代码1、 2D映射到3D,函数输入为2D点坐标OCAM参数代码功能详解2、3D --> 2D 3、总结Scaramuzza 模型的核心思想Scaramuzza 模型的核心思想与 Kannala-Brandt 模型的对比Scaramuzza 模型的独特之处Scaramuzza 的意…...

LVS 负载均衡集群(NAT模式)
一、环境准备 四台主机(一台 LVS、两台 RS、一台客户端) 注意每个虚拟机都需要关闭防火墙和 selinux 1.1.LVS 主机 LVS 主机(两块网卡) 第一块:NAT模式(内网) 第二块:添加网卡&am…...
MATLAB中的APPdesigner绘制多图问题解析?与逻辑值转成十进制
在matlab APPdesigner中绘图可以用UIAxes组件进行绘图,但是当想多张图时,只能提前绘制图像区域不方便。下面是几种办法: 为了操作可以添加Panl组件,方便操作。 1、当是要求的几个图像大小都是相同时刻采用函数: til…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...