从官方文档学习Rabbit与SpringAMQP-乱版

news2024/11/27 18:39:36

本文也是笔者一直没有去详细学习的一个重要知识点MQ,也是架构中非常重要的一个中间件。
主要从Rabbit官网于Spring AMQP官方文档的角度去详细学习MQ

官方文档

Rabbit
Spring AMQP

学习结果

测试项目地址

导读

本文主要从以下两个角度去学习MQ

一、RabbitMQ 官方文档

该角度主要从中间件服务的角度去分析MQ的一些核心概念与高可用。

二、SpringAMQP 官方文档

该角度主要从客户端角度去学习怎么接入MQ,并且优化配置。

节点和群集存储可视为架构、元数据或拓扑的信息。 用户、虚拟主机、队列、交换、绑定、运行时参数都属于此类别。 此元数据在 RabbitMQ 术语中称为定义。

Rabbit

一、核心概念

首先从官方的架构文档开始看起(点击标题进入官方文档):

英文描述中文描述描述
VHost虚拟主机类似分组的存在,可以用来做服务的隔离,如测试环境与生产环境
Exchange交换机用户投递消息的入口,对消息识别后,投递到不同的队列中
Queue队列实际存储消息的队列,接收来自交换机的消息
Binding绑定定义交换机与队列绑定条件,决定不同条件的消息进入不同的队列

在这里插入图片描述
上文可能还不够自观,下图具体描述主流程,其中Exchange->Queue/Exchange的条件也就是上文所说的Binding(绑定)
在这里插入图片描述
以上是最重要的核心概念,在机构描述中还有一些其他内容:
元数据:也就是整个Rabbit服务信息,也可以理解成配置信息,该数据Rabbit提供了多种导出方案,在迁移或集群之间的复制同步信息时被使用到;
角色:也就是权限系统,也有详细的账号权限控制功能;

单节点安装

Rabbit是基于Erlang开发的,所以安装Rabbit需要Erlang环境,且版本需要匹配。可以点击查看版本匹配表。

受限篇幅长度这里就不列出安装步骤了,笔者可以点击连接后,往下拉官方文档里会教安装。

Linux-Rabbit安装包下载
windows-Rabbit安装包下载
Erlang安装包下载

Rabbit HA

本节主要阐述Rabbit高可用方案,主要有三:

Federation and/or ShovelClustering
Brokers 在逻辑上是独立的,可能有不同的所有者。集群形成单个逻辑Broker。
Broker可以运行不同(并且在某些方面不兼容)版本的 RabbitMQ 和 Erlang。节点必须运行兼容版本的 RabbitMQ 和 Erlang。
Broker可以通过不可靠的 WAN 连接 链接。通信通过 AMQP 0-9-1(可选由 TLS 保护),需要设置适当的用户和权限。Broker必须通过合理可靠的 LAN 进行连接 链接。节点将使用共享密钥相互进行身份验证 并选择性地使用启用了 TLS 的链接。
Broker可以以任何拓扑结构连接。链接可以是单向的,也可以是双向的。所有节点双向连接到所有其他节点。
强调可用性和分区容错 (AP) 来自 CAP定理。强调一致性和分区容错 (CP) 来自 CAP 定理。
Broker中的一些Exchange可能是联合的,而有些可能是本地的。全有或全无。
连接到任何Broker的客户端只能在该代理中使用非独占队列。连接到任何节点的客户端可以在所有节点上使用非独占队列。

官方描述可能还是过于晦涩,笔者用自己理解的白话文进行描述。其主要量大类,根据CAP原理分为AP、CP,提供了三种方案

Clustering

其中队列可以只在某个节点也可以集群所有节点同步队列以达到安全高可用,当然全集群的复制队列虽然安全但性能比较低,为此Rabbit提供了其他两种队列类型以达到更优秀的性能同时保证安全,下文会介绍到。
同时这种CP方案应在局域网内,以减少网路损耗,从而达到高效同步队列数据;
在这里插入图片描述

Federation

该类型主要是在不同的Rabbit服务下,通过该模式类似投递的方式也向对象Rabbit服务推送消息。
但需要所有同步所需权限账号才可以进行连接。
在这里插入图片描述

Shovel

类似Federation,Shovel 插件工作在一个较低的级别。
federation旨在提供交换机和队列的独立分布,而shovel只是从一个代理上的队列中消费消息,并将它们转发到另一个代理上的交换机。

Clustering

思考过的读者应该可以发觉Clustering集群方案是我们常见的高可用方案,而其他两种更像业务之间的解耦,为其他业务转发消息。而本节主要介绍该方案的详细信息。

核心概念
  1. 集群是一个或 多个节点,每个节点共享用户、虚拟主机、 队列、交换、绑定、运行时参数和其他分布式状态;
  2. 集群的组成可以动态变更。 所有 RabbitMQ Broker(节点)一开始都是在单个上运行的节点。这些节点可以加入到集群中,也可以退回到一个Borker;
  3. 默认创建的队列都只在一个节点上,但通过访问集群中的其中一个节点都可以访问到该队列;
  4. 使用复制队列和流,可以使得队列在集群节点中复制队列副本,以达到消息的安全;
  5. 不像Zookeeper的集群有Leader节点(主节点),通常情况下每个节点都是平等的,但复制队列类型的情况下些许不同;
  6. 因为有几个功能(例如复制队列,MQTT中的客户端跟踪) 需要集群成员之间达成共识,强烈建议使用奇数个集群节点: 1、3、5、7 等。

在这里插入图片描述

Delay Queues(延迟队列)

延迟队列,在Rabbit中没有直接提供延迟队列的功能,该功能通过队列的dead-letter-exchange参数配置实现:

在这里插入图片描述
认真看图后是可以发现:

  1. 通过设置消息过期时间
  2. 投递到无消费者的队列中
  3. 过期后投递到指定的队列,该队列就是延迟队列

浅看一下Rabbit管理端的配置界面
在这里插入图片描述

优化方案:

  1. 设置预拉取数量dead_letter_worker_consumer_prefetch,可以提高吞吐量-默认预拉取32条;
  2. 延迟队列会尝试尽可能早地将消息移动到磁盘,惰性模式配置。

Quorum Queues(复制队列)

中文直译复制队列,前面提到了那么多次,本节主要对他进行介绍;

  1. 复制队列是 RabbitMQ 实现持久、 基于Raft共识算法的复制FIFO队列。 它从 RabbitMQ 3.8.0 开始可用。
  2. 复制队列针对数据安全性为重中之重。复制队列被视为复制队列类型的默认选项。
  3. 具有Leader节点与副本节点,Leader节点向副本节点确认存储后才确认消费。

复制队列与 RabbitMQ 中其他类型的队列共享许多基本原理。 但是,它们更专门构建,专注于数据安全和可预测的恢复, 并且不支持某些功能。

Raft协议是一个CP协议,以一套规则来保证分布式数据安全,其主要核心概念是:集群内的部分节点状态达成一致即算成功;

特征经典队列(默认类型)仲裁队列
是否可以非持久队列可以
排他性是的
每条消息持久性允许总是
集群变更自动手动
消息 TTL(生存时间)是的是(自 3.10 起)
队列 TTL是的是的
队列长度限制是的
懒惰的行为是的始终(从 3.10 开始)或通过内存限制功能(3.10 之前)
消息优先级是的
消费者优先是的是的
死信推Exchange是的是的
遵守政策是的是(请参阅策略支持)
有害消息处理是的
全局 QoS 预取是的
复制队列-死信

死信的配置也决定了延迟队列的可靠性。如果不能理解这句话请读者重新阅读上文”延迟队列“

复制队列支持死信交换 (DLX),在集群环境中使用 DLX 并不安全,在3.10 复制队列支持更安全的死信形式,该形式对队列之间的消息传输使用至少一次保证 (下面概述了限制和注意事项):

形式默认基础描述
至少一次可选官方推荐,更加安全
最多一次默认具有幂等性,但是在一些设置下会变的不安全

首先需要读者认真思考,两者的词意
至少一次:在多种情况下,确保消息安全
最多一次:消息幂等性考虑

一、最多一次

对于复制队列,“最多一次”仍然是默认的死信策略,对于死信更多地是一种信息性质的情况,信息性质应该保证消息不会被重复投递(幂等),但是在传输过程中丢失或在溢出策略不合适的情况下丢失,丢失情况如果可以被情况,那该策略方案是好选择。

二、 至少一次

通过实现一个特殊的内部死信消费者进程来完成的。 其工作原理类似于普通队列消费者,手动确认分开 从它只使用已经死信的消息。
这意味着源复制队列将保留 死信消息,直到它们被确认。内部消费者 将使用死信消息并将其发布到目标队列 发布者确认。只有在发布者确认 收到,因此至少提供一次保证

三、 配置至少一次

要为源复制队列启用至少一次死信,请应用以下所有策略 (参数x- 开头

  1. dead-letter-strategy设置为at-least-once(默认值为at-most-once)。
  2. overflow设置为reject-publish(默认值为drop-head)。
  3. 配置dead-letter-exchange
  4. 启用功能标志stream_queue(默认启用) 对于在 3.9 或更高版本中创建的 RabbitMQ 集群)。
  5. (可选)配置死信路由配置dead-letter-routing-key

建议另外配置最大长度或最大长度字节,以防止源复制队列中过多的消息堆积
Rabbit官方管理端配置:
在这里插入图片描述

四、至少一次的局限性/警告
  1. 至少一次死信不适用于默认的drop-head溢出 策略,即使未设置队列长度限制。 因此,如果配置了drop-head,则死信将回退最多一次。请改用溢出策略拒绝-发布reject-publish
  2. 至少一次死信将需要更多的系统资源,例如内存和 CPU。 因此,仅当要求死信不丢失时,才启用至少一次
  3. 确认成为死信后被正常投递,避免队列堆积。
  4. 每个复制队列,将有一个内部死信 消费者流程。内部死信使用者进程位于复制队列领导节点上,默认每次预拉取最大拉取 32条;
  5. 如果死信吞吐量较高,则可以通过高级配置文件的 rabbit 应用程序部分中的dead_letter_worker_consumer_prefetch设置来增加预取大小 (每秒数千条消息)是必需的。
  6. 可以通过设置reject-publish可以动态切换
五、优先级

复制队列不支持设置消息的优先级,只能设置消费者的优先级;
但可以通过在Exchange,将不同优先级的消息投递到不同的队列中来实现优先级的划分;

由于篇幅限制,笔者将重新开一篇来介绍复制队列
👇专门介绍复制队列的博客👇
👉复制队列👈
👆专门介绍复制队列的博客👆

懒惰模式

即 尽可能早地将其内容移动到磁盘, 并且仅在消费者请求时才将它们加载到 RAM 中。

惰性模式下有一些内存于磁盘的负载配置,需要读者自己点开标题进入官网详细阅读

经典队列

可以在惰性模式下运行:即 尽可能早地将其内容移动到磁盘, 并且仅在消费者请求时才将它们加载到 RAM 中。
惰性队列的主要目标之一是能够支持非常 长队列(数百万条消息)。队列可能会变得很长 出于各种原因:

  1. 消费者离线/已崩溃/停机进行维护
  2. 消息入口突然激增,生产者超过消费者
  3. 消费者比正常情况慢

以上问题主要来自磁盘I/O速度导致速率变慢

官网也给出了一份报告:

消息数邮件正文大小消息类型生产者消费者
1,000,0001,000字节Durable10
队列模式队列进程内存内存中的消息消息使用的内存节点内存
默认257兆字节386,307368兆字节734兆字节
懒惰模式159 KB00117兆字节

两个队列都保留了 1,000,000 条消息,并使用了 1.2 GB 的磁盘空间。

在一些业务场景下也有使用

  1. 节点内存使用率时,延迟队列是合适的 更高的磁盘 I/O 和磁盘利用率是可以接受的。延迟队列还有其他方面 这应该被考虑。
  2. 非常适合在延迟队列的中转队列。
复制队列

整体语义相同也是消息会存入磁盘来降低内存消耗。

从 RabbitMQ 3.10 之后

复制队列将其消息内容存储在磁盘上(根据 Raft 要求)和 仅在内存中保留每条消息的少量元数据记录。
但是复制队列的内存限制配置已经没有用了,可以配置最大内存数量x-max-in-memory-length=0
90000000000

Stream队列

流是一种新的持久和复制的数据结构:

  1. 以性能为主要目标;
  2. 提供复制队列的CP高可用;
  3. 非消费后就删除消息的形式消费消息,允许多个消费者同时消费、重复消费;
  4. 适用日志队列
  5. 执行任何操作之前将所有数据保存到磁盘

可以看出该队列就像一个数据库表,按照顺序存储消息,消息在一定限定范围内持久化存储。
在这里插入图片描述

持久化保存

流作为不可变的仅追加磁盘日志实现。这意味着 日志将无限增长,直到磁盘用完。为了避免这种不良情况 方案可以为每个流设置保留配置,这将 根据日志数据总大小和/或期限丢弃日志中最旧的数据。

参数配置描述
max-ageY, M, D, h, m, s-例如7D(七天)
max-length-bytes最大存储字节数
性能特点

由于流在执行任何操作之前将所有数据保存到磁盘,因此建议使用 以尽可能使用最快的磁盘。
由于流的磁盘 I/O 密集型性质,它们的吞吐量会降低 随着邮件大小的增加。
就像仲裁队列一样,流也受到群集大小的影响。 流具有的副本越多,其吞吐量通常越低 因为必须做更多的工作来复制数据并达成共识。

优先队列

RabbitMQ 从版本 3.5.0 开始在核心中实现了优先级队列。 该实现支持有限数量的优先级:255。建议使用 1 到 10 之间的值,使用 x-max-priority 可选队列参数设置。 此参数应为 1 到 255 之间的正整数, 指示队列应支持的最大优先级。

意思可以为队列设置255个等级的消息,每个优先级都有一些内存中和磁盘上成本 每个队列。还有额外的 CPU 成本,从该特性考虑,优先级应该控制在10以内;

需要注意的是,如果消息未发生堆积(消费速度比生产速度快),消息的产生都将被即时消费,那么即使设置了优先级,但因为消息被即刻消费导致没有机会被排序,那么该功能将失效;

安全性

保证消息安全也是关键:
默认手动ack前提下

消息的安全也需要在开启ack模式下,Mq告知消息处理失败,且业务端也要做出一定处理

队列安全性描述
经典队列不安全只在单个broker存储
复制队列安全在集群大多数可用下安全
Stream特定情况不安全服务器宕机时缓存数据丢失

Spring AMQP

连接池类型

连接类型推荐指数描述
PooledChannelConnectionFactory其次基于 Apache Pool2 管理单个连接和两个通道池。 一个池用于事务通道,另两个个池用于非事务通道
ThreadChannelConnectionFactory推荐一个池用于事务通道,另两个个池用于非事务通道,但确保同线程的消息被相同的连接处理,以确保消费顺序。
CachingConnectionFactory最推荐单个连接代理,可以通过通道来区分是否支持事务,扩展性更强,也可以设置基于多个连接,更适合集群。

PooledChannelConnectionFactory

此工厂基于 Apache Pool2 管理单个连接和两个通道池。 一个池用于事务通道,另一个池用于非事务通道。 池是默认配置的;提供回调以配置池;有关更多信息,请参阅 Apache 文档。GenericObjectPool

    @Bean
    PooledChannelConnectionFactory pcf() throws Exception {
        com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
        connectionFactory.setHost("localhost");
        PooledChannelConnectionFactory pcf = new PooledChannelConnectionFactory(connectionFactory);
        pcf.setPoolConfigurer((pool, tx) -> {
            if (tx) {
                // 事务连接池
            }
            else {
                // 非事务连接池
            }
        });
        return pcf;
    }

注意要先引入Apache的连接池包

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.11.1</version>
        </dependency>

ThreadChannelConnectionFactory

Apache jar 必须位于类路径上才能使用此工厂。commons-pool2
此工厂管理单个连接和两个连接,一个用于事务通道,另一个用于非事务通道。 此工厂确保同一线程上的所有操作都使用相同的通道(只要它保持打开状态)。 这有助于严格的消息排序,而无需作用域内操作。 为避免内存泄漏,如果应用程序使用许多生存期较短的线程,则必须调用工厂的线程来释放通道资源。 从版本 2.3.7 开始,线程可以将其通道传输到另一个线程。 有关详细信息,请参阅多线程环境中的严格消息排序。ThreadLocalcloseThreadChannel()

    @Bean
    ConnectionFactory tcf() {
        com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
        connectionFactory.setHost(HOST);
        connectionFactory.setPort(PORT);
        connectionFactory.setUsername(USERNAME);
        connectionFactory.setPassword(PASSWORD);
        connectionFactory.setVirtualHost(VIRTUAL_HOST);
        connectionFactory.setThreadFactory(new NamedThreadFactory("PooledChannelConnectionFactory"));
        ThreadChannelConnectionFactory threadChannelConnectionFactory = new ThreadChannelConnectionFactory(connectionFactory);
        return threadChannelConnectionFactory;
    }

CachingConnectionFactory

既可以单个连接/多个通道也可以多个连接/多个通道,动态性更强,配置为CacheMode.CONNECTION时HA模式下更适用。

 @Bean
 public ConnectionFactory connectionFactory() {
     CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
     cachingConnectionFactory.setHost(HOST);
     cachingConnectionFactory.setPort(PORT);
     cachingConnectionFactory.setUsername(USERNAME);
     cachingConnectionFactory.setPassword(PASSWORD);
     cachingConnectionFactory.setConnectionLimit(1);
     //连接30秒后超时,超时后销毁且
     cachingConnectionFactory.setChannelCheckoutTimeout(30 * 1000);
     //最大缓存数量
     cachingConnectionFactory.setChannelCacheSize(Runtime.getRuntime().availableProcessors());
     //CacheMode.CHANNEL模式下,所有的客户端共享一个链接,不同的channel之间相互隔离。
     cachingConnectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CONNECTION);
     cachingConnectionFactory.setConnectionNameStrategy((connectionFactory) -> "业务系统Connection");
     cachingConnectionFactory.setVirtualHost(VIRTUAL_HOST);
     cachingConnectionFactory.setPublisherReturns(true);
     cachingConnectionFactory.setRequestedHeartBeat(60);
     cachingConnectionFactory.setConnectionThreadFactory(new NamedThreadFactory("RabbitConnection"));
     cachingConnectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
     return cachingConnectionFactory;
 }

动态选这VHost

消息顺序

考虑以下情况:

  • 投递时按序投递
  • 消费时按序消费

由于 RabbitMQ 的异步性质和缓存通道的使用;不确定是否将使用相同的通道,因此无法保证消息到达队列的顺序。 (在大多数情况下,它们会按顺序到达,但无序交付的概率不为零)。 要解决此用例:

  1. 生产者在同一通道发送(发送串行化)
  2. 无并发消费者(单个消费者消费)
    在这里插入图片描述
    串行化通道发送
    @Bean(name = "singleConnRabbitTemplate")
    public RabbitTemplate singleConnRabbitTemplate() {
        //创建连接工厂
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(HOST);
        connectionFactory.setPort(PORT);
        connectionFactory.setUsername(USERNAME);
        connectionFactory.setPassword(PASSWORD);
        //只开辟单个连接
        connectionFactory.setChannelCacheSize(1);
        connectionFactory.setChannelCheckoutTimeout(1000L);
        //创建操作模板
        return new RabbitTemplate(connectionFactory);
    }

ThreadChannelConnectionFactory连接池也可以做到指定线程通道

消费时预拉取数量设置1且设置单个消费者

生产(推送消息)

消费(消费消息)

有两种方法可以接收 :

  1. 简单的选项是使用轮询方法调用一次轮询一个
  2. 更复杂但更常见的方法是注册异步按需接收的侦听器
轮询消费者
异步消费
  1. 支持@Valid 注解验证入参,校验异常被RabbitListenerErrorHandler 监听
  2. 单队列根据类型不同处理

原始消息信息org.springframework.amqp.core.Message
原始消息属性 MessageProperties Message
通信管道 com.rabbitmq.client.Channel
从传入的 AMQP 消息转换而来。org.springframework.messaging.Message
@Header-带注释的方法参数,用于提取特定的标头值,包括标准 AMQP 标头。
@Headers-带注释的参数,所有标头。java.util.Map

笔者后知后觉还是单写了一篇
笔者后知后觉还是单写了一篇
笔者后知后觉还是单写了一篇

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

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

相关文章

【nodejs】模块的加载机制

1、优先从缓存中加载 模块在第一次加载后会被缓存。意味着多次调用require()不会导致模块的代码被执行多次 注意&#xff1a;不论是内置模块、用户自定义模块、还是第三方模块&#xff0c;它们都会优先从缓存中加载&#xff0c;从而提高模块的加载效率。 &#xff08;1&#x…

【求证】 网上配镜靠谱吗?

肯定也有不少的小伙伴 看着网上琳琅满目的“明星同款”眼镜 心动不已 盘算着给自己弄一副“性价比” 最高“明星同款”那么网上配镜究竟靠不靠谱&#xff1f; 潍坊眼科医院眼健康管理中心提醒您 网上配镜需谨慎 网络平台的价格优势非常明显&#xff0c;部分销量高的店铺&#x…

二叉树基础计算

题目专题二叉树节点个数二叉树叶子节点个数二叉树第k 层节点个数二叉树查找值为x 的节点一共有这么几个题目&#xff0c;主要是用来表现题目的性质 分别是求 二叉树节点个数 二叉树叶子节点个数 二叉树第k 层节点个数 二叉树查找值为x 的节点 如果我使用的还是这个二叉树 其…

【linux】基础IO

文章目录一、复习文件相关知识二、复习C文件相关操作1、复习知识点2、复习操作三、文件的系统调用接口1、open2、write3、read小结四、文件描述符1、初步认识2、两个问题知识点3、文件描述符的分配规则五、重定向1、 dup2函数2、myshell里面实现重定向功能3、知识点六、如何理解…

【C++】stack、queue和deque

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;stack 的…

密集单目 SLAM 的概率体积融合

点击进入—>3D视觉工坊学习交流群笔者简述&#xff1a;这篇论文主要还是在于深度估计这块&#xff0c;深度估计由于硬件设备的不同是有很多方法的&#xff0c;双目&#xff0c;RGBD&#xff0c;激光雷达&#xff0c;单目&#xff0c;其中最难大概就是单目了。在该论文中作者…

Flutter不常用组件(四)

Offstage 创建一个在视觉上隐藏其子项的小部件。隐藏后不占空间。 该组件有以下几个属性&#xff1a; Key? key&#xff1a;标识键bool offstage true&#xff1a;是否隐藏。默认为trueWidget? child&#xff1a;子组件 Center(child: Column(mainAxisAlignment: MainAx…

【设计篇】36 # 如何理解可视化设计原则?

说明 【跟月影学可视化】学习笔记。 可视化设计的四个基本原则 基本原则一&#xff1a;简单清晰原则 我们可以看下面一张图&#xff1a;国际茶叶委员会制作的全球茶叶消费排行榜图表&#xff0c;目的是想说明喝茶最多的不是中国人 我们可以用更简单的直方图方式去表现 基本…

c++11 标准模板(STL)(std::deque)(九)

定义于头文件 <deque> std::deque 修改器 移除末元素 std::deque<T,Allocator>::pop_back void pop_back(); 移除容器的最末元素。 在空容器上调用 pop_back 是未定义的。 指向被擦除元素的迭代器和引用被非法化。尾后迭代器是否被非法化是未指定的。其他迭代…

YOLOv5-common.py文件

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 目录一、任务说明二、导入相关包和配置1.基本组件1.1 autopad1.2 Conv1.3 Focus1.4 Bottleneck1.5 BottleneckCSP1.6 C31.7 SPP1.8 Concat1.…

C3P0数据库连接池详解 及连接JDBC步骤

目录 一、基本定义 二、使用C3P0&#xff08;数据库连接池&#xff09;的必要性 1.JDBC传统模式开发存在的主要问题 三、数据库连接池的详细说明 四、使用连接池的明显优势 1.资源的高效利用 2.更快的系统反应速度 3.减少了资源独占的风险 4.统一的连接管理&#xff0c…

SQL优化实战-0001:SQL查找是否存在,不要再使用count

文章目录1.需求分析与普遍SQL写法2.问题分析3.优化方案4.总结5.补充5.1 还有什么时候可以使用LIMIT 15.2 什么时候没必要使用LIMIT 11.需求分析与普遍SQL写法 业务代码中&#xff0c;需要根据一个或多个条件&#xff0c;查询是否存在记录而不关心有多少条记录。普遍的SQL及代码…

大战谷歌!微软Bing引入ChatGPT;羊了个羊高·薪招纳技术人才;Debian彻底移除Python2;GitHub今日热榜 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f3a1; 『微软Bing』将引入 ChatGPT&#xff0c;与 Google 一场大战难免 微软计划2023年3月底之前推出 Bing 搜索引擎的新版本&#xff0c;使用 ChatGPT …

Lua中self 、自索引及其面向对象应用代码示例

一、Lua表的self标识 在lua中&#xff0c;表拥有一个标识&#xff1a;self。self类似于c中的this指针和python中的self。在lua中&#xff0c;提供了冒号操作符来隐藏这个参数&#xff0c;例如&#xff1a; t1 {id 1, name "panda",addr "beijing" }-…

快过年了,看我使用python制作一个灯笼的小程序

哈喽呀&#xff0c;最近一直在写一些关于新年的的python小东西&#xff0c;今天也不例外&#xff0c;我把那些都放到了一个专辑里面了&#xff0c;感兴趣的朋友们可以去看看一下哦 目录 前言 画外轮廓 画灯笼的提线 画灯笼盖 画一下各种柱子 小小的外壳来一下 其他的小装饰…

Python打包(问题记录,待解决)

引言 文章用于测试在Python3.8的版本&#xff0c;打包Obspy地震包&#xff0c;最后集成到PyQt5上。 部署或冻结应用程序是 Python 项目的重要组成部分&#xff0c; 这意味着捆绑所有必需的资源&#xff0c;以便应用程序找到它需要的一切 能够在客户端计算机上运行。 但是&…

基于Python Unet的医学影像分割系统源码,含皮肤病的数据及皮肤病分割的模型,用户输入图像,模型可以自动分割去皮肤病的区域

手把手教你用Unet做医学图像分割 我们用Unet来做医学图像分割。我们将会以皮肤病的数据作为示范&#xff0c;训练一个皮肤病分割的模型出来&#xff0c;用户输入图像&#xff0c;模型可以自动分割去皮肤病的区域和正常的区域。废话不多说&#xff0c;先上效果&#xff0c;左侧…

JAVA语言基础语法——JVM虚拟机默认处理异常的方式,try...catch捕获异常

1.JVM默认的处理方式 a&#xff0e;把异常的名称&#xff0c;异常原因及异常出现的位置等信息输出在了控制台 运行结果如下&#xff1a; b&#xff0e;程序停止执行&#xff0c;异常下面的代码不会再执行了 2.try...catch捕获异常&#xff08;自己处理&#xff0c;捕获异常&am…

数学建模-相关性分析(Matlab)

注意&#xff1a;代码文件仅供参考&#xff0c;一定不要直接用于自己的数模论文中 国赛对于论文的查重要求非常严格&#xff0c;代码雷同也算作抄袭 如何修改代码避免查重的方法&#xff1a;https://www.bilibili.com/video/av59423231 //清风数学建模 一、基础知识 1.皮尔逊…

Qt之Json操作demo

一、JSON简介&#xff1a; JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;使用JavaScript语法来描述数据对象&#xff0c;但是JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多不同的编程语言&#xff0c;被广泛用于Internet上的数据交换格式。…