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

双网卡如何配置DNS?我是一个仅主机模式配置静态(static)IP、一个NET或桥接(dhcp获取)
目录 一、所有主机初始化 二、135、136服务器,部署DNS调度服务器 1、更改主机主从DNS服务器的主机名称 2、安装bind软件、修改主配置文件 3、修改区域配置文件 4、修改数据文件 5、启动named服务、修改网卡信息 6、解析 7、双网卡的话记得注释以下内容、注…...

Android10: 动态隐藏导航栏和状态栏总结
(1)全屏相关设置 //(1)主题添加 <item name"android:windowFullscreen">true</item>//(2)setContentView之前添加 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCRE…...

roop 视频换脸
roop: one click face swap. 只用一张人脸图片,就能完成视频换脸。 项目地址: https://github.com/s0md3v/roopColab 部署: https://github.com/dream80/roop_colab 本文是本地部署的实践记录。 环境基础 OS: Ubuntu 22.04.2 LTSKernel: 5…...

Java类集框架(一)
目录 1.Collection集合接口 2.List 接口 (常用子类 ArrayList ,LinkedList,Vector) 3.Set 集合 接口(常用子类 HashSet LinkedHashSet,TreeSet) 4.集合输出(iterator , Enumeration) 1.Collection集合接口 Collection是集合中最大父接口,在接口中定义了核心的…...

Jsp+Ssh+Mysql实现的简单的企业物资信息管理系统项目源码附带视频指导运行教程
由jspssh(springstruts2mysql)实现的企业物资信息管理系统,系统功能比较简单,实现了基本的管理员、操作员等用户管理、物品分类管理、物品管理、入库管理、出库管理、库存预警、客户管理、供应商管理等基本功能需要的可以联系我分…...

【Spring】深究SpringBoot自动装配原理
文章目录 前言1、main入口2、SpringBootApplication3、EnableAutoConfiguration4、AutoConfigurationImportSelector4.1、selectImports()4.2、getAutoConfigurationEntry()4.3、getCandidateConfigurations()4.4、loadFactoryNames() 5、META-INF/spring.factories6、总结 前言…...

阿里云负载均衡SLB网络型NLB负载均衡架构性能详解
阿里云网络型负载均衡NLB是阿里云推出的新一代四层负载均衡,支持超高性能和自动弹性能力,单实例可以达到1亿并发连接,帮您轻松应对高并发业务。网络型负载均衡NLB具有超强性能、自动弹性伸缩、高可用、TCPSSL卸载、多场景流量分发和丰富的高级…...

JavaScript学习 -- SM4算法应用实例
SM4算法,也被称为国密算法,是中国公布的一种高效且安全的对称加密算法。在JavaScript中,我们可以通过使用CryptoJS库来实现SM4算法的加密和解密。本篇博客将为您介绍如何在JavaScript中使用SM4算法,并提供一个实际的案例。 首先&…...

【JVM】什么是双亲委派机制
文章目录 1、类加载机制2、双亲委派模型2.1、介绍2.2、为什么需要双亲委派2.3、源码解析 3、破坏双亲委派3.1、介绍3.2、破坏实现3.3、破坏双亲委派的例子 4、线程上下文类加载器 1、类加载机制 类加载阶段分为加载、连接、初始化三个阶段,而加载阶段需要通过类的全…...

网络安全 Day24-select高级用法和多表连接
select高级用法和多表连接 1. select 多子句单表高级实践1.1 select 多子句高级语法1.2 聚合函数1.3 group by 实践1.4 having 筛选1.5 order by 排序1.6 limit 2. 多表连接 1. select 多子句单表高级实践 1.1 select 多子句高级语法 where 和 having 区别是后者是分组后进行…...

JUC并发编程之volatile详解
目录 1. volatile 1.1 volatile关键字的作用 1.1.1 变量可见性 1.1.2 禁止指令重排序 1.2 volatile可见性案例 1.3 volatile非原子性案例 1.4 volatile 禁止重排序 1.5 volatile 日常使用场景 送书活动 1. volatile 在并发编程中,多线程操作共享的变量时&a…...

swing布局详解
1. 布局管理器接口 (1)说明 布局管理器接口为LayoutManager和LayoutManager2,LayoutManager2是LayoutManager的子类。 (2)常用方法 方法描述LayoutManageraddLayoutComponent(String name, Component comp) removeL…...

el-table某一列嵌套使用el-popover,使用click触发,导致页面下拉框组件无法触发弹框关闭(解决办法)
在弹框触发的方法里加上document.body.click() 即可 尝试了很多其他的方法都没用,只有这个解决了 完整代码: <el-select change"sourceChange" clearable ><el-optionv-for"option in list1":key"option.code":…...

正泰电力携手图扑:VR 变电站事故追忆反演
VR(Virtual Reality,虚拟现实)技术作为近年来快速发展的一项新技术,具有广泛的应用前景,支持融合人工智能、机器学习、大数据等技术,实现更加智能化、个性化的应用。在电力能源领域,VR 技术在高性能计算机和专有设备支…...

报错 -bash: wget: command not found
1、报错 -bash: wget: command not found 可以重装 wget 工具: 卸载 wget 工具 yum remove wget下载 wget 工具 yum -y install wget最后尝试 wget “url” 又OK了,一般是原来的wget初始化有文件损坏造成的。...

HashMap扩容和Redis中Dict 扩容
扩容时机: Hash Map:要在某个临界点进行扩容处理,该临界点就是HashMap中元素的数量在数值上等于threshold(table数组长度*加载因子) Dict: 当每次新增键值对的时 , 会检测 负载因子(LoadFactor) , 判断以…...

【Redis】内存数据库Redis进阶(Redis持久化)
目录 分布式缓存 Redis 四大问题Redis 持久化RDB (Redis DataBase)RDB执行时机RDB启动方式——save指令save指令相关配置save指令工作原理save配置自动执行 RDB启动方式——bgsave指令bgsave指令相关配置bgsave指令工作原理 RDB三种启动方式对比RDB特殊启动形式RDB优点与缺点 A…...

在PHP8中检测数据类型-PHP8知识详解
在PHP 8中,可以使用多种方法来检测数据类型。以下是常用的四种方法:使用 gettype() 函数、使用 is_* 系列函数、使用 get_debug_type() 函数、使用 get_class() 函数。 一、使用 gettype() 函数 gettype() 函数返回给定变量的数据类型。例如:…...

amoeba实现MySQL读写分离
amoeba实现MySQL读写分离 准备环境:主机A和主机B作主从配置,IP地址为192.168.131.129和192.168.131.130,主机C作为中间件,也就是作为代理服务器,IP地址为192.168.131.136。三台服务器操作系统为RHEL6.4 x86_64,为…...

angr学习-入门篇
前言: 资源链接:GitHub - jakespringer/angr_ctf(题库仓库,里面有个讲解angr的PPT,里面有官方的题解很详细) GitHub - Hustcw/Angr_Tutorial_For_CTF: angr tutorial for ctf 安装: 关于angr…...

基于java SpringBoot和HTML的博客系统
随着网络技术渗透到社会生活的各个方面,传统的交流方式也面临着变化。互联网是一个非常重要的方向。基于Web技术的网络考试系统可以在全球范围内使用互联网,可以在本地或异地进行通信,大大提高了通信和交换的灵活性。在当今高速发展的互联网时…...

动态sql以及常用的标签
什么是动态sql: 指根据不同的条件生成不同的sql 搭建环境: 建表: create table blog( id varchar(50) not null comment 博客id, title varchar(100) not null comment 博客标题, author varchar(30) not null comment 博客作者, create_ti…...

DID以及社交网络中的ZKP
1. 引言 本文关键术语为: Decentralized Identity (DID,去中心化身份) or self-sovereign identity (SSI,自治身份) :是一个基于开放标准的框架,使用自主、独立的标识符和可验证证书,实现可信的数据交换。…...

基于SWAT-MODFLOW地表水与地下水耦合
耦合模型被应用到很多科学和工程领域来改善模型的性能、效率和结果,SWAT作为一个地表水模型可以较好的模拟主要的水文过程,包括地表径流、降水、蒸发、风速、温度、渗流、侧向径流等,但是对于地下水部分的模拟相对粗糙,考虑到SWAT…...

2023拒绝内卷!两年转行网络安全真实看法!
我目前转行网络安全两年,没啥天分,全靠努力,基本能够得上中级的水平了。看到大家对转行网络安全挺感兴趣,也有挺多争议,想把我的建议和经验告诉大家。 有很多人觉得网络安全已经饱和了,现在选择这个工作&a…...

【SA8295P 源码分析】57 - libDSI_MAX96789_0.so驱动库 之 QDI_Panel_Init 显示屏初始化函数 代码分析
【SA8295P 源码分析】57 - libDSI_MAX96789_0.so驱动库 之 QDI_Panel_Init 显示屏初始化函数 代码分析 一、QDI_Panel_Init() 显示屏初始化函数:Panel_DSI_MAX96789_0_Init()二、QDI_Panel_SetPower() 显示屏初始化:Panel_DSI_MAX96789_0_PowerLCD()三、QDI_Panel_GetInfo() …...

IDEA偶尔编译的时候不识别lombok
偶尔IDEA启动项目的时候会识别不到lombok,识别不到get()跟set()方法 方案 在settings添加下面代码 -Djps.track.ap.dependenciesfalse...

rust学习-构建服务器
单线程server 服务器会依次处理每一个请求,在完成第一个连接的处理之前不会处理第二个连接 // cat main.rs use std::io::prelude::*; use std::net::TcpListener; use std::net::TcpStream;fn main() {let listener TcpListener::bind("127.0.0.1:7878&quo…...

Java并发----进程、线程、并行、并发
一、进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 当一个程序被运行…...