当前位置: 首页 > article >正文

Go语言外部服务调用可靠性实践:Icepick库的重试、熔断与并发控制

1. 项目概述与核心价值最近在折腾一个需要深度集成多个外部API的后端服务遇到了一个老生常谈但又极其棘手的问题如何优雅、可靠地处理那些可能失败的外部调用重试、熔断、降级、超时控制……这些概念听起来都懂但真要把它们组合成一个健壮、可维护的解决方案代码往往会变得臃肿不堪业务逻辑被各种防御性代码淹没。就在我为此头疼在各大开源社区翻找灵感时一个名为Icepick的项目进入了我的视线。它来自hatchet-dev这个组织定位非常清晰——一个为Go语言设计的、专注于提升外部服务调用可靠性的轻量级库。简单来说它帮你把重试、熔断、并发控制这些“脏活累活”封装起来让你能像调用普通函数一样安全地调用那些可能“抽风”的外部服务。Icepick这个名字起得很形象冰镐是攀登冰川的利器能帮你凿开坚冰、固定绳索。在分布式系统的“冰川”上不可靠的网络和外部服务就是那些暗冰而Icepick就是帮你安全通过这些危险地带的工具。它不试图做一个大而全的微服务框架而是聚焦于“客户端韧性”这一个点通过提供一套简洁的API和可插拔的策略让Go开发者能够以极低的成本为任何外部HTTP或gRPC调用注入可靠性。对于我这样经常需要对接第三方支付、短信、对象存储、AI模型接口的开发者来说这简直是雪中送炭。它让我从自己手写循环重试、维护断路器状态的繁琐中解脱出来能更专注于业务逻辑本身。2. 核心设计理念与架构拆解2.1 问题域界定我们到底在解决什么在深入Icepick之前我们必须先厘清它要解决的“外部服务调用”问题域。这不仅仅是“网络请求失败重试一下”那么简单。一个生产级的调用需要综合考虑多个维度的失败模式和处理策略瞬时故障网络抖动、服务端瞬间高负载、TCP连接超时。这类故障通常是暂时的通过简单的指数退避重试就能解决。部分故障服务端某些实例异常但其他正常。这需要客户端具备从失败中快速恢复并切换到其他可用实例的能力。持续故障下游服务完全宕机或严重过载。此时继续重试只会雪上加霜需要快速失败熔断并给出友好的降级响应。慢响应下游服务响应极慢占用客户端资源如连接、线程。必须设置超时并可能结合熔断器防止被拖垮。并发过载客户端自身对某个下游的并发请求过多可能压垮对方或耗尽自身资源。需要限制并发数。Icepick的设计正是围绕这些场景展开。它没有重新发明轮子而是基于Go社区成熟的库如cenkalti/backoff用于退避算法sony/gobreaker用于熔断器提供了一层更高阶、更统一的抽象。2.2 核心抽象Client与PolicyIcepick的架构非常清晰核心是两个抽象Client和Policy。Client是你的操作入口。你可以创建一个针对特定基础HTTP客户端或gRPC连接的Icepick Client。这个Client包装了底层的通信能力并允许你为其附加一个或多个Policy。Policy是策略的抽象定义了“在什么情况下执行什么操作”。这是Icepick的灵魂。目前它主要内置了三种核心策略重试策略 (RetryPolicy)定义重试的条件如哪些HTTP状态码或错误需要重试、重试的最大次数、以及重试之间的等待间隔支持常数、线性、指数等多种退避算法。熔断器策略 (CircuitBreakerPolicy)包装了一个断路器当失败率达到阈值时快速失败避免连锁故障。通常与重试策略配合使用。并发限制策略 (ConcurrencyLimitPolicy)限制对某个下游服务的并发请求数防止客户端或服务端过载。这些策略可以像乐高积木一样组合。例如你可以创建一个“先进行并发限制然后通过熔断器最后在熔断器内部执行带重试的请求”的调用链。这种组合性提供了极大的灵活性。2.3 工作流程与责任链模式Icepick内部采用了类似责任链Chain of Responsibility的模式来处理请求。当你通过Icepick Client发起一个调用时请求会依次通过你附加的所有Policy。每个Policy都可以决定是继续传递请求、直接返回如熔断器打开时、还是修改请求如重试策略会重新发起请求。一个典型的工作流如下请求到达ConcurrencyLimitPolicy。如果并发数已满则立即返回“资源不足”类错误否则占用一个信号量继续向下传递。请求到达CircuitBreakerPolicy。检查断路器状态。如果处于“打开”状态则立即返回熔断错误如果处于“半开”或“关闭”状态则继续传递并根据最终执行结果成功/失败更新断路器状态。请求到达RetryPolicy。执行原始请求。如果失败且符合重试条件则根据退避算法等待后重试直到成功或达到最大重试次数。最终请求由底层HTTP客户端或gRPC连接器实际执行。这种设计的好处是职责分离每个Policy只关心自己的逻辑易于测试和扩展。你也可以很容易地实现自己的自定义Policy。3. 实战从零开始集成Icepick理论讲得再多不如一行代码。我们来看一个完整的集成示例假设我们要调用一个不太稳定的天气预报API。3.1 基础安装与客户端创建首先引入Icepick库go get github.com/hatchet-dev/icepick然后我们创建一个包装了标准net/httpClient的Icepick客户端。package main import ( context fmt io net/http time github.com/hatchet-dev/icepick github.com/hatchet-dev/icepick/policy/breaker github.com/hatchet-dev/icepick/policy/retry ) func main() { // 1. 创建底层的 *http.Client baseHttpClient : http.Client{ Timeout: 10 * time.Second, // 设置基础超时 } // 2. 创建Icepick Client包装这个http.Client client, err : icepick.NewClient(baseHttpClient) if err ! nil { panic(err) } // 后续我们会为这个client添加策略 }3.2 策略配置与组合现在我们来定义策略。假设我们对天气预报API的调用策略是重试最多重试3次遇到5xx状态码或网络错误时重试重试间隔使用指数退避初始1秒乘数2。熔断当最近10次请求的失败率达到50%时熔断器打开持续30秒后进入半开状态。并发限制最多同时有5个请求在等待该API的响应。// 配置重试策略 retryPolicy, err : retry.NewPolicy( retry.WithMaxAttempts(4), // 总共尝试4次1次初始3次重试 retry.WithRetryableStatusCodes(500, 502, 503, 504), // 对哪些HTTP状态码重试 retry.WithExponentialBackoff(1*time.Second, 2.0, 10*time.Second), // 指数退避 ) if err ! nil { panic(err) } // 配置熔断器策略 circuitBreakerPolicy, err : breaker.NewPolicy( breaker.WithFailureThreshold(0.5), // 失败率阈值50% breaker.WithHalfOpenMaxRequests(3), // 半开状态下允许的最大试探请求数 breaker.WithCounterRollingWindow(10), // 统计最近10次请求 breaker.WithOpenTimeout(30*time.Second), // 打开状态持续时间 ) if err ! nil { panic(err) } // 将策略附加到客户端。 // 策略的执行顺序就是添加的顺序通常把并发限制放最外层熔断次之重试在最内层最靠近实际调用。 client.WithPolicy(circuitBreakerPolicy) client.WithPolicy(retryPolicy) // 注当前版本的Icepick可能未内置并发限制策略可能需要自定义或使用其他库如golang.org/x/sync/semaphore配合实现。3.3 执行调用与结果处理配置好策略的客户端其使用方式和原来的*http.Client几乎一样。func getWeather(city string, client *icepick.Client) (string, error) { ctx : context.Background() // 构建请求 req, err : http.NewRequestWithContext(ctx, GET, https://api.weather.com/v1/city, nil) if err ! nil { return , err } // 使用Icepick客户端执行请求。 // 所有的重试、熔断逻辑都在这一行背后自动完成。 resp, err : client.Do(req) if err ! nil { // 这里的错误可能是网络错误、重试耗尽后的错误、熔断器打开错误等。 // Icepick会尽力包装错误让你能区分类型。 return , fmt.Errorf(failed to get weather after all retries or due to circuit breaker: %w, err) } defer resp.Body.Close() body, err : io.ReadAll(resp.Body) if err ! nil { return , err } return string(body), nil }注意client.Do(req)返回的错误需要仔细处理。它可能包含多层信息。Icepick可能会返回特定的错误类型如breaker.ErrCircuitOpen熔断器打开你可以通过errors.Is来判断并实现相应的降级逻辑例如返回缓存数据或默认值。result, err : getWeather(beijing, client) if err ! nil { if errors.Is(err, breaker.ErrCircuitOpen) { // 熔断器打开使用缓存或默认数据 log.Println(Circuit is open, using cached weather data.) result getCachedWeather() } else { // 其他错误如网络问题、重试失败 log.Fatalf(Unexpected error: %v, err) } } fmt.Println(result)4. 高级用法与自定义策略4.1 细粒度重试条件判断内置的WithRetryableStatusCodes可能不够用。比如某些API的4xx错误如429 Too Many Requests也可能需要重试。Icepick允许你自定义重试判断函数。retryPolicy, err : retry.NewPolicy( retry.WithMaxAttempts(3), retry.WithRetryableFunc(func(resp *http.Response, err error) bool { // 如果底层请求出错网络错误总是重试 if err ! nil { return true } // 对5xx和429状态码重试 if resp.StatusCode 500 || resp.StatusCode http.StatusTooManyRequests { return true } // 其他情况不重试 return false }), retry.WithConstantBackoff(2 * time.Second), )4.2 实现自定义并发限制策略虽然当前版本可能未内置但实现一个自定义的ConcurrencyLimitPolicy来演示其扩展性非常简单。import ( context golang.org/x/sync/semaphore ) type concurrencyLimitPolicy struct { sem *semaphore.Weighted } func NewConcurrencyLimitPolicy(max int64) *concurrencyLimitPolicy { return concurrencyLimitPolicy{ sem: semaphore.NewWeighted(max), } } func (p *concurrencyLimitPolicy) Execute(ctx context.Context, req *http.Request, next icepick.Handler) (*http.Response, error) { // 尝试获取信号量 if err : p.sem.Acquire(ctx, 1); err ! nil { return nil, err // 通常是上下文取消 } defer p.sem.Release(1) // 无论成功失败最终都要释放 // 执行下一个处理器可能是熔断器、重试或最终请求 return next(ctx, req) } // 使用时 concurrencyPolicy : NewConcurrencyLimitPolicy(5) client.WithPolicy(concurrencyPolicy)4.3 策略的上下文Context传播与超时控制这是一个至关重要的实践点。Icepick的请求执行链会传播context.Context。你必须为你的原始请求设置一个具有总超时的Context这个超时是整个调用链包括所有重试等待时间的上限。ctx, cancel : context.WithTimeout(context.Background(), 30*time.Second) // 总超时30秒 defer cancel() req, err : http.NewRequestWithContext(ctx, GET, url, nil) resp, err : client.Do(req)如果重试了3次每次等待2秒加上每次请求的执行时间总时间不能超过30秒否则会在某次重试前因上下文超时而退出。这保证了调用方不会被一个无限重试的请求永远挂起。5. 生产环境部署的考量与避坑指南在实际项目中使用Icepick有几个关键点需要特别注意。5.1 监控与可观测性仅仅有重试和熔断不够你必须能看到它们的状态。你需要监控熔断器状态每个下游服务的熔断器是开、关还是半开这直接反映了该服务的健康状况。重试统计每个接口的重试次数分布如何重试成功率多少这能帮你判断是下游不稳定还是你的重试策略不合理。请求延迟引入Icepick后P99延迟是否有显著变化重试和退避会增加尾部延迟。Icepick本身可能提供了一些指标接口或者你可以通过包装策略、在Execute方法中打点将数据导出到Prometheus等监控系统。没有监控的韧性策略如同盲人骑马。5.2 配置调优没有银弹策略参数需要根据实际场景调整切忌照搬。重试次数与退避对于用户交互请求重试次数不宜过多2-3次退避时间要短避免用户长时间等待。对于后台异步任务可以适当增加重试次数和退避时间。熔断器阈值FailureThreshold和CounterRollingWindow需要配合。一个激进的做法是窗口小如5次、阈值高如80%能快速熔断但可能过于敏感。一个保守的做法是窗口大如100次、阈值低如30%更平滑但反应慢。需要根据下游服务的SLA和故障模式来定。区分“重试”与“熔断”的错误不是所有错误都应触发熔断。例如401 Unauthorized认证失败是业务逻辑错误重试没用也不应影响熔断器。而503 Service Unavailable是基础设施错误应触发重试和熔断。这需要在RetryableFunc和熔断器的错误判断函数中仔细区分。5.3 与现有基础设施的集成日志确保Icepick内部的决策如“开始第N次重试”、“熔断器状态变为OPEN”以结构化的方式记录到日志中并带上唯一的请求追踪ID如X-Request-ID便于故障排查。分布式追踪如果你使用了Jaeger、Zipkin等确保每次重试的请求都能被记录为一个独立的Span并归属于同一个Trace这样你能清晰地看到一次用户请求背后可能发生的多次重试调用。依赖注入将配置好策略的Icepick Client通过依赖注入的方式传递给业务代码而不是在代码中硬编码创建。这便于测试可以注入一个Mock的Client和配置管理。5.4 常见陷阱与解决方案重试风暴服务A调用BB调用C。C故障导致B重试B的重试请求又压向A形成风暴。解决方案除了客户端重试必须结合熔断器和服务端限流。同时重试应采用随机化退避Jitter避免所有客户端同时重试。资源泄漏如果重试策略没有正确使用context.Context或者没有设置总超时一个挂起的请求可能永远占用连接、内存等资源。解决方案如前所述务必为每个请求设置一个合理的总超时Context。忽略降级熔断器打开了然后呢如果客户端没有降级逻辑返回缓存、默认值、简化功能用户体验会直接受损。解决方案在错误处理中必须对breaker.ErrCircuitOpen等错误类型做专门处理实现优雅降级。配置僵化策略参数写死在代码里无法根据运行时情况调整。解决方案将策略配置如重试次数、熔断阈值外部化到配置中心如Consul、Etcd支持动态热更新。在服务流量低谷时可以自动调低熔断阈值让服务更快进入半开状态尝试恢复。Icepick作为一个库提供了强大的构建块。但构建一个真正有韧性的分布式系统还需要开发者对这些模式有深刻的理解并结合监控、配置、架构设计一起运用。它不是一个“用了就高枕无忧”的魔法盒而是一把锋利的冰镐能否在复杂的系统冰川上安全前行最终取决于使用它的人。

相关文章:

Go语言外部服务调用可靠性实践:Icepick库的重试、熔断与并发控制

1. 项目概述与核心价值 最近在折腾一个需要深度集成多个外部API的后端服务,遇到了一个老生常谈但又极其棘手的问题:如何优雅、可靠地处理那些可能失败的外部调用?重试、熔断、降级、超时控制……这些概念听起来都懂,但真要把它们组…...

LIKWID标记API深度解析:精确测量代码性能

LIKWID标记API深度解析:精确测量代码性能 【免费下载链接】likwid Performance monitoring and benchmarking suite 项目地址: https://gitcode.com/gh_mirrors/li/likwid LIKWID是一款功能强大的性能监控和基准测试套件,其标记API(Ma…...

【Midjourney光照提示词黄金法则】:20年AI视觉工程师亲授7类光效参数组合,92%新手3天提升质感层级

更多请点击: https://intelliparadigm.com 第一章:光照提示词在Midjourney中的底层作用机制 光照提示词(Lighting Prompts)并非简单的修饰性描述,而是直接参与 Midjourney V6 模型的 latent 空间引导与风格解耦的关键…...

UTF8-CPP跨版本兼容性指南:从C++98到C++20的完整支持

UTF8-CPP跨版本兼容性指南:从C98到C20的完整支持 【免费下载链接】utfcpp UTF-8 with C in a Portable Way 项目地址: https://gitcode.com/gh_mirrors/ut/utfcpp UTF8-CPP是一个轻量级的C库,专注于以可移植的方式提供UTF-8编码和解码功能&#x…...

命令行控制中心:提升开发效率的聚合与自动化工具

1. 项目概述:一个面向开发者的命令行控制中心最近在GitHub上看到一个挺有意思的项目,叫jendrypto/command-center。光看名字,你可能会联想到科幻电影里那种布满屏幕、控制一切的舰桥。但在开发者的世界里,它其实是一个更接地气、更…...

SDLPAL图形渲染技术揭秘:OpenGL与Shader的完美结合

SDLPAL图形渲染技术揭秘:OpenGL与Shader的完美结合 【免费下载链接】sdlpal SDL-based reimplementation of the classic Chinese-language RPG known as PAL. 项目地址: https://gitcode.com/gh_mirrors/sd/sdlpal SDLPAL是一款基于SDL的经典中文RPG游戏重制…...

101种美食-图像分类数据集

101种美食图像分类数据集 数据集(文章最后关注公众号获取数据集): 通过网盘分享的文件: 链接: https://pan.baidu.com/s/1MWasy2HPJSknwgA5IrrNSA?pwdzj6u 提取码: zj6u 数据集信息介绍 apple_pie(苹果派)…...

77种商品-图像分类数据集

77种商品图像分类数据集 数据集(文章最后关注公众号获取数据集): 链接: https://pan.baidu.com/s/1Xcj5Z-RSUjGH47OIbH5wjQ?pwd=fq2p 提取码: fq2p 数据集信息介绍: 以下是整理后的清晰呈现,按照商品名称首字母顺序进行排列: 东方树叶红茶:文件夹中的图片数量为 150 …...

3D模型格式转换终极指南:如何用stltostp快速将STL转为STEP格式

3D模型格式转换终极指南:如何用stltostp快速将STL转为STEP格式 【免费下载链接】stltostp Convert stl files to STEP brep files 项目地址: https://gitcode.com/gh_mirrors/st/stltostp 你是否曾经遇到这样的困境?辛苦设计的3D打印模型在STL格式…...

你的PNG文件为什么总是太大?让SuperPNG插件帮你解决这个痛点

你的PNG文件为什么总是太大?让SuperPNG插件帮你解决这个痛点 【免费下载链接】SuperPNG SuperPNG plug-in for Photoshop 项目地址: https://gitcode.com/gh_mirrors/su/SuperPNG 如果你经常使用Photoshop处理PNG图片,可能已经发现了一个令人头疼…...

Linux内核构建自动化:jpoindexter/kern工具实战指南

1. 项目概述:一个被低估的Linux内核构建工具 如果你和我一样,长期在嵌入式开发、内核模块调试或者需要频繁定制Linux内核的岗位上工作,那么你一定对内核的配置、编译、打包这一套繁琐的流程感到又爱又恨。爱的是,这是深入理解操作…...

spoof 与网络安全:如何利用 MAC 地址伪造增强企业安全防护

spoof 与网络安全:如何利用 MAC 地址伪造增强企业安全防护 【免费下载链接】spoof Easily spoof your MAC address in macOS, Windows, & Linux! 项目地址: https://gitcode.com/gh_mirrors/sp/spoof 在当今数字化时代,网络安全已成为企业运营…...

智能体技能库构建指南:从基础工具到复杂工作流编排

1. 项目概述:智能体技能库的构建与价值最近在探索AI智能体(Agent)的开发与应用时,我一直在思考一个问题:一个真正“智能”的智能体,其核心能力究竟体现在哪里?是背后的大语言模型(LL…...

UltraScale架构FPGA功耗优化技术与工程实践

1. UltraScale架构的功耗优化技术全景解析在当今高性能计算和通信领域,功耗已成为FPGA选型的决定性因素之一。Xilinx UltraScale架构通过多层次的创新,在20nm工艺节点上实现了显著的功耗降低。作为深耕FPGA设计十余年的工程师,我将从实际应用…...

fastmod vs codemod:为什么你应该选择这个更快的代码替换工具

fastmod vs codemod:为什么你应该选择这个更快的代码替换工具 【免费下载链接】fastmod A fast partial replacement for the codemod tool. Assists with large-scale codebase refactors via regex-based find and replace with human oversight and occasional i…...

AI技能实战:本地部署大模型构建智能摘要工具

1. 项目概述:一个面向AI技能实践的开发者工具箱最近在GitHub上看到一个挺有意思的项目,叫inblog-inc/inblog-ai-skills。光看这个名字,你可能会觉得它又是一个关于“AI技能”的教程合集或者理论文档。但点进去之后,我发现它的定位…...

NewLife.Core配置系统深度解析:XML/JSON/HTTP多源配置实战

NewLife.Core配置系统深度解析:XML/JSON/HTTP多源配置实战 【免费下载链接】X Core basic components: log (file / network), configuration (XML / JSON / HTTP), cache (memory / redis), network (TCP / UDP / HTTP), RPC framework, serialization (binary / X…...

如何利用awesome-clothed-human资源构建你自己的虚拟试穿系统?

如何利用awesome-clothed-human资源构建你自己的虚拟试穿系统? 【免费下载链接】awesome-digital-human Digital Human Resource: 2D/3D/4D Human Modeling, Avatar Generation & Animation, Clothed People Digitalization, Virtual Try-On, etc. 项目地址: …...

Dot自定义配置指南:调整模型参数满足个性化需求

Dot自定义配置指南:调整模型参数满足个性化需求 【免费下载链接】Dot Text-To-Speech, RAG, and LLMs. All local! 项目地址: https://gitcode.com/gh_mirrors/dot1/Dot Dot是一款功能强大的本地AI应用,支持文本转语音、RAG(检索增强生…...

(二)进程的状态优先级

1进程的状态(兼容所有操作系统)1.1并行和并发CPU执行进程代码,不是把进程代码执行完毕,才开始执行下一个 而是给每一个进程预分配一个 时间片,基于时间片,进行调度轮转(单CPU下),并发。并发:多个进程在一个…...

linux操作系统乱码:Malformed input or input contains unmappable characters:

目录 问题 解决问题 查看 手动生成 zh_CN.UTF-8 字符集 centos8 问题 java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: /home/dualven/wvp-server/static/kmz/段雄文的航线.kmz 解决问题 查看 java -XshowSettings:pr…...

国产信创电脑是什么意思?为什么政府和企业都在用?

国产信创电脑——这个名词虽然听起来有些陌生,但它正在深刻影响着我们的工作和生活。从政府采购到企业信息化方案,再到科技媒体的报道,“国产信创电脑”已经成为了关键词之一。那么,它究竟是什么?为什么如此重要&#…...

基于ESP32-S3与CircuitPython的NASA小行星追踪器项目实践

1. 项目概述:一个会“说话”的太空瞭望台如果你对头顶那片星空既充满好奇又带有一丝敬畏,想知道是否有“天外来客”正悄无声息地接近我们,那么这个项目就是为你准备的。这不是一个简单的数据看板,而是一个亲手搭建的、能实时“对话…...

如何用Python快速接入Taotoken平台调用多模型API

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 如何用Python快速接入Taotoken平台调用多模型API 对于希望快速体验不同大模型能力的开发者而言,逐一对接各家厂商的API…...

终极指南:如何快速将AIO Sandbox与主流AI框架集成(LangChain、OpenAI Assistant等)

终极指南:如何快速将AIO Sandbox与主流AI框架集成(LangChain、OpenAI Assistant等) 【免费下载链接】sandbox All-in-One Sandbox for AI Agents that combines Browser, Shell, File, MCP and VSCode Server in a single Docker container. …...

ESP32-S3物联网开发实战:从点灯到上云Adafruit IO

1. 项目概述:从点灯到上云,解锁ESP32-S3的完整能力拿到一块ESP32-S3开发板,比如Adafruit的QT Py ESP32-S3,很多朋友的第一步就是让板载的RGB LED(NeoPixel)闪起来,这就像嵌入式世界的“Hello Wo…...

Flutter 表单处理完全指南

Flutter 表单处理完全指南 引言 表单是移动应用中不可或缺的一部分,Flutter 提供了强大的表单处理能力。本文将深入探讨 Flutter 表单的各种用法和高级技巧。 基础概念回顾 核心组件 Form: 表单容器TextFormField: 文本输入字段FormState: 表单状态管理GlobalKey: 全…...

YOLOv8手机识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)

摘要 针对公共场所中手机使用行为检测的需求,本文基于YOLOv8目标检测算法构建了一套手机检测系统。实验采用自建手机图像数据集,经过数据标注与增强后,训练了YOLOv8模型。最终模型在验证集上取得了mAP50高达1.02、精度0.99、召回率0.99的优异…...

YOLOv8无人机识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)

摘要 针对低空无人机(drone)的检测需求,本文基于YOLOv8目标检测算法构建了一个无人机识别系统。实验采用自建无人机数据集,包含训练集1012张图像、验证集347张图像,类别为单一目标“drone”。模型训练过程中&#xff…...

aztfexport扩展开发:如何自定义资源映射和导入逻辑

aztfexport扩展开发:如何自定义资源映射和导入逻辑 【免费下载链接】aztfexport A tool to bring existing Azure resources under Terraforms management 项目地址: https://gitcode.com/gh_mirrors/az/aztfexport Azure Export for Terraform(a…...