RabbitMQ 教程 | RabbitMQ 入门
👨🏻💻 热爱摄影的程序员
👨🏻🎨 喜欢编码的设计师
🧕🏻 擅长设计的剪辑师
🧑🏻🏫 一位高冷无情的编码爱好者
大家好,我是 DevOps 工程师
欢迎分享 / 收藏 / 赞 / 在看!
这篇 RabbitMQ 教程为学习者提供了全面的内容,从 RabbitMQ 的简介开始,涵盖了消息中间件的概念、RabbitMQ 的安装与使用,以及交换机、队列、路由键等相关概念的介绍。进一步深入,教程探讨了 AMQP 协议、客户端开发向导,以及消息的发送和消费方式。同时,学习者还可以了解消息传输保障、高级特性如死信队列、延迟队列、优先级队列、RPC 实现等。此外,教程还涵盖了 RabbitMQ 的管理、配置、运维、监控和集群管理等重要主题,帮助学习者充分掌握 RabbitMQ 的应用。整篇教程丰富内容详实,适合初学者和有经验的开发者参考学习。
全篇共 11 章,9 万余字。本文:第2章 RabbitMQ 入门。
第2章 RabbitMQ 入门
2.1 相关概念介绍
在本节中,我们将介绍与 RabbitMQ 相关的一些重要概念,这些概念对于理解 RabbitMQ 的工作原理非常重要。
2.1.1 生产者和消费者
在 RabbitMQ 中,生产者和消费者是两个关键的角色,它们协同工作来实现消息的发布和消费。
生产者(Producer): 生产者是消息的发送者,负责向 RabbitMQ 发送消息。生产者将消息发布到交换机(Exchange),交换机再根据消息的路由键(Routing Key)将消息路由到一个或多个队列(Queue)。生产者不需要知道消息最终将被哪个消费者接收,它只关心将消息发送到正确的交换机,并指定合适的路由键。
在发送消息之前,生产者需要和 RabbitMQ 建立连接,并创建一个通道(Channel)来进行消息的发布。通道是在连接上打开的一个轻量级的会话,通过通道可以避免频繁地打开和关闭连接,从而提高消息的传输效率。
通常,生产者会向一个特定的交换机发送消息,交换机根据一定的规则将消息路由到队列中,然后消费者从队列中接收消息进行处理。生产者可以根据业务需求决定消息的发送频率和内容。
示例代码(使用 Python 的 pika 库):
import pika# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()# 声明一个名为"hello"的队列
channel.queue_declare(queue='hello')# 发送消息
channel.basic_publish(exchange='',routing_key='hello',body='Hello, RabbitMQ!')print(" [x] Sent 'Hello, RabbitMQ!'")# 关闭连接
connection.close()
消费者(Consumer): 消费者是消息的接收者,负责从队列中获取消息并进行处理。消费者需要与 RabbitMQ 建立连接,并订阅(Consume)一个或多个队列来接收消息。
一旦消息被发送到队列中,消费者就可以从队列中获取消息,并对消息进行处理。处理方式可以是执行一段代码、存储到数据库、发送到其他系统等,这取决于消费者的业务逻辑。
消费者在接收消息后,通常会给 RabbitMQ 发送一个确认(Ack)信号,告知 RabbitMQ 消息已经被成功处理,RabbitMQ 可以删除该消息。这样可以确保消息不会丢失,并保证消息传递的可靠性。
示例代码(使用 Python 的 pika 库):
import pikadef callback(ch, method, properties, body):print(" [x] Received %r" % body)# 消息处理逻辑,例如保存到数据库或执行其他操作ch.basic_ack(delivery_tag=method.delivery_tag)# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()# 声明一个名为"hello"的队列
channel.queue_declare(queue='hello')# 告诉RabbitMQ当收到消息后,调用callback函数进行处理
channel.basic_consume(queue='hello', on_message_callback=callback)print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
生产者和消费者的协作使得 RabbitMQ 能够在分布式系统中高效地传递消息,实现了解耦和异步处理,提高了系统的可扩展性和可靠性。
2.1.2 队列
在 RabbitMQ 中,队列(Queue)是消息的存储和传递单元,是 RabbitMQ 的核心组件之一。队列是一个有名字的管道,用于保存消息,生产者通过交换机(Exchange)将消息发送到队列,消费者则从队列中接收和处理消息。
以下是 RabbitMQ 队列的一些关键特性和介绍:
- 有名字:每个队列在 RabbitMQ 中都有一个唯一的名称,生产者和消费者通过名称来访问和使用队列。
- 持久性:队列可以被声明为持久化的,这意味着在 RabbitMQ 服务器重启后,队列依然存在,其中的消息也不会丢失。持久化可以确保消息的可靠传递。
- 非持久性:如果队列被声明为非持久化的,在 RabbitMQ 服务器重启后,该队列将会被删除,其中的消息也会丢失。
- 先进先出:队列中的消息按照先进先出(FIFO)的顺序进行处理,即最先进入队列的消息会最先被消费者接收。
- 自动删除:队列可以被声明为自动删除的,在最后一个消费者断开连接后,该队列将会被自动删除,用于临时队列的场景。
- 绑定到交换机:队列通过绑定到交换机来获取消息。交换机根据一定的规则(根据路由键)将消息路由到相应的队列。
- 消息确认:消费者接收到消息后,可以向 RabbitMQ 发送确认信号(ACK)来告知 RabbitMQ 消息已经被成功处理。如果消费者不发送 ACK,RabbitMQ 会认为消息没有被成功处理,并将其重新发送给其他消费者或者继续存储在队列中。
- 消息持久性:消息也可以被声明为持久化的,这样即使 RabbitMQ 服务器重启,消息也不会丢失。当消息被发送到持久化的队列中,同时消息本身也被声明为持久化时,才能保证消息的持久性。
在 RabbitMQ 中,队列是一种非常重要的组件,它实现了消息传递的核心功能。通过合理的使用队列的特性,可以确保消息的可靠传递和处理,构建高性能、可靠的消息传递系统。
2.1.3 交换机、路由键、绑定
在 RabbitMQ 中,交换机(Exchange)、路由键(Routing Key)和绑定(Binding)是实现消息路由的关键概念。它们一起协同工作,将生产者发送的消息从交换机路由到合适的队列中,供消费者进行处理。
- 交换机(Exchange): 交换机是消息的接收和路由中心,它接收生产者发送的消息,并根据消息的路由键将消息路由到一个或多个队列。RabbitMQ 支持多种类型的交换机,包括直接(Direct)交换机、扇形(Fanout)交换机、主题(Topic)交换机和头部(Headers)交换机。每种交换机根据不同的路由策略将消息路由到不同的队列。
- 路由键(Routing Key): 路由键是生产者在发送消息时指定的一个字符串值。生产者通过路由键告诉 RabbitMQ 消息的路由规则。不同类型的交换机使用路由键的方式不同。对于直接交换机,路由键与队列的绑定键(Binding Key)必须完全匹配;对于扇形交换机,路由键会被忽略,消息会被广播到所有绑定到该交换机的队列;而对于主题交换机,路由键可以使用通配符进行模糊匹配。
- 绑定(Binding): 绑定是交换机和队列之间的关联关系。在 RabbitMQ 中,消费者创建一个绑定,将队列绑定到特定的交换机,并指定绑定键(Binding Key)。绑定键的含义取决于交换机的类型。当一个消息发送到交换机时,交换机会根据消息的路由键和绑定的绑定键将消息路由到合适的队列。
综合起来,消息从生产者发送到交换机,交换机根据消息的路由键和绑定的绑定键将消息路由到相应的队列。消费者绑定到队列上,从队列中接收和处理消息。
下面是交换机、路由键和绑定之间的关系示意图:
Producer --> Message (with Routing Key) --> Exchange --> Binding (with Binding Key) --> Queue --> Consumer
总结: 交换机、路由键和绑定是 RabbitMQ 中实现消息路由的核心机制。生产者通过路由键指定消息的路由规则,交换机根据路由规则将消息路由到相应的队列中,供消费者进行处理。这种灵活的消息路由机制使得 RabbitMQ 能够适应不同的消息传递场景。
2.1.4 交换机类型
RabbitMQ 支持多种类型的交换机(Exchange),每种类型的交换机根据不同的路由策略将消息路由到绑定到它的队列中。下面介绍 RabbitMQ 中常见的交换机类型:
- 直接交换机(Direct Exchange): 直接交换机是最简单的交换机类型。它将消息的路由键与队列的绑定键(Binding Key)进行完全匹配,只有当路由键和绑定键完全相同时,才将消息路由到对应的队列中。可以理解为一种点对点的消息路由方式。如果消息的路由键没有与任何队列的绑定键匹配,那么消息将会被丢弃。直接交换机的路由规则是最严格的。
- 扇形交换机(Fanout Exchange): 扇形交换机是一种广播式的交换机。它会将收到的消息广播到所有绑定到它上面的队列,忽略消息的路由键。因此,使用扇形交换机时,无需指定绑定键。适用于需要将消息同时发送给多个消费者的场景。
- 主题交换机(Topic Exchange): 主题交换机是一种更加灵活的交换机类型。它将消息的路由键与队列的绑定键进行模糊匹配,支持通配符匹配。主题交换机的绑定键可以是一个由点号(.)分隔的单词列表,可以包含两种通配符:*表示匹配一个单词,#表示匹配零个或多个单词。使用主题交换机时,可以根据消息的路由键模式将消息路由到满足条件的队列中。
- 头部交换机(Headers Exchange): 头部交换机不使用路由键来路由消息,而是使用消息的头部信息进行匹配。它通过消息头部的键值对来决定消息是否路由到队列。头部交换机的匹配规则比较复杂,通常较少使用。
根据不同的业务场景和消息路由需求,可以选择合适的交换机类型。通过灵活地使用交换机和绑定,可以构建出强大的消息传递系统,实现消息的精确路由和广播传递。
2.1.5 RabbitMQ 运转流程
了解 RabbitMQ 的运转流程,包括生产者发送消息到交换机,交换机将消息路由到队列,消费者从队列中取出并处理消息。
以下是 RabbitMQ 的基本运转流程:
- 生产者发送消息:
-
- 生产者(Producer)创建一个与 RabbitMQ 服务器的连接,并打开一个通道(Channel)。
- 生产者声明一个交换机(Exchange)并将消息发送给该交换机。生产者需要指定交换机的名称、类型和路由键(Routing Key)。
- 交换机根据指定的路由键将消息路由到一个或多个队列(Queue)中。
- 消费者接收消息:
-
- 消费者(Consumer)创建一个与 RabbitMQ 服务器的连接,并打开一个通道。
- 消费者声明一个队列,并将队列绑定到指定的交换机。消费者需要指定队列的名称、交换机的名称、绑定键(Binding Key)以及其他可选的参数。
- 消费者通过订阅(Consume)队列来接收消息。
- 消息路由和传递:
-
- 当生产者发送消息时,交换机根据消息的路由键和绑定的绑定键将消息路由到相应的队列中。
- 队列中的消息将按照先进先出(FIFO)的顺序被消费者接收和处理。
- 消息确认:
-
- 消费者在接收到消息并处理完成后,可以向 RabbitMQ 发送确认信号(ACK),告知 RabbitMQ 消息已经被成功处理。
- 如果消费者不发送 ACK,RabbitMQ 会将消息重新发送给其他消费者或继续存储在队列中。
- 持久性和高可用性:
-
- RabbitMQ 支持队列和消息的持久化,确保消息在服务器重启后不会丢失。
- 可以通过设置镜像队列和集群等机制来实现 RabbitMQ 的高可用性。
- 其他特性:
-
- RabbitMQ 还支持消息的过期时间(TTL)、死信队列、延迟队列、优先级队列等高级特性。
在 RabbitMQ 中,一个生产者与 RabbitMQ 建立连接后,通常会创建多个 Channel 信道。每个 Channel 是一个独立的会话通道,用于进行消息的发送和接收。通过创建多个 Channel,生产者可以并行发送多个消息(在不同的 Channel 上发送不同的消息,或者在同一个 Channel 上发送多条消息),从而提高消息的处理效率和吞吐量。
每个连接可以创建多个 Channel,而每个 Channel 只属于一个连接。这样的设计可以在一个连接上同时进行多个操作,而不需要等待之前的操作完成。同时,每个 Channel 之间是相互独立的,一个 Channel 的异常不会影响其他 Channel 的正常运行。
生产者与 RabbitMQ 建立的连接可以对应一个或多个 Virtual Host (vhost)。
Virtual Host 是 RabbitMQ 中用于进行逻辑隔离的概念,它允许在单个 RabbitMQ 服务器上创建多个独立的逻辑消息环境。每个 Virtual Host 类似于一个独立的消息代理,拥有自己的交换机、队列、绑定等资源。这样可以使不同的应用或服务在同一台 RabbitMQ 服务器上运行,互相之间不会干扰。
当生产者与 RabbitMQ 建立连接时,可以选择连接到指定的 Virtual Host。如果没有指定 Virtual Host,默认情况下生产者连接到名为 "/" 的默认 Virtual Host。然后,生产者可以在该 Virtual Host 中进行消息的生产和发送。
在一个 RabbitMQ 服务器上可以配置多个 Virtual Host,因此生产者可以建立多个连接,并分别连接到不同的 Virtual Host,以便将消息发送到不同的逻辑环境中。
消费者与 RabbitMQ 建立连接后,消费消息通常是根据队列名称直接与队列进行交互,而不是直接与交换机交互。在 RabbitMQ 中,生产者将消息发送到交换机,然后交换机根据绑定规则将消息路由到相应的队列。消费者需要消费队列中的消息,因此它会与特定的队列建立连接,并从队列中取出消息进行消费。
消费者通过创建一个或多个 Channel 信道,然后通过这些 Channel 与指定的队列建立连接。然后,消费者可以通过消费队列的操作来从队列中取出消息,并进行处理。
通过与队列直接交互,消费者可以按照自己的消费速率从队列中获取消息,这样可以更好地控制消息的消费过程,避免消息的丢失或堆积。同时,队列还可以作为消息的缓冲区,帮助消费者处理可能出现的瞬时流量高峰。这样的设计使得消息的消费过程更加灵活和可靠。
总结: RabbitMQ 通过交换机、队列和绑定的灵活组合,实现了高效可靠的消息传递。生产者将消息发送到交换机,交换机根据消息的路由键将消息路由到队列中,然后消费者从队列中接收消息进行处理。通过消息确认机制,确保消息的可靠处理。同时,RabbitMQ 支持多种高级特性,使得消息传递更加灵活和强大。
2.2 AMQP 协议介绍
AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是一种开放标准的消息传递协议,旨在实现跨网络的高性能、高可靠性的消息传递。它提供了一种灵活的消息传递模型,适用于各种异步消息传递场景,如消息队列、消息中间件和消息路由。
以下是 AMQP 协议的主要特点和介绍:
- 高度可扩展:AMQP 协议支持多种交换机和队列类型,以及灵活的路由规则,可以根据不同的业务需求进行定制和扩展。这使得 AMQP 协议适用于各种规模和复杂度的应用场景。
- 异步消息传递:AMQP 协议采用异步消息传递模型,生产者和消费者之间不需要直接建立连接,而是通过交换机和队列来中转消息。这样可以实现解耦和灵活的消息传递。
- 高可靠性:AMQP 协议支持消息的持久化,可以确保消息在服务器重启后不会丢失。同时,它提供了消息确认机制,消费者可以向服务器发送确认信号,告知服务器消息已经被成功处理。
- 跨平台支持:AMQP 协议是一种开放标准,得到了众多厂商和社区的支持。因此,它可以在不同的编程语言和操作系统上进行实现,实现跨平台的消息传递。
- 安全性:AMQP 协议支持身份验证和加密传输,可以确保消息在传输过程中的安全性。
- 多种消息传递模式:AMQP 协议支持多种消息传递模式,包括点对点(Point-to-Point)和发布-订阅(Publish-Subscribe)等。这使得它可以适应不同的消息传递需求。
- 灵活的路由规则:AMQP 协议支持多种交换机类型,可以根据消息的路由键和绑定键将消息路由到相应的队列中。这使得消息传递更加灵活和精确。
AMQP 协议是一种非常强大和通用的消息传递协议,它在分布式系统中广泛应用于异步消息传递场景。RabbitMQ 作为 AMQP 协议的实现之一,提供了高性能、高可靠性的消息传递服务,并支持丰富的特性和灵活的消息传递模型。
2.2.1 AMQP 生产者流转过程
AMQP 生产者(Producer)流转过程描述了生产者如何将消息发送到 RabbitMQ 服务器的过程。以下是 AMQP 生产者流转过程的详细步骤:
- 建立连接:生产者首先与 RabbitMQ 服务器建立一个网络连接。这是通过 TCP/IP 连接到 RabbitMQ 服务器的默认端口(5672)来实现的。
- 创建通道:在建立连接后,生产者需要在该连接上创建一个通道(Channel)。通道是在连接上打开的一个轻量级会话,所有的消息传递操作都是在通道上进行的。通道的创建可以通过 AMQP 协议中的 channel.open 命令实现。
- 声明交换机(Exchange):生产者需要声明一个交换机,用于发送消息。交换机是消息的接收和路由中心,它根据消息的路由键将消息路由到一个或多个队列。交换机的声明可以通过 AMQP 协议中的 exchange.declare 命令实现。
- 发布消息:生产者使用 channel.basicPublish 方法将消息发送到交换机。在消息中,生产者需要指定交换机的名称、路由键以及消息的主体(Payload)。
- 路由规则:交换机根据消息的路由键将消息路由到相应的队列。具体的路由规则取决于交换机的类型。如果找不到与消息路由键匹配的队列,根据交换机的规则,消息可能会被丢弃或存储在交换机中。
- 消息持久化(可选):生产者可以选择将消息设置为持久化的。通过在消息的属性中设置 deliveryMode 为 2,可以确保消息在服务器重启后不会丢失。
- 关闭通道和连接:当生产者完成消息发送后,可以选择关闭通道和连接,释放资源。关闭通道和连接是通过 AMQP 协议中的 channel.close 和 connection.close 命令来实现的。
AMQP 生产者流转过程包括建立连接、创建通道、声明交换机、发布消息等步骤。生产者通过交换机将消息发送到 RabbitMQ 服务器,并根据消息的路由键将消息路由到相应的队列中。生产者可以选择设置消息的持久性,确保消息在服务器重启后不会丢失。完成消息发送后,生产者可以选择关闭通道和连接,释放资源。
2.2.2 AMQP 消费者流转过程
AMQP 消费者(Consumer)流转过程描述了消费者如何从 RabbitMQ 服务器接收和处理消息的过程。以下是 AMQP 消费者流转过程的详细步骤:
- 建立连接:消费者首先与 RabbitMQ 服务器建立一个网络连接。这是通过 TCP/IP 连接到 RabbitMQ 服务器的默认端口(5672)来实现的。
- 创建通道:在建立连接后,消费者需要在该连接上创建一个通道(Channel)。通道是在连接上打开的一个轻量级会话,所有的消息传递操作都是在通道上进行的。通道的创建可以通过 AMQP 协议中的 channel.open 命令实现。
- 声明队列:消费者需要声明一个队列,用于接收消息。队列的声明可以通过 AMQP 协议中的 queue.declare 命令实现。消费者需要指定队列的名称、是否持久化、是否独占等参数。
- 绑定队列和交换机:消费者需要将队列绑定到一个或多个交换机上,以便从交换机接收消息。绑定可以通过 AMQP 协议中的 queue.bind 命令实现。消费者需要指定交换机的名称、绑定键(Binding Key)等参数。
- 订阅队列:消费者使用 channel.basicConsume 方法订阅队列,开始接收消息。在订阅时,消费者可以指定消费者标签(Consumer Tag)和消息回调函数。
- 消息回调:当队列中有消息到达时,RabbitMQ 服务器会将消息传递给消费者的消息回调函数。消费者可以在回调函数中处理收到的消息。
- 消息确认(可选):消费者在成功处理消息后,可以选择向 RabbitMQ 服务器发送确认信号(ACK),告知服务器消息已经被成功处理。消息确认可以通过 AMQP 协议中的 basic.ack 命令实现。如果消费者没有发送确认信号,RabbitMQ 会认为消息没有被成功处理,并将其重新发送给其他消费者或者继续存储在队列中。
- 关闭通道和连接:当消费者不再需要接收消息时,可以选择关闭通道和连接,释放资源。关闭通道和连接是通过 AMQP 协议中的 channel.close 和 connection.close 命令来实现的。
AMQP 消费者流转过程包括建立连接、创建通道、声明队列、绑定队列和交换机、订阅队列、消息回调等步骤。消费者通过订阅队列接收消息,当队列中有消息到达时,RabbitMQ 服务器将消息传递给消费者的消息回调函数。消费者可以选择发送确认信号来确认消息的处理结果。完成消息接收和处理后,消费者可以选择关闭通道和连接,释放资源。
2.2.3 AMQP命令概览
AMQP(Advanced Message Queuing Protocol)是一个复杂的协议,用于在消息传递系统中传输消息。它包含许多不同的命令和方法,用于管理连接、通道、交换机、队列以及消息的传递等操作。以下是 AMQP 命令的概览,列出了一些常见的AMQP命令和方法:
- 连接管理命令:
-
- connection.start:启动连接,用于协商协议版本和进行身份验证。
- connection.secure:在安全连接上进行身份验证。
- connection.open:打开一个新的连接。
- connection.close:关闭当前连接。
- 通道管理命令:
-
- channel.open:打开一个新的通道。
- channel.close:关闭当前通道。
- 交换机管理命令:
-
- exchange.declare:声明一个交换机。
- exchange.delete:删除一个交换机。
- 队列管理命令:
-
- queue.declare:声明一个队列。
- queue.bind:将队列绑定到一个交换机上。
- queue.unbind:解绑队列和交换机的绑定关系。
- queue.purge:清空队列中的所有消息。
- queue.delete:删除一个队列。
- 消息传递命令:
-
- basic.publish:将消息发送到交换机。
- basic.consume:订阅队列,接收消息。
- basic.get:从队列中获取单个消息,非订阅方式。
- basic.ack:确认收到消息,告知服务器消息已被处理。
- basic.nack:否定消息,告知服务器消息未被成功处理。
- basic.reject:拒绝消息,告知服务器不接受消息。
- 事务命令:
-
- tx.select:开启事务。
- tx.commit:提交事务。
- tx.rollback:回滚事务。
- 其他命令:
-
- confirm.select:启用发布确认模式,用于确认消息是否被正确接收和处理。
- confirm.select-ok:确认发布确认模式已经启用。
以上仅列出了一部分 AMQP 命令和方法,实际上 AMQP 协议有更多的命令和参数,用于支持复杂的消息传递和系统管理操作。在使用 AMQP 的客户端库时,这些命令和方法会被封装成相应的API函数,开发者可以通过这些API函数来实现对 RabbitMQ 服务器的操作。
2.3 小结
本章介绍了 RabbitMQ 的入门知识,包括相关概念的介绍和 AMQP 协议的简要介绍。在下一章中,我们将学习 RabbitMQ 客户端的开发向导,包括如何连接 RabbitMQ 服务器、使用交换机和队列、发送和消费消息等。
相关文章:

RabbitMQ 教程 | RabbitMQ 入门
👨🏻💻 热爱摄影的程序员 👨🏻🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…...

【雕爷学编程】MicroPython动手做(10)——零基础学MaixPy之神经网络KPU2
KPU的基础架构 让我们回顾下经典神经网络的基础运算操作: 卷积(Convolution):1x1卷积,3x3卷积,5x5及更高的卷积 批归一化(Batch Normalization) 激活(Activate) 池化&…...
BUG分析以及BUG定位
一般来说bug大多数存在于3个模块: 1、前台界面,包括界面的显示,兼容性,数据提交的判断,页面的跳转等等,这些bug基本都是一眼可见的,不太需要定位,当然也不排除一些特殊情况…...

Day46 算法记录| 动态规划 13(子序列)
这里写目录标题 300.最长递增子序列 674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 视频解析: 第一层for循环遍历每一个元素, ------- 第二层for循环找到当前元素前面有几个小于该值的元素 结尾需要统计最多的个数 class Solution {pu…...

结构型-桥接模式(Bridge Pattern)
概述 桥接模式(Bridge Pattern)是一种结构型设计模式,将抽象部分和实现部分分离,使它们可以独立地变化。桥接模式通过将继承关系转化为关联关系,将抽象部分和实现部分分离开来,从而使它们可以独立地变化。…...

基于小波哈尔法(WHM)的一维非线性IVP测试问题的求解(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 💥1 概述 小波哈尔法(WHM)是一种求解一维非线性初值问题(IVP)的数值方法。它基于小波分析的思想…...

前端(Electron Nodejs)如何读取本地配置文件
使用electron封装了前端界面之后,最终打包为一个客户端(exe)。但是,最近项目组内做CS(c开发)的,想把所有的配置都放进安装目录的配置文件中(比如config.json)。这做法&am…...

没有 telnet 不能测试端口?容器化部署最佳的端口测试方式
写在前面 生产中遇到,整理笔记在容器中没有 telnet ,如何测试远程端口理解不足小伙伴帮忙指正 他的一生告诉我们,不能自爱就不能爱人,憎恨自己也必憎恨他人,最后也会像可恶的自私一样,使人变得极度孤独和悲…...

漏洞发现-BurpSuite插件-Fiora+Fastjson+Shiro
BurpSuite插件安装 插件:Fiora Fiora是LoL中的无双剑姬的名字,她善于发现对手防守弱点,实现精准打击。该项目为PoC框架nuclei提供图形界面,实现快速搜索、一键运行等功能,提升nuclei的使用体验。 该程序即可作为burp插…...

Elasticsearch-倒排索引
Elasticsearch和Lucene的关系 Lucene 是一个开源、免费、高性能、纯 Java 编写的全文检索引擎,可以算作是开源领域最好的全文检索工具包。ElasticSearch 是基于Lucene实现的一个分布式、可扩展、近实时性的高性能搜索与数据分析引擎。 Lucene索引层次结构 Lucene的…...

pagehelper与mybatis-plus冲突的解决办法
背景: springcloud项目开发新功能时因想使用mybatis-plus,原有功能只使用了mybatis,但在开发时发现某个公共模块使用了com.github.pagehelper,且很多模块都集成了该模块依赖(为了保证原有功能不发生问题,…...

解决使用Timer时出现Task already scheduled or cancelled异常的问题
在使用java.util.Timer和java.util.TimerTask执行定时任务时,如果在调用Timer的schedule或scheduleAtFixedRate方法时,报错如下: java.lang.IllegalStateException: Task already scheduled or cancelled 说明当前Timer对象已经执行结束或被取…...

P1175 后缀表达式
题意 传送门 P1175 表达式的转换 题解 编码运算符的优先级,线性复杂度将中缀表达式转换为后缀表达式。为了方便输出,可以用类似对顶栈的结构,初始时右侧栈为后缀表达式;对于每一步计算,右侧栈不断弹出数字到左侧栈&…...

【HashMap】49. 字母异位词分组
49. 字母异位词分组 解题思路 创建一个哈希容器 key是每一个字母异位词 排序之后的词 List是所有的字母异位词因为所有的字母异位词排序之后的结果都是一样的增强for循环遍历字符串数组将每一个字符串转换为字符数组因为字母异位词排序之后 都是一样的将排序之后的字符数组 转…...

golang实现多态
Go 通过接口来实现多态。在 Go 语言中,我们是隐式地实现接口。一个类型如果定义了接口所声明的全部方法,那它就实现了该接口。现在我们来看看,利用接口,Go 是如何实现多态的。 package mainimport "fmt"type Income in…...

formatter的用法,深拷贝, Object.assign 方法实战。
1. :formatter的用法 :formatter 接受一个函数作为参数,这个函数有三个参数:row,column 和 cellValue。row 是当前行的数据,column 是当前列的数据,cellValue 是当前单元格的值。 <el-table-column prop"SYS…...

Windows上安装和使用git到gitoschina和github上_亲测
Windows上安装和使用git到gitoschina和github上_亲测 git介绍与在windows上安装创建SSHkey在gitoschina使用 【git介绍与在windows上安装】 Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 相关介绍可以参考 <百度百科>…...

MATLAB算法实战应用案例精讲-【深度学习】预训练模型GPTXLNet
目录 GPT 1. 介绍 1.1 GPT的动机 2. 模型结构 3. GPT训练过程 3.1 无监督的预训练...

Spring data JPA常用命令
简介 Spring Data JPA是Spring框架的一部分,它提供了一个简化的方式来与关系型数据库进行交互。JPA代表Java持久化API,它是Java EE规范中定义的一种对象关系映射(ORM)标准。Spring Data JPA在JPA的基础上提供了更高级的抽象&…...

Excel的使用
1.EXCEL诞生的意义 1.1 找到想要的数据 1.2 提升输入速度 2.数据分析与可视化操作 目的是提升数据的价值和意义 3.EXCEL使用的内在意义和外在形式 4.EXCEL的价值 4.1 解读及挖掘数据价值 4.2 协作板块 4.3 展示专业度 4.4 共享文档内容 5.人的需求》》软件功能...

大数据课程D4——hadoop的MapReduce
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解MapReduce的作用和特点; ⚪ 掌握MapReduce的组件; ⚪ 掌握MapReduce的Shuffle; ⚪ 掌握MapReduce的小文件问题; ⚪ 掌握MapReduce的压缩机制; ⚪ 掌握MapReduce的推测执行机制…...

java策略模式
在Java中,策略模式(Strategy Design Pattern)用于定义一系列算法,并将每个算法封装成单独的类,使得它们可以互相替换,让客户端在使用算法时不需要知道具体的实现细节。策略模式是一种行为型设计模式&#x…...

Vue2封装自定义全局Loading组件
前言 在开发的过程中,点击提交按钮,或者是一些其它场景总会遇到Loading加载框,PC的一些UI库也没有这样的加载框,无法满足业务需求,因此可以自己自定义一个,实现过程如下。 效果图 如何封装? 第…...

docker 搭建jenkins
1、拉取镜像 docker pull jenkins/jenkins:2.4162、创建文件夹 mkdir -p /home/jenkins_mount chmod 777 /home/jenkins_mount3、运行并构建容器 docker run --restartalways -d -p 10240:8080 -p 10241:50000 -v /home/jenkins_mount:/var/jenkins_home -v /etc/localtime:…...

【Docker】Docker 部署 Mysql 并设置数据持久化
文章目录 1. Docker持久化MySQL2. 测试删除MySQL容器后新建容器,数据还在不在3. 参考资料 我们使用Docker的目的就是图它方便下载部署,不用常规的经历下载、配置、安装等等繁琐的步骤。但是与此同时Docker也存在一些缺点,像删除容器后数据就都…...

【ARM 常见汇编指令学习 5 -- arm64汇编指令 wzr 和 xzr】
文章目录 ARM64 zero registerARMv8 zero 寄存器的背景xzr 在寄存器读写操作中的使用 上篇文章:ARM 常见汇编指令学习 4 – ARM64 比较指令 cbnz 与 b.ne 区别 下篇文章:ARM 常见汇编指令学习 6 - bic(位清除), orr(位或), eor(异或) ARM64 zero registe…...

4.4 成员变量与局部变量的区别有哪些?
文章目录 4.5 创建一个对象用什么运算符?对象实体与对象引用有何不同?4.6 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?4.7 构造方法有哪些特性?4.8 在调用子类构造方法之前会先调用父类没有参数的构造方法…...

学生管理系统-03项目案例(3)
一、用户列表 1、编写api接口 //导入封装后的axios import {instance} from /util/request export default{getUsers:params>instance.get(/users/getUsers,{params}) } 2、表格渲染 <template><el-card><!-- 当el-table元素中注入data对象数组后&#x…...

Banana Pi BPI-KVM – 基于 Rockchip RK3568 SoC 的 KVM over IP 解决方案
Banana Pi 已经开始开发基于 Rockchip RK3568 SoC 的 BPI-KVM 盒,但它不是迷你 PC,而是 KVM over IP 解决方案,旨在远程控制另一台计算机或设备,就像您在现场一样,例如能够打开和关闭连接的设备、访问 BIOS 等。 商业…...

面试:Spring Cloud和Kubernetes的优缺点
Spring Cloud 优点 spring cloud是从应用框架层面解决微服务架构的一部分,如网关、服务发现、负载平衡、配置管理、指标跟踪等,易于Java开发者上手。 缺点 缺乏打包、持续集成、伸缩、高可用和自我修复等,且局限于Java平台。 Kubernetes …...