RabbitMQ 基础概念(队列、交换机、路由键、绑定键、信道、连接、虚拟主机、多租户)介绍


RabbitMQ
本文是博主在梳理 RabbitMQ 知识的过程中,将所遇到和可能会遇到的基础知识记录下来,用作梳理 RabbitMQ 的整体架构和功能的线索文章,通过查找对应的知识能够快速的了解对应的知识而解决相应的问题。


文章目录

  • 一、RabbitMQ 是什么?
  • 二、RabbitMQ 的核心概念
    • 01、消息(Message)
    • 02、生产者(Producer)
    • 03、消费者(Consumer)
    • 04、消息中间件的服务节点(Broker)
    • 05、队列(Queue)
    • 06、交换机(Exchange)
    • 07、路由键(RoutingKey)
    • 08、绑定(Binding)
    • 09、信道(Channel)
    • 10、连接(Connection)
    • 11、虚拟主机(Virtual Host, vHost)
    • 10、多租户(Multi-Tenancy)
    • 11、虚拟主机与多租户的对比与延伸
  • 三、协议与通信
    • 1. AMQP 协议(Advanced Message Queuing Protocol)
    • 2. MQTT 协议(Message Queuing Telemetry Transport)
    • 3. STOMP 协议(Simple Text Oriented Messaging Protocol)

一、RabbitMQ 是什么?

RabbitMQ 是一个开源的消息中间件(Message Broker),基于 AMQP(高级消息队列协议,Advanced Message Queuing Protocol)实现,旨在为分布式系统提供可靠的异步通信解决方案。

在开发中引入 RabbitMQ 中间件一般用作不同项目之间的消息传递。例如在即时通讯项目中,常会将不同的业务进行构建独自的服务项目,比如消息服务、文件服务、状态服务和查询服务等,各个服务之间相互独立又彼此相连。例如用户状态(上线或下线)的传递,实时传输到各个服务,而又不会受到其他服务的影响,实现解耦。

  • 异步通信桥梁:允许不同应用程序通过 消息 进行间接通信,无需实时同步响应,提升系统解耦性和可扩展性。

使用 RabbitMQ 还有一个好处就是他的消息传递是通过交换机传输到队列中,消息队列具有一定的容量可以应对流量的波动。例如一个大型的即时通讯服务,用户的状态会经常发生变化(上线-离开-在线-请勿打扰)等等,例如早晨用户状态变化可能会急剧增加,用户在进入离开状态会有一段时间,就会出现一个状态变化的峰值。消息队列能够存储一定的流量,缓解消费者的压力,同时稳定服务的消费能力不会大幅变化。

  • 削峰填谷:通过消息队列暂存峰值流量,缓解后端服务压力,适用于流量波动较大的场景(如电商促销、日志处理)。

状态服务的消息传输是需要稳定传输的,不然你就可能会和一个 下线 的人在聊天,这就会影响用户体验,基于此,RabbitMQ 具有机制保障消息能够可靠的传输。

  • 可靠消息传递:支持消息持久化、确认机制(ACK)、重试策略等,确保消息不丢失或重复处理。

此外 RabbitMQ 还具有一些其他优势,如:

  • 多语言支持:提供 Java、Python、C#、Go、JavaScript 等主流语言的客户端库,方便跨平台集成。
  • 高可用性与集群:支持节点集群部署(如镜像队列),实现故障转移和负载均衡,保障服务稳定性。
  • 插件生态:通过插件扩展功能,例如管理界面(RabbitMQ Management Plugin)、STOMP/MQTT 协议支持、消息追踪等。
  • 轻量与高效:基于 Erlang 语言开发,天生支持高并发和低延迟,适合分布式系统环境。与 Kafka 等吞吐量优先的中间件相比,RabbitMQ 在处理超大规模数据时性能稍弱,更适合中等规模、注重可靠性的业务。

RabbitMQ 是分布式系统中实现异步通信的核心工具,通过消息队列、交换机和路由规则的组合,帮助开发者解耦系统模块、提升容错能力,适用于需要可靠消息传递的企业级应用,如金融、电商、物流等领域。

二、RabbitMQ 的核心概念

RabbitMQ 整体上是一个生产者和消费者模型,主要负责接收,存储和转发消息。

RabbitMQ
上图是从网上找的网图,标有作者,如有侵权请联系删除。

我们可以从该图了解里面的工作流程:生产者生产消息,携带路由键发布到交换器中,交换器根据绑定键路由到不同的队列,消费者根据所订阅的队列消费消息。

01、消息(Message)

通信的最小单元,通常包含两个部分:消息体和标签。

  • 消息体:消息体也可以称之为内容(Payload),实际数据(如 JSON 格式的订单信息)。
  • 标签:有时被称为 元数据 ,用来表述这条消息。
    • 例如:路由键、过期时间、优先级、是否持久化等。
    • 如物流消息:标注 易碎品(属性),通知消费者轻拿轻放。

类比:快递包裹,内部是商品(Payload),外部面单是元数据(地址、重量、保价等)。

02、生产者(Producer)

投递消息的一方,常见于发送消息的应用程序或服务。

  • 不关心消息如何被处理,只负责将消息丢给 RabbitMQ。
    • 如打车软件:司机接单后,将行程信息发送到消息队列,由后台系统异步派单。
  • 支持批量发送、消息持久化等配置。

类比:餐厅厨师,做好餐后将菜品(消息)交给传菜员(RabbitMQ),不关心顾客何时就餐。

03、消费者(Consumer)

接收并处理消息的应用程序或服务。当消费者消费一条消息时,只是消费消息的消息体(payload)。在消息路由的过程中,消息的标签会被丢弃,存入到队列的只有消息体,消费者也只会消费到消息体,也就不知道消息的生产者是谁。

  • 主动 订阅 队列,按需拉取消息。
    • 如电商订单系统:库存服务监听 扣库存 队列,收到消息后执行扣减操作。
  • 支持消息确认(ACK):处理完成后通知 RabbitMQ 移除消息,避免丢失。

类比:超市收银员,从传送带(队列)上取商品(消息)扫码结账,完成后商品离开传送带。

04、消息中间件的服务节点(Broker)

在学习 RabbitMQ 时,经常会遇到这个这个概念,英文直译为中间件(经纪人),一般是消息队列的服务实体。

对于 RabbitMQ 来说,一个 RabbitMQ Broker 可以简单的看作一个 RabbitMQ 服务节点,或者 RabbitMQ 服务实例,大多数情况下也可以看作一台 RabbitMQ 服务器。

05、队列(Queue)

RabbitMQ 的内部对象,消息的最终存储容器,消费者从这里获取消息,可以理解成存放消息的 临时仓库 ,支持 异步收发 和 削峰填谷 。RabbitMQ 的消息只能存储在队列里,和 Kafka 正好相反,Kafka 将消息存储在 topic (主题)这个层面,而相应的队列逻辑只是 topic 实际存储文件中的位移标识。RabbitMQ 最终生产的消息最终会投递到队列中,供消费者消费。

  • 支持持久化(消息存磁盘,RabbitMQ 重启不丢失)。
  • 多消费者竞争消费(如订单队列:多个支付服务节点同时处理订单,提升吞吐量)。

当多个消费者可以订阅同一个队列,这时消息默认会平均分摊(Round-Ronbin,轮询)给多个消费者进行处理。

  • 解耦生产者和消费者(如外卖平台:商家出餐后将“餐品”放入取餐柜,骑手按需取餐,无需实时等待)。
  • 应对流量波动(如电商大促:订单消息先存入队列,避免瞬间压垮支付系统)。

06、交换机(Exchange)

RabbitMQ 最终生产的消息最终会投递到队列中,供消费者消费。在这个过程中,消息是先发送到 Exchange 交换器,由交换器将消息根据 路由规则 路由到一个或者多个队列中。如果路由不到,或许会返还给生产者,也有可能会丢弃消息。

交换器只负责转发消息,不具备存储功能,可以理解成一个简单的实体。交换器有四种不同的类型,不同的类型有不同的类型策略,会在第四章详细介绍。

  • Direct(精准匹配):消息携带 路由键,交换机按 键 路由到对应队列。
  • Fanout(广播):消息直接复制到所有绑定队列。
  • Topic(模式匹配):支持通配符(如“user.#”匹配“user.register”“user.login”等队列)。
  • headers (头交换机):不依赖路由键的匹配功能,而是根据发送消息中的 headers 属性进行匹配。

07、路由键(RoutingKey)

生产者将消息发送给交换机的时候,一般会指定一个 RoutingKey,用来指定这个消息的路由规则,而这个 RoutingKey 需要与交换器类型和绑定键 BindingKey 联合使用才会生效。

08、绑定(Binding)

RabbitMQ 通过绑定将交换器和队列关联起来,在绑定的时候一般会指定一个绑定键 BindiingKey ,这样就知道如何正确的将不同的消息路由到正确的队列。

整体来说:生产者将消息发给交换器时,需要一个 RoutingKey ,当 BindingKey 和 RoutingKey 相匹配时,消息会被路由到对应队列中。在绑定多个队列到一个交换器时,这些绑定允许使用相同的 BindingKey 。

BindingKey 并不是在所有的情况下都生效,它依赖于交换器类型,例如在 fanout 和 header 交换器中就会失效。

  • 交换器相当于投递包裹的邮箱。
  • RoutingKey 相当于填写在包裹上的地址。
  • BindingKey 相当于包裹的目的地。
    • 在使用绑定的时候,需要的路由键是 BindingKey。
    • 在发送消息的时候,需要的路由键是 RoutingKey。
  • 一个交换机可绑定多个队列,一个队列可绑定多个交换机。

09、信道(Channel)

生产者和消费者与 RabbitMQ 通信的轻量级通道,复用 TCP 连接。

  • 避免频繁创建 TCP 连接(一个连接可创建多个信道,如 1 个连接支持 1000 个信道,节省资源)。
  • 线程安全:每个线程独立使用信道,互不干扰(如电商订单服务:10 个线程通过 1 个连接的 10 个信道并发发送消息)。

类比:高速公路的“车道”,多个车辆(消息)通过同一条高速(连接)的不同车道(信道)并行行驶。

10、连接(Connection)

生产者和消费者与 RabbitMQ 建立的TCP 长连接。 其核心生命周期:

  • 建立:耗时操作(需认证、协商参数),建议复用。
  • 心跳机制:防止连接中断(默认 60 秒发送一次心跳包)。
  • 关闭:异常时自动重连(如网络闪断后,消费者重新建立连接继续消费)。

类比:打电话时的“通话链路”,一次拨号(连接)支持多次对话(信道传输消息),挂断后需重新拨号。

11、虚拟主机(Virtual Host, vHost)

虚拟主机是 RabbitMQ 中一种 逻辑隔离机制,类似于操作系统中的 目录 或数据库中的 Schema,相当于逻辑隔离的 容器 。

它将单个 RabbitMQ 服务器划分为多个独立的环境,每个环境拥有自己的 Exchange(交换器)、Queue(队列)、Binding(绑定)、用户权限 等资源,且这些资源在不同虚拟主机之间完全隔离(除非显式共享,通常不会)。

  • 资源隔离:每个虚拟主机是一个独立的沙箱,例如租户 A 的队列 order_queue 和租户 B 的队列 order_queue 互不干扰,因为它们属于不同虚拟主机。
  • 权限控制单元:虚拟主机是 RabbitMQ 权限管理的最小粒度。管理员可为每个虚拟主机单独配置用户的 读/写/配置权限,例如用户 user1 只能访问虚拟主机 vhost1 中的队列,无法查看 vhost2 的内容。
  • 配置独立:每个虚拟主机可自定义连接地址(如 amqp://user:password@host:port/vhost1),甚至支持不同的插件配置(尽管较少使用)。
  • 多租户支持:一个 RabbitMQ 实例可创建多个 vHost ,供不同业务线使用。
  • 与物理服务器的关系:虚拟主机是逻辑隔离,而非物理隔离。多个虚拟主机共享 RabbitMQ 服务器的内存、CPU 等资源,但通过权限和命名空间隔离避免数据交叉。
  • 与连接(Connection)的关系:客户端连接时需指定虚拟主机(默认是 /),一个连接只能属于一个虚拟主机,无法跨虚拟主机操作资源。
  • 与消息路由的关系:Exchange、Queue 的名称在虚拟主机内唯一,跨虚拟主机可重复,路由规则仅在当前虚拟主机内生效。

10、多租户(Multi-Tenancy)

多租户指一个软件系统为 多个独立租户(如企业、团队、应用) 提供服务,且确保租户之间的数据、配置、资源相互隔离,同时共享底层基础设施(降低成本),属于系统级隔离架构。

核心目标是:

  • 隔离性:租户 A 的数据不能被租户 B 访问,故障不扩散。
  • 可配置性:每个租户可自定义参数(如队列优先级、消息保留策略)。
  • 资源效率:共享服务器资源,通过配额管理避免单个租户耗尽资源。

RabbitMQ 的虚拟主机是实现多租户的核心机制,二者关系如下:

  • 虚拟主机是多租户的“载体”:每个租户分配一个独立虚拟主机,租户的所有消息实体(队列、交换器等)均在其中创建,从命名空间和权限上实现隔离。
  • 结合权限系统强化隔离:通过 user_tags(如 administrator、management)和 permission(配置、读、写权限),可精确控制租户对虚拟主机的操作范围。例如,租户 A 的用户只能 读 自己虚拟主机的队列,不能删除交换器。
  • 资源配额补充隔离:虽然虚拟主机本身不提供严格的资源限制(如内存、带宽配额),但可通过 RabbitMQ 的 资源限制插件(如 rabbitmq_shovel 或外部工具) 为不同租户分配资源上限,避免资源抢占。

与微服务、云架构的结合:

  • 微服务多租户:若微服务架构中不同业务线(如电商的 用户服务 和 订单服务 )需隔离,可将每个服务分配到独立虚拟主机,避免队列名称冲突或权限泄漏。
  • SaaS 应用场景:云服务商为每个客户(租户)创建专属虚拟主机,客户的消息管道完全独立,同时共享同一套 RabbitMQ 集群,降低基础设施成本。
  • 多环境隔离:开发、测试、生产环境可使用不同虚拟主机,避免误操作影响线上环境(如误删生产队列)。

11、虚拟主机与多租户的对比与延伸

维度虚拟主机(技术实现)多租户(架构目标)
定位RabbitMQ 内置的逻辑隔离机制,偏技术细节。系统设计目标,关注租户间的隔离、共享与资源管理。
核心价值命名空间隔离、权限控制、连接独立。支持多租户的商业模型(如 SaaS),平衡隔离与效率。
依赖关系多租户可通过虚拟主机实现,但还需结合权限、配额等。虚拟主机是多租户的一种实现方式,非唯一(如通过独立集群实现)。

与其他中间件的对比

  • Kafka 的多租户:通过 Topic(主题)+ ACL(访问控制列表) 实现,租户共享集群,但通过 Topic 隔离数据,权限控制更细粒度(如按 Topic 授权),但缺乏类似虚拟主机的“整体隔离容器”。
  • RocketMQ 的多租户:通过 Namespace(命名空间) 实现,与 RabbitMQ 虚拟主机类似,每个 Namespace 包含独立的 Topic、Group 等资源,支持租户级隔离。

实践中的注意事项

  • 资源分配均衡:虚拟主机不提供物理隔离,需通过集群节点部署、流量控制等避免单个租户拖垮整体性能。
  • 权限最小化原则:为每个租户的用户账户分配最小必要权限(如仅 读 或 写 队列),防止越权操作。
  • 监控与日志分离:通过 RabbitMQ 管理界面或插件(如 rabbitmq_prometheus)按虚拟主机监控指标(如队列长度、消息吞吐量),便于租户级故障排查。
  • 跨租户通信:若需租户间消息共享,可通过 跨虚拟主机转发(如使用 Shovel 插件将消息从一个虚拟主机复制到另一个),但需谨慎设计,避免破坏隔离性。

RabbitMQ 的虚拟主机是实现多租户的核心技术手段,通过逻辑隔离和权限控制,为多个租户提供独立的消息通信空间。二者结合后,既能满足企业内部多团队协作的隔离需求,也能支撑云原生时代 SaaS 应用的商业化架构。

理解这两个概念的关键在于把握 隔离与共享的平衡 ——虚拟主机在技术层面提供容器化隔离,多租户则从架构层面定义了如何利用这种隔离实现高效的资源分配与安全保障。

架构全景图(结合概念)

生产者 → 连接 → 信道 → 交换机(根据Binding路由)→ 队列 → 信道 → 消费者  └── 虚拟主机(隔离环境) ── 消息(含元数据)

总结:RabbitMQ 通过这些组件的协作,实现了 生产者无需知道消费者是谁、消费者无需实时等待生产者 的异步通信,是分布式系统解耦的基石。

三、协议与通信


1. AMQP 协议(Advanced Message Queuing Protocol)

AMQP 是一种开放标准的应用层协议,专为面向消息的中间件设计,支持跨平台、跨语言的企业级消息通信。其核心目标是提供可靠、灵活的消息传递机制,适用于复杂的分布式系统。

核心特点:

  • 可靠传输:支持消息确认(ACK/NACK)、持久化存储、事务机制,确保消息不丢失。
  • 灵活路由:通过交换器(Exchange)、**队列(Queue)和绑定(Binding)**实现动态消息路由。交换器类型包括:
    • 直连(Direct):基于精确的路由键匹配。
    • 主题(Topic):支持通配符模式匹配路由键。
    • 扇出(Fanout):广播到所有绑定队列。
    • 头部(Headers):基于消息属性而非路由键。
  • 多语言支持:兼容多种编程语言(如Java、Python、C#)。
  • 协议版本:
    • AMQP 0-9-1:广泛实现(如RabbitMQ),采用传统的交换器-队列模型。
    • AMQP 1.0:标准化协议,简化模型,更注重通用消息传递(如Apache ActiveMQ支持)。

适用场景:

  • 企业应用集成(如银行交易、订单处理)。
  • 云计算服务(如Azure Service Bus、RabbitMQ)。
  • 需要复杂路由和高可靠性的系统。

2. MQTT 协议(Message Queuing Telemetry Transport)

MQTT 是一种轻量级的发布/订阅模型协议,专为低带宽、高延迟或不稳定网络环境设计,广泛应用于物联网(IoT)场景。

核心特点:

  • 极简设计:协议头部仅2字节,减少传输开销。
  • QoS分级:
    • QoS 0(最多一次):尽力交付,无重传。
    • QoS 1(至少一次):确保消息到达,但可能重复。
    • QoS 2(恰好一次):通过四次握手保证精确一次交付。
  • 主题层级:支持通配符(+单层、#多层)订阅,如 sensors/+/temperature。
  • 遗嘱消息(Last Will):客户端异常断开时,代理自动发布预设消息。
  • 协议版本:
    • MQTT 3.1.1:主流版本,广泛支持。
    • MQTT 5.0:增强功能(如原因码、共享订阅、流量控制)。

适用场景:

  • 物联网设备通信(如传感器数据上报、智能家居控制)。
  • 移动应用推送(弱网环境)。
  • 需要低功耗和高效传输的嵌入式系统。

实现依赖:
在RabbitMQ等中间件中需启用插件(如 rabbitmq_mqtt)支持。


3. STOMP 协议(Simple Text Oriented Messaging Protocol)

STOMP 是一种基于文本的简单协议,设计目标是实现客户端与消息代理之间的跨语言互操作性,通常结合WebSocket用于浏览器通信。

核心特点:

  • 文本帧结构:类似HTTP,命令与标头为纯文本,消息体可包含任意格式(如JSON、XML)。
    • 示例帧:
      SEND
      destination:/queue/test
      content-type:text/plainHello, STOMP!
      
  • 基础命令:
    • CONNECT/STOMP:建立连接。
    • SEND:发送消息到目标(队列或主题)。
    • SUBSCRIBE:订阅目标。
    • ACK/NACK:消息确认。
  • 简单性:无内置路由机制,依赖代理的队列/主题管理。
  • 跨平台性:易于通过Telnet或浏览器(WebSocket)调试。

适用场景:

  • 浏览器实时通信(如股票行情推送、聊天应用)。
  • 需要快速原型开发或简单消息交互的系统。
  • 与其他文本协议(如HTTP)集成的场景。

实现依赖:
在RabbitMQ等中间件中需启用插件(如 rabbitmq_stomp)支持。


协议对比

特性AMQPMQTTSTOMP
设计目标企业级可靠消息传递轻量级物联网通信简单文本交互
协议类型二进制二进制文本
路由灵活性高(多类型交换器)中(基于主题层级)低(依赖代理实现)
QoS/可靠性事务、持久化、ACK机制QoS 0/1/2分级基础ACK支持
网络适应性稳定网络环境高(适应弱网)一般
典型应用金融交易、ERP系统传感器网络、智能设备Web应用、实时仪表盘
实现复杂度高中低

  • AMQP:适合企业级复杂系统,提供灵活路由和高可靠性。
  • MQTT:为物联网优化,轻量且支持弱网环境。
  • STOMP:适用于简单交互场景,尤其是浏览器与后端的实时通信。

在RabbitMQ等消息中间件中,AMQP通常为默认支持,而MQTT和STOMP需通过插件启用。选择协议时需根据场景需求权衡功能、复杂度与性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/pingmian/78364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习第一篇 线性回归

数据集:公开的World Happiness Report | Kaggle中的happiness dataset2017. 目标:基于GDP值预测幸福指数。(单特征预测) 代码: 文件一:prepare_for_traning.py """用于科学计算的一个库…

Java面试高频问题(29-30)

二十九、全链路压测:数据隔离与流量 关键技术点 1. 流量染色:通过Header注入X-Test-TraceId标识压测流量 2. 影子库表:通过ShardingSphere实现数据隔离 3. 熔断降级:压测流量触发异常时自动切换回生产数据源 数据隔离方案对比 …

Python常用的第三方模块之数据分析【pdfplumber库、Numpy库、Pandas库、Matplotlib库】

【pdfplumber库】从PDF文件中读取内容 import pdfplumber #打开PDF文件 with pdfplumber.open(DeepSeek从入门到精通(20250204).pdf) as pdf:for i in pdf.pages: #遍历页print(i.extract_text()) #extract_text()方法提取内容print(f----------------第{i.page_number}页结束…

长短板理论——AI与思维模型【83】

一、定义 长短板理论思维模型,也被称为木桶原理,是指一只木桶能盛多少水,并不取决于最长的那块木板,而是取决于最短的那块木板。该理论将木桶视为一个整体系统,各个木板代表着系统的不同组成部分或要素,强…

2025蓝桥省赛c++B组第二场题解

前言 这场的题目非常的简单啊,至于为什么有第二场,因为当时河北正在刮大风被迫停止了QwQ,个人感觉是历年来最简单的一场,如果有什么不足之处,还望补充。 试题 A: 密密摆放 【问题描述】 小蓝有一个大箱子&#xff0…

【数据结构与算法】从完全二叉树到堆再到优先队列

完全二叉树 CBT 设二叉树的深度为 h , 若非最底层的其他各层的节点数都达到最大个数 , 最底层 h 的所有节点都连续集中在左侧的二叉树叫做 完全二叉树 . 特点 对任意节点 , 其右分支下的叶子节点的最底层为 L , 则其左分支下的叶子节点的最低层一定是 L 或 L 1 .完全二叉树…

Leetcode:1. 两数之和

题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示…

flume整合kafka

需求一: 启动flume 启动kafka消费者,验证数据写入成功 新增测试数据 需求二: 启动Kafka生产者 启动Flume 在生产者中写入数据

Hbase集群管理与实践

一、HBase集群搭建实战 1.1 环境规划建议 硬件配置基准(以10节点集群为例): 角色CPU内存磁盘网络HMaster4核16GBSSD 200GB(系统盘)10GbpsRegionServer16核64GB124TB HDD(JBOD)25GbpsZooKeeper4核8GBSSD 500GB10Gbps1.2 关键配置项示例(hbase-site.xml) <configu…

STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)

概述 STM32F10x.h 是 STM32F1 系列微控制器的核心头文件&#xff0c;提供了所有外设寄存器的定义和内存映射 一、内存映射 #define PERIPH_BASE ((uint32_t)0x40000000)#define APB1PERIPH_BASE PERIPH_BASE #define APB2PERIPH_BASE (PERIPH_BASE 0x…

QEMU源码全解析 —— 块设备虚拟化(23)

接前一篇文章:QEMU源码全解析 —— 块设备虚拟化(22) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM源码解析与应用》 —— 李强,机械工业出版社 特此致谢! QEMU启动过程中的块设备虚拟化 上一回解析了qcow2格式对应的qcow2_open函数,本回解…

【PCB工艺】推挽电路及交越失真

推挽电路(Push-Pull Circuit) 推挽电路(Push-Pull Circuit) 是一种常用于功率放大、电机驱动、音频放大等场合的电路结构,具有输出对称、效率高、失真小等优点。 什么是推挽电路? 推挽是指:由两种极性相反的器件(如 NPN 和 PNP、NMOS 和 PMOS)交替导通,一个“推”电…

RD电子实验记录本选用贴士A-B-C

传统的实验记录本&#xff0c;令人又爱又恨本 如何挑选电子实验室记录本&#xff08;ELN&#xff09;的品牌/服务商/供应商&#xff1f; 电子实验记录本&#xff0c;又名为ELN&#xff0c;Electronic lab notebook&#xff0c;enotebook&#xff0c;研发电子管理系统&#xf…

Qt实战之将自定义插件(minGW)显示到Qt Creator列表的方法

Qt以其强大的跨平台特性和丰富的功能&#xff0c;成为众多开发者构建图形用户界面&#xff08;GUI&#xff09;应用程序的首选框架。而在Qt开发的过程中&#xff0c;自定义插件能够极大地拓展应用程序的功能边界&#xff0c;让开发者实现各种独特的、个性化的交互效果。想象一下…

java基础之枚举和注解

枚举 简介 枚举&#xff1a;enumeration&#xff0c;jdk1.5中引入的新特性&#xff0c;用于管理和使用常量 入门案例 第一步&#xff1a;定义枚举&#xff0c;这里定义一个动物类&#xff0c;里面枚举了多种动物 public enum AnimalEnum {CAT, // 猫DOG, // 狗PIG // …

2.3java运算符

运算符 1. 算术运算符 算术运算符用于执行基本的数学运算&#xff0c;像加、减、乘、除等。 运算符描述示例加法int a 5 3; // a 的值为 8-减法int b 5 - 3; // b 的值为 2*乘法int c 5 * 3; // c 的值为 15/除法int d 6 / 3; // d 的值为 2%取模&#xff08;取余&…

升级 Spring Boot CLI

&#x1f31f; 升级 Spring Boot CLI 1️⃣ &#x1f504; 通过包管理器升级 使用对应包管理器命令&#xff08;如 brew upgrade&#xff09; 2️⃣ &#x1f4e5; 手动安装升级 遵循 标准安装说明 注意更新 PATH 环境变量移除旧版本路径 &#x1f517; 链接原文&#xff1a…

如何轻松将RS232转为Profibus DP,提升PLC效率?

如何轻松将RS232转为Profibus DP&#xff0c;提升PLC效率&#xff1f; 今天&#xff0c;我们就来聊聊一个工业自动化中常见的应用场景&#xff1a;如何通过兴达易控RS232转Profibus DP网关&#xff0c;实现流量泵与PLC&#xff08;可编程逻辑控制器&#xff09;的通信。这个话…

QT 连接数据库操作(15)

文章目录 一、本章说明二、QT连接云端数据库实现2.1 ODBC软件安装及参数设置2.2 软件代码实现三、项目源码文件一、本章说明 注:本节为【基于STM的环境监测系统(节点+云服务器存储+QT界面设计)】项目第15篇文章,前面已经创建了监测软件的登录窗口,接下来我们将在主窗口实…

linux系统之----命令行参数和环境变量

一、命令行参数 1.main()函数的参数 在C语言中&#xff0c;main函数可以接收命令行参数&#xff0c;其标准形式为&#xff1a; int main(int argc, char *argv[]) {// 程序代码return 0; } 这里我们解释一下&#xff1a; argc&#xff1a;参数个数计数器&#xff08;Argum…