RabbitMQ实战宝典:从新手到专家的全面探索

前言

在当今分布式系统架构中,消息队列已成为不可或缺的一部分,而RabbitMQ作为其中的佼佼者,凭借其强大的功能和灵活性,广泛应用于各种规模的应用场景中。本文将带你从基础概念出发,深入探讨RabbitMQ的核心特性,通过实战案例与Java代码示例,引领你踏上成为RabbitMQ大师的旅程。

第一章:启程——初识RabbitMQ

1.1 RabbitMQ简介

RabbitMQ是一个开源的消息代理和队列服务器,它遵循AMQP(Advanced Message Queuing Protocol)协议,支持多种编程语言,包括Java。RabbitMQ的核心价值在于解耦应用程序、提高系统扩展性和容错能力。

1.2 交换机类型及实战

RabbitMQ提供了多种交换机类型,以满足不同场景的需求:

DirectExchange:最简单直接的路由,适合一对一消息传递。
FanoutExchange:实现发布/订阅模式,任何绑定到此交换机的队列都会接收到消息。
TopicExchange:基于模式匹配的路由,提供了极其灵活的消息路由方式。

实战案例:假设我们有一个系统需要在用户注册后,通过邮件和短信通知用户。我们可以使用FanoutExchange,为邮件服务和短信服务各创建一个队列,并让这两个队列都绑定到同一个FanoutExchange上。

// java示例代码
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("registration_notifications", BuiltinExchangeType.FANOUT);
String queueNameEmail = channel.queueDeclare().getQueue();
String queueNameSMS = channel.queueDeclare().getQueue();
channel.queueBind(queueNameEmail, "registration_notifications", "");
channel.queueBind(queueNameSMS, "registration_notifications", "");
// 发布消息
channel.basicPublish("registration_notifications", "", null, "User registered!".getBytes());

1.3 消息模型与工作流程

RabbitMQ支持多种消息模型,其中最常用的是发布/订阅模型(Pub/Sub)、路由模型(Routing)和主题模型(Topics)。每种模型都对应着不同的消息传递需求和业务场景。

发布/订阅模型

在上述实战案例中,我们已经见识了发布/订阅模型的威力。这种模型允许消息生产者(发布者)发送消息到一个交换机,然后由交换机负责将消息复制并发送给所有绑定到该交换机的队列。这非常适合一对多的通知场景,比如新闻推送、系统事件广播等。

路由模型

直接交换机(DirectExchange)体现了路由模型的特点,它根据消息携带的路由键(routing key)将消息精确地路由到与之匹配的队列。这种模型适用于需要根据特定条件分发消息的场景,比如订单处理系统中的不同商品类别处理。

主题模型

TopicExchange是主题模型的实现,它通过模式匹配的方式路由消息,允许队列通过通配符订阅多个路由键。这种灵活性使得主题模型在处理复杂且动态变化的路由规则时尤为有效,例如日志收集系统,可以根据不同的日志级别和来源配置不同的处理队列。

1.4 安装与配置

RabbitMQ可以在多种操作系统上运行,包括WindowsLinuxmacOS。最便捷的安装方式是通过包管理器(如Homebrewapt-getyum),或者直接从官方网站下载预编译的二进制文件。安装完成后,RabbitMQ会默认启动,并可通过Web管理界面http://localhost:15672进行访问和管理。

配置方面,RabbitMQ提供了丰富的配置选项,包括队列声明、交换机类型、权限控制、集群部署等,这些都可以通过配置文件、命令行参数或是管理界面来完成。对于复杂的部署需求,还可以利用插件系统进行功能扩展,如使用rabbitmq_management插件增强管理界面的功能。

1.5 安全与监控

确保消息系统的安全是至关重要的。RabbitMQ支持用户认证、权限控制和SSL/TLS加密传输,以保护消息在传输过程中的安全。管理员可以通过定义不同的用户角色和权限,细粒度地控制对队列、交换机和绑定的操作权限。

至于监控,RabbitMQ提供了一系列内置的监控和诊断工具,如上面提到的Web管理界面可以直观地展示队列状态、消息速率、节点健康状况等。此外,还可以集成第三方监控系统,利用AMQP协议的管理API获取更详细的指标数据,以便于进行性能调优和故障排查。

第二章:稳如磐石——消息可靠性保障

确保消息的可靠性是构建健壮消息驱动系统的基础。通过消息持久化、手动ACK机制、发布确认、镜像队列、死信处理与重试机制、以及网络分区的处理策略,RabbitMQ为开发者提供了一整套工具来保障消息在各种情况下的可靠性。结合正确的配置和最佳实践,可以最大限度减少消息丢失的风险,提高系统的整体稳定性。随着业务需求的增长和复杂度的提升,深入理解和应用这些可靠性策略,将对提升应用的容错能力和用户体验起到关键作用。

2.1 消息持久化

为了确保消息不因服务器故障而丢失,RabbitMQ提供了消息和队列的持久化机制。通过设置消息和队列的delivery_modedurable属性,可以在服务重启后恢复消息。

2.2 手动ACK机制

消费者通过手动确认(ACK)机制告诉RabbitMQ消息已被成功处理,这样即使消费者崩溃,消息也不会丢失。

channel.basicConsume(queueName, false, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), StandardCharsets.UTF_8);System.out.println("[x] Received '" + message + "'");// 处理消息逻辑...// 手动确认channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}, consumerTag -> {});

2.3 发布确认(Publisher Confirmations)

除了消费者端的ACK机制,RabbitMQ还支持发布确认(Publisher Confirmations),允许生产者确认消息是否成功到达交换机。这为消息的生产端也提供了可靠性保障。

channel.confirmSelect();try {for (int i = 0; i < messageCount; i++) {String message = "Message " + i;channel.basicPublish("", queueName, null, message.getBytes(StandardCharsets.UTF_8));}boolean waitForConfirms = channel.waitForConfirms();if (waitForConfirms) {System.out.println("All messages confirmed.");} else {System.out.println("Some messages were not confirmed.");}
} catch (Exception e) {e.printStackTrace();
}

2.4 镜像队列(Mirrored Queues)

镜像队列是一种高级的高可用性策略,它可以将队列中的消息复制到集群中的其他节点上,确保即使某个节点发生故障,队列的数据也不会丢失。配置镜像队列需要通过策略设置,指定队列的镜像级别,如以下命令行操作:

rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode":"all","ha-sync-mode":"automatic"}' --apply-to queues

这段命令设置了一个名为HA的策略,应用于所有不以amq.开头的队列,确保这些队列的数据在所有节点上都有镜像。

2.5 死信处理与重试机制

RabbitMQ允许通过死信交换机(Dead Letter Exchange, DLX)来处理无法正常消费的消息。当消息达到最大重试次数或符合特定条件时,可以被重新路由到DLX,从而进入死信队列,便于后续分析或重试。

channel.queueDeclare("DLQ", true, false, false, null);
channel.queueBind("DLQ", "myDeadLetterExchange", "#");Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "myDeadLetterExchange");
channel.queueDeclare("myQueue", true, false, false, args);

这里,myQueue配置了一个死信交换机myDeadLetterExchange,当消息变为死信时,会被重新发送到这个交换机,并根据路由键最终到达死信队列DLQ

2.6 网络分区处理与仲裁队列

在分布式系统中,网络分区可能导致部分节点与其他节点失去联系,RabbitMQ提供了网络分区检测与处理机制。当检测到网络分区时,可以根据配置策略决定队列的可写性,避免数据不一致。仲裁队列(Quorum Queues)是RabbitMQ 3.8版本引入的新特性,相比经典队列,它在分布式环境中提供了更好的耐久性和可用性,特别是在面对网络分区时,通过多数节点同意的机制保证数据一致性。

第三章:进阶探索——高级特性与最佳实践

本章深入探讨了RabbitMQ的高级特性与最佳实践,从灵活的消息路由、消息重复消费的处理,到性能优化、安全加固、自动化运维等多个维度,为开发者提供了全面的指南。通过合理运用这些策略和技巧,可以显著提升基于RabbitMQ构建的应用系统的稳定性和效率。面对日益复杂和规模化的应用环境,深入理解和实践这些高级特性,是每位消息中间件使用者必备的能力。未来,随着技术的不断进步和业务需求的演变,RabbitMQ及其生态系统将继续提供更为强大和灵活的解决方案,助力开发者构建更加高效、可靠的分布式系统。

3.1 TopicExchange的灵活运用

利用TopicExchange,可以实现消息的灵活路由。通过通配符模式,可以实现复杂的消息过滤逻辑。以下示例展示了如何配置TopicExchange以及消费者如何根据不同的通配符订阅消息:

// 声明TopicExchange
channel.exchangeDeclare("topicExchange", BuiltinExchangeType.TOPIC);// 声明两个队列并绑定到TopicExchange
channel.queueDeclare("queueNews", true, false, false, null);
channel.queueBind("queueNews", "topicExchange", "*.news.*");channel.queueDeclare("queueSports", true, false, false, null);
channel.queueBind("queueSports", "topicExchange", "*.sports.*");// 发布消息到TopicExchange
channel.basicPublish("topicExchange", "uk.news.weather", null, "Weather update UK".getBytes());
channel.basicPublish("topicExchange", "us.sports.football", null, "Football match results US".getBytes());// 消费者代码示例
String queueNameNews = "queueNews";
String queueNameSports = "queueSports";channel.basicConsume(queueNameNews, true, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), StandardCharsets.UTF_8);System.out.println("[News Queue] Received '" + message + "'");
}, consumerTag -> {});channel.basicConsume(queueNameSports, true, (consumerTag, delivery) -> {String message = new String(delivery.getBody(), StandardCharsets.UTF_8);System.out.println("[Sports Queue] Received '" + message + "'");
}, consumerTag -> {});

在这个例子中,queueNews绑定了通配符*.news.*,意味着它将接收所有包含.news.的消息,如uk.news.weather。同样,queueSports绑定了*.sports.*,会接收所有与体育相关的消息,如us.sports.football。这样,通过灵活的通配符订阅,TopicExchange能够有效地根据消息主题将消息路由到感兴趣的消费者,满足复杂的消息过滤和分发需求。

3.2 避免消息重复消费

消息重复消费是分布式系统中常见的问题。采用全局唯一ID与Redis结合,可以有效避免重复。

Jedis jedis = new Jedis("localhost");
long result = jedis.setnx("messageId:" + messageId, "processing");
if (result == 1) {// 消费消息// ...jedis.del("messageId:" + messageId); // 消费成功后删除标识
} else {// 检查消息状态,决定是否需要重新消费
}

3.3 使用TTL和Dead Letter Exchange优化消息生命周期管理

消息的生存时间(Time-To-Live, TTL)特性允许为消息或队列设置过期时间,过期后消息可被自动删除或转发至死信队列,从而实现消息的生命周期管理。

channel.queueDeclare("myQueue", true, false, false, new HashMap<String, Object>() {{put("x-message-ttl", 60000); // 设置队列消息TTL为60秒put("x-dead-letter-exchange", "dlxExchange"); // 设置死信交换机}}
);channel.exchangeDeclare("dlxExchange", "direct");
channel.queueDeclare("dlxQueue", true, false, false, null);
channel.queueBind("dlxQueue", "dlxExchange", "routingKeyForDeadLetter");

这段代码展示了如何为队列myQueue设置消息的TTL,并指定了一个死信交换机dlxExchange。当消息过期后,将会被路由到dlxQueue,实现消息的生命周期管理。

3.4 高并发下的性能优化

在高并发场景下,可以通过预取(Prefetch)设置、批量发布和消费、以及合理的队列和交换机设计来提升性能。通过调整预取值,可以平衡消息的处理速度和系统负载,避免单个消费者占用过多资源,提高整体处理效率:

channel.basicQos(100); // 设置消费者预取值为100,即每次最多发送给消费者100条未确认消息

3.5 使用RabbitMQ的延迟队列特性

RabbitMQ通过插件支持延迟队列,允许消息在特定时间后才被投递,这对于定时任务、订单超时处理等场景非常有用。例如:安装并启用RabbitMQ延迟消息插件(rabbitmq_delayed_message_exchange)后,可以创建带有延迟特性的交换机:

channel.exchangeDeclare("delayedExchange", "x-delayed-message", true, false, new HashMap<String, Object>() {{put("x-delayed-type", "direct");}}
);channel.basicPublish("delayedExchange", "routingKey", new AMQP.BasicProperties.Builder().expiration("5000").build(), // 设置消息延迟5秒"This message will be delayed for 5 seconds".getBytes());

这段代码展示了如何发布一个将在5秒后被投递的消息到延迟交换机。

3.6 插件扩展与自定义行为

RabbitMQ的强大之处还在于其丰富的插件生态。开发者可以利用现有插件如Management UIShovelFederation等来增强监控、数据迁移和集群互联功能,甚至开发自定义插件以满足特定业务需求。例如安装和启用RabbitMQ Management插件,以增强监控能力:

rabbitmq-plugins enable rabbitmq_management

通过浏览器访问http://localhost:15672即可查看管理界面。

3.7 安全加固:权限管理与TLS加密

确保RabbitMQ的安全不仅限于网络层面,还包括严格的权限管理和数据传输加密。通过配置用户角色、vhost访问控制以及启用TLS/SSL加密,可以有效保护敏感信息和防止未经授权的访问。如下示例配置RabbitMQ的用户权限和TLS加密:

# 创建用户并分配权限
rabbitmqctl add_user username password
rabbitmqctl set_permissions -p / username ".*" ".*" ".*"# 启用TLS
rabbitmq-plugins enable rabbitmq_management_agent rabbitmq_web_stomp
rabbitmqctl set_listener_tcp_tls [-p VhostName] port [certfile] [keyfile] [cacertfile]

确保使用证书和密钥文件配置TLS监听,以加密客户端与RabbitMQ之间的通信。

3.8 监控与日志分析

利用RabbitMQ Management UI和各类监控工具(如Prometheus+GrafanaELK Stack)对消息队列的性能指标进行实时监控,结合日志分析,能够快速定位并解决潜在的性能瓶颈和异常状况。例如集成Prometheus监控RabbitMQ:

  1. 安装rabbitmq_prometheus监控插件:
rabbitmq-plugins enable rabbitmq_prometheus
  1. 配置Prometheus抓取数据:
- job_name: 'rabbitmq'static_configs:- targets: ['localhost:15692']

通过Grafana展示监控图表,及时发现并解决问题。

3.9 自动化运维与持续集成

将RabbitMQ的部署、配置和升级纳入自动化运维流程,结合持续集成/持续部署(CI/CD)实践,可以提高系统的稳定性和迭代效率。使用Docker容器化部署、Ansible自动化配置管理等技术,简化运维复杂度。使用Ansible自动化配置RabbitMQ实例:

- name: Ensure RabbitMQ is installedapt:name: rabbitmq-serverstate: present- name: Configure RabbitMQcommand: rabbitmqctl set_policy ha-all "^queue\." '{"ha-mode":"all","ha-sync-mode":"automatic"}'

结合GitLab CI/CD pipeline,自动化测试和部署RabbitMQ配置更改。

3.10 案例研究:大规模分布式系统中的消息模式设计

通过分析实际案例,探讨在大规模分布式系统中如何设计高效、可扩展的消息模式。比如如何利用发布/订阅模式实现事件驱动架构,或如何结合RPC模式处理跨服务的异步请求响应,都是深入理解RabbitMQ在复杂应用场景中的关键。例如考虑一个事件驱动架构的电商系统,使用发布/订阅模式处理订单状态变更事件:

channel.exchangeDeclare("orderEvents", "fanout");
channel.queueDeclare("emailNotifications", true, false, false, null);
channel.queueBind("emailNotifications", "orderEvents", "");channel.queueDeclare("smsNotifications", true, false, false, null);
channel.queueBind("smsNotifications", "orderEvents", "");// 发布订单状态变更事件
channel.basicPublish("orderEvents", "", null, "Order status changed".getBytes());

此例中,当订单状态变更时,通过orderEvents交换机发布消息,同时emailNotificationssmsNotifications两个队列作为订阅者,分别处理电子邮件和短信通知,实现了消息的解耦和高效处理。

第四章:运维的艺术——命令行管理

4.1 用户管理的艺术

高效运维RabbitMQ离不开对rabbitmqctl命令行工具的熟练掌握。在用户管理方面,以下是一些核心命令:

# {username} 表示用户名; {password}表示用户密码
# 该命令将创建一个 non-administrative 用户
rabbitmqctl add_user {username} {password}# 表示删除一个用户,该命令将指示RabbitMQ broker去删除指定的用户
rabbitmqctl delete_user {username}# 表示修改指定的用户的密码
rabbitmqctl change_password {username} {newpassword}# 表示清除指定用户的密码
# 执行此操作后的用户,将不能用密码登录,但是可能通过已经配置的SASL EXTERNAL的方式登录。
rabbitmqctl clear_password {username}# 表示指引RabbitMQ broker认证该用户和密码
rabbitmqctl authenticate_user {username} {password}# 表示设置用户的角色,{tag}可以是零个,一个,或者是多个。并且已经存在的tag也将会被移除。
# rabbitmqctl set_user_tags tonyg administrator 该命令表示指示RabbitMQ broker确保用户tonyg为一个管理员角色。
# 上述命令在用户通过AMQP方式登录时,不会有任何影响;但是如果通过其他方式,例如管理插件方式登录时,就可以去管理用户、vhost 和权限。
rabbitmqctl set_user_tags {username} {tag ...}# 表示列出所有用户名信息
rabbitmqctl list_users

4.2 虚拟主机(VHost)的操控

虚拟主机是RabbitMQ中消息通道的逻辑隔离单元,管理它们同样重要:

# {vhost} 表示待创建的虚拟主机项的名称
rabbitmqctl add_vhost {vhost}# 表示删除一个vhost。删除一个vhost将会删除该vhost的所有exchange、queue、binding、用户权限、参数和策略。
rabbitmqctl delete_vhost {vhost}# 表示列出所有的vhost。其中 {vhostinfoitem} 表示要展示的vhost的字段信息,展示的结果将按照 {vhostinfoitem} 指定的字段顺序展示。这些字段包括: name(名称) 和 tracing (是否为此vhost启动跟踪)。
# 如果没有指定具体的字段项,那么将展示vhost的名称。
rabbitmqctl list_vhosts {vhostinfoitem ...}# 表示设置用户权限。 {vhost} 表示待授权用户访问的vhost名称,默认为 "/"; {user} 表示待授权反问特定vhost的用户名称; {conf}表示待授权用户的配置权限,是一个匹配资源名称的正则表达式; {write} 表示待授权用户的写权限,是一个匹配资源名称的正则表达式; {read}表示待授权用户的读权限,是一个资源名称的正则表达式。
# rabbitmqctl set_permissions -p myvhost tonyg "^tonyg-.*" ".*" ".*"
# 例如上面例子,表示授权给用户 "tonyg" 在vhost为 `myvhost` 下有资源名称以 "tonyg-" 开头的 配置权限;所有资源的写权限和读权限。
rabbitmqctl set_permissions [-p vhost] {user} {conf} {write} {read}# 表示设置用户拒绝访问指定指定的vhost,vhost默认值为 "/"
rabbitmqctl clear_permissions [-p vhost] {username}# 表示列出具有权限访问指定vhost的所有用户、对vhost中的资源具有的操作权限。默认vhost为 "/"。
# 注意,空字符串表示没有任何权限。
rabbitmqctl list_permissions [-p vhost]# 表示列出指定用户的权限vhost,和在该vhost上的资源可操作权限。
rabbitmqctl list_user_permissions {username}

4.3 图形化界面的启停自如

rabbitmq_management插件提供了一个强大的Web管理界面,其启用与禁用操作如下:

# 启用管理界面:
rabbitmq-plugins enable rabbitmq_management# 停用管理界面:
rabbitmq-plugins disable rabbitmq_management

4.4 进程管理

# 以前台进程的方式启动RabbitMQ
rabbitmq-server# 以后台进程的方式启动RabbitMQ
rabbitmq-server -detached# 查看并杀死进程
ps -ef | grep erlang# 查看服务是否启动
lsof -i:5672# 查看服务的详细状态
rabbitmqctl status

结语

RabbitMQ的学习与掌握是一个持续探索的过程。通过本指南的介绍,相信你已经掌握了从RabbitMQ的基础配置到高级特性的应用,以及如何在Java项目中集成RabbitMQ并确保消息的可靠传递。接下来,将理论知识应用于实际项目,不断优化你的消息队列设计,逐步迈向RabbitMQ大师的行列。在实战中成长,让消息驱动的架构助你一臂之力,构建更加健壮、可扩展的应用系统。

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

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

相关文章

计算机网络 静态路由及动态路由RIP

一、理论知识 1.静态路由 静态路由是由网络管理员手动配置在路由器上的固定路由路径。其优点是简单和对网络拓扑变化不敏感&#xff0c;缺点是维护复杂、易出错&#xff0c;且无法自动适应网络变化。 2.动态路由协议RIP RIP是一种基于距离向量的动态路由协议。它使用跳数作…

springboot+vue+mysql+mybatis 二手交易平台

springbootvuemysqlmybatis 二手交易平台 相关技术 javaspringbootmybatismysqlvueelementui

芯片后端之 PT 使用 report_timing 产生报告如何阅读

今天,就PT常用的命令,做一个介绍,希望对大家以后的工作,起到帮助作用。 在PrimeTime中,使用report_timing -delay max命令生成此报告。switch -delay max表示定时报告用于设置(这是默认值)。 首先,我们整体看一下通过report_timing 运行之后,报告产生的整体样式。 pt…

Bootstrap 5 导航

Bootstrap 5 导航 Bootstrap 5 是一个流行的前端框架&#xff0c;用于快速开发响应式和移动设备优先的网站。在本文中&#xff0c;我们将深入探讨 Bootstrap 5 中的导航组件&#xff0c;包括其功能、自定义选项以及如何在实际项目中有效使用它们。 简介 Bootstrap 5 的导航组…

vscode用vue框架2,续写登陆页面逻辑,以及首页框架的搭建

目录 前言&#xff1a; 一、实现登录页信息验证逻辑 1.实现登录数据双向绑定 2.验证用户输入数据是否和默认数据相同 补充知识1&#xff1a; 知识点补充2&#xff1a; 二、首页和登录页之间的逻辑(1) 1. 修改路由&#xff0c;使得程序被访问先访问首页 知识点补充3&am…

numpy.ndarray数据计算及操作集锦

目录 1. numpy.ndarray各列求均值1.1 列1.2 行 1. numpy.ndarray各列求均值 1.1 列 要对 v_sec_trans 数组的每一列求均值&#xff0c;可以使用 numpy 库中的 mean 函数。以下是具体的代码示例&#xff1a; import numpy as np# 定义 v_sec_trans 数组 v_sec_trans np.array…

Qt 实战(5)布局管理器 | 5.1、DPI对布局的影响

文章目录 一、DPI对布局的影响1、什么是DPI&#xff1f;2、DPI对布局的影响3、优化布局以适应不同DPI4、总结 前言&#xff1a; 在开发跨平台桌面应用程序时&#xff0c;DPI&#xff08;Dots Per Inch&#xff0c;每英寸点数&#xff09;是一个不可忽视的因素。DPI决定了屏幕上…

【STM32】STM32通过I2C实现温湿度采集与显示

目录 一、I2C总线通信协议 1.I2C通信特征 2.I2C总线协议 3.软件I2C和硬件I2C 二、stm32通过I2C实现温湿度&#xff08;AHT20&#xff09;采集 1.stm32cube配置 RCC配置&#xff1a; SYS配置&#xff1a; I2C1配置&#xff1a; USART1配置&#xff1a; GPIO配置&#…

二叉树经典OJ练习

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 二叉树经典OJ练习 收录于专栏【数据结构初阶】 本专栏旨在分享学习数据结构学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 前置说…

python:psutil获取指定进程Cpu及Memory使用的GUI界面

1导入依赖库 import os import psutil import time from pyecharts import options as opts from pyecharts.charts import Line import PySimpleGUI as sg from datetime import datetime from concurrent.futures import ThreadPoolExecutor import ctypes import sys2主界面…

八、(正点原子)Linux内核定时器实验

定时器是我们最常用到的功能&#xff0c;一般用来完成定时功能&#xff0c;本章我们就来学习一下 Linux 内核提供的定时器 API 函数&#xff0c;通过这些定时器 API 函数我们可以完成很多要求定时的应用。 Linux内核也提供了短延时函数&#xff0c;比如微秒、纳秒、毫秒延时函数…

YOLO系列--Anchor Based Anchor Free

一、Anchor based 1.1 Anchor的定义 Anchor也被称为锚框&#xff0c;预先设置目标的大概位置&#xff0c;然后再在这些预设框的基础上进行精细化的调整。调整过程被包括分类 判断预设框是属于正样本 or 负样本-和回归调整预测框的位置。 1.2 Anchor的产生 Anchor box是指在…

长尾分布(Long-tailed Distribution)

长尾分布&#xff08; L o n g − t a i l e d D i s t r i b u t i o n Long-tailed\ Distribution Long−tailed Distribution&#xff09;是统计学和概率论中的一个重要概念&#xff0c;用于描述一组数据中尾部&#xff08;即远离均值的部分&#xff09;包含了相对较多极端值…

【Linux基础】SSH登录

SSH简介 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。 SSH通过在网络中建立安全隧道来实现SSH客户端与服务器之间的连接。 SSH最常见的用途是远程登…

LeetCode 算法:二叉树的最大深度 c++

原题链接&#x1f517;&#xff1a;二叉树的最大深度 难度&#xff1a;简单⭐️ 题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,…

【高考选专业 | 家长篇】2024,计算机何去何从?小P老师带你看

目录 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f;1.行业竞争现状2.专业前景分析 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f; 随着2024年高考落幕&#xff0c;数百万高三学生又将面临人生中的重要抉择&#xff1a;选择大学专业。有人欢喜&#x…

如何在Java中实现高效的缓存机制

如何在Java中实现高效的缓存机制 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 在大多数软件系统中&#xff0c;缓存机制是提高性能和响应速度的关键技…

操作系统真象还原:用户进程

第11章-用户进程 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 11.1 为什么要有任务状态TSS Linux 任务切换未采用 Intel 的做法&#xff0c;而是用了一套自己的方法&#xff0c;只是用了 TSS 的一小部分功能。 操作系统最直接控制的就是 CPU&…

ubuntu22.04笔记: 更换为阿里源

没有按照LTS 版本 会遇到下面问题&#xff1a; 参考&#xff1a;https://zhuanlan.zhihu.com/p/691625646 Ubuntu 22.04代号为&#xff1a;jammy Ubuntu 20.04代号为&#xff1a;focal Ubuntu 19.04代号为&#xff1a;disco Ubuntu 18.04代号为&#xff1a;bionic Ubuntu …

对于C++ 程序员来说,35岁魔咒是否存在?

大家常说程序员职业生涯会在35岁左右遇到所谓的“35岁魔咒”。这意味着在这个年龄段&#xff0c;程序员可能会面临就业不稳定或职业发展的挑战。对于C程序员来说&#xff0c;这个问题更加引人关注。 随着时间的推移&#xff0c;技术行业不断演进&#xff0c;新的编程语言层出不…