Moby 依赖解析:azcore(Azure SDK for Go 核心库)CHANGELOG 版本演进全解读
本篇技术指南以 Moby(Docker 引擎上游仓库)中 vendor 的 azcore CHANGELOG 为主体,完整梳理 Azure SDK for Go 核心库 github.com/Azure/azure-sdk-for-go/sdk/azcore 从 0.1.0(2020-01-10)到 1.21.1(2026-04-16)的全部发布历史、重大破坏性变更与关键 API 演进,并结合仓库中的 go.mod、vendor/modules.txt 与 vendored 源码,解释 azcore 在 Moby 依赖图中的位置及其 API 设计(Pipeline/Policy、Retry、Poller/Pager、ResponseError 等)的实现落点,帮助读者在升级或排查 Azure SDK 相关依赖时快速定位版本行为差异。
azcore 在 Moby 仓库中的位置
Moby 仓库通过 Go modules 的 vendor 机制完整纳入了 azcore。查阅 go.mod 可以看到:
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 // indirect
注意 // indirect 标记:Moby 自身并不直接 import azcore,它是经由 Azure 存储 SDK(azblob)等包间接引入的。vendor/modules.txt 中同样列出了 # github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 及其各子包(cloud、log、policy、runtime、streaming、to、tracing、internal/exported、internal/pollers 等),与 CHANGELOG 中描述的包结构完全对应。
因此,阅读这份 CHANGELOG 的实用价值在于:当 Moby 升级 azblob/azcore 版本、或排查容器镜像分发链路中涉及 Azure Blob 存储的间接依赖行为变化时,这份发布历史是判断 API 语义、默认值与修复边界的第一手依据。
版本时间线总览
CHANGELOG 完整记录了 60+ 个版本,按阶段可归纳为:
| 阶段 | 版本区间 | 时间 | 主题 |
|---|---|---|---|
| 0.x 早期 | 0.1.0 – 0.23.1 | 2020-01 ~ 2022-04 | 基础请求/传输模型、日志、重试、LRO 轮询、分页 |
| 0.x 后期 | 0.23.0 – 0.23.1 | 2022-04 | 泛型化 Pager[T]/Poller[T]、cloud 包、XML 修复 |
| 1.0 稳定版 | 1.0.0 | 2022-05 | 大规模 API 固化,多项 Breaking Changes |
| 1.x 快速迭代 | 1.1.x – 1.8.0 | 2022-06 ~ 2023-10 | 重试调优、tracing、CAE、KeyCredential/SASCredential、messaging |
| 1.x 成熟期 | 1.9.0 – 1.21.1 | 2023-11 ~ 2026-04 | 错误处理强化、轮询器修复、观测性增强、Go 1.23/1.25 升级 |
Moby 当前 vendor 的 1.21.1 属于成熟期末期版本,意味着上述所有 1.x 的修复(尤其是轮询器、重试与错误日志相关)都已包含在内。
近期版本详解(Moby 当前版本 1.21.1 及其前驱)
1.21.1 (2026-04-16):错误日志脱敏与 URL 拼接修复
这是 Moby 当前 vendor 的版本,修复点非常具体:
ResponseError.Error()中请求 URL 路径未转义的问题。ResponseError是 azcore 统一的非 2xx 响应错误类型,其定义见 errors.go:
// ResponseError is returned when a request is made to a service and
// the service returns a non-success HTTP status code.
// Use errors.As() to access this type in the error chain.
//
// When marshaling instances, the RawResponse field will be omitted.
// However, the contents returned by Error() will be preserved.
type ResponseError = exported.ResponseError
注意其类型别名指向 internal/exported.ResponseError(vendored 于 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/),错误文本通过 Error() 生成时会内嵌请求 URL,1.21.1 修复了其中路径未转义、以及日志记录错误时未脱敏(redact)查询参数的问题——后者对避免凭据随查询串泄漏到日志有实际意义。
runtime.JoinPaths查询串处理修复:当paths以?(查询串)开头时,不再在 root 与 path 之间插入斜杠。该行为在当前 vendor 源码 runtime/request.go 中可以直接验证(第 74–104 行):
// JoinPaths concatenates multiple URL path segments into one path,
// inserting path separation characters as required. JoinPaths will preserve
// query parameters in the root path
func JoinPaths(root string, paths ...string) string {
if len(paths) == 0 {
return root
}
qps := ""
if strings.Contains(root, "?") {
splitPath := strings.Split(root, "?")
root, qps = splitPath[0], splitPath[1]
}
// ...
if strings.HasSuffix(root, "/") && strings.HasPrefix(p, "/") {
root = root[:len(root)-1]
} else if !strings.HasSuffix(root, "/") && !strings.HasPrefix(p, "/") && !strings.HasPrefix(p, "?") {
p = "/" + p
}
// ...
}
第 102 行 !strings.HasPrefix(p, "?") 条件正是本次修复的直接落点:path 段是纯查询串时不补斜杠。该函数被 SDK 代码生成逻辑广泛使用,是排查“URL 多出一个 /”类问题的关键函数。
- 升级至 Go 1.25.0 并更新依赖。
1.21.0 (2026-01-12):runtime/datetime 包与云受众对齐
- 新增
runtime/datetime包,提供专门的时间类型封装,用于按 Azure 各服务使用的多种格式(如ISO 8601的 date/time 变体)序列化和反序列化时间值。这是 azcore 首次把“时间编码格式”从各 SDK 自行处理收编为公共基础设施; cloud.AzureGovernment与cloud.AzureChina的 audience 值与 Azure CLI 对齐,影响多云(government/china)环境下的令牌受众断言。
1.20.0 (2025-11-06):next link 分页的动词可控
runtime.FetcherForNextLinkOptions新增HTTPVerb字段,允许指定通过 next link 获取下一页时使用的 HTTP 动词,默认http.MethodGet。部分 Azure 服务的分页接口要求 POST 翻页,此前无法覆盖;- 修复 base64 字符串解码时可能 panic 的问题;
- 修复资源标识符(resource ID)解析对畸形 ID 不返回错误的漏洞。
1.19.x (2025-08 ~ 2025-09):ARM 资源层级解析修复
- 1.19.1:修复 provider 专属资源层级中包含
resourceGroups段时的资源标识符解析;改进了对不规范编写的长时运行操作(LRO)的错误回退; - 1.19.0:新增
runtime.APIVersionLocationPath,供把 API 版本放在 URL 路径中的客户端声明。
1.18.x (2025-04 ~ 2025-07):BearerTokenPolicy 稳健性
- 1.18.0 新增
AccessToken.RefreshOn字段,BearerTokenPolicy会在决定是否申请新令牌时考虑非零值——即调用方可指定“早于过期时间多少”刷新令牌,避免临近过期窗口取令牌; - 1.18.2 修复
BearerTokenPolicy未保证认证错误为不可重试(non-retriable)的情形; - 1.18.1 修复重试请求时 request/response 日志中 try 信息不正确,以及
ResourceID.String()的数据竞争。
1.17.x (2025-01 ~ 2025-03)
- 1.17.0 新增
runtime.NewPollerOptions[T]的OperationLocationResultPath字段,用于Operation-Location模式的 LRO 指定最终结果所在字段;arm.ResourceID开始支持encoding.TextMarshaler/encoding.TextUnmarshaler接口; - 1.17.1 升级至 Go 1.23。
1.16.0 / 1.15.0 (2024-10):Span Kind 与 CAE 支持
- 1.16.0:
runtime.StartSpanOptions新增Kind字段(创建 span 时指定 kind);修复BearerTokenPolicy重试前不回绕(rewind)请求体的 bug——不 rewind 会导致重试时读取到已消费的空 body; - 1.15.0:
BearerTokenPolicy开始处理 CAE(Continuous Access Evaluation)claims challenge——AAD 可在 200 响应中通过WWW-Authenticate头返回claims,客户端需按提示重新取令牌重试;这是 Azure 平台级认证策略升级的配套能力。同时ResponseError.RawResponse在 JSON 序列化中被忽略(对应 1.21.1 中errors.go注释所述“marshaling 时 RawResponse 字段被省略”),修复了整实例无法 marshal 的问题;重试策略的整数溢出也被修复。
1.14.0 – 1.12.0 (2024):观测与工具函数
- 1.14.0:
runtime.StartSpanOptions新增Attributes字段简化带属性的 span 创建;log.EventRetryPolicy日志条目包含 HTTP 动词与 URL; - 1.13.0:新增
runtime.NewRequestFromRequest(),允许从既有*http.Request构造policy.Request; - 1.12.0:
runtime.FetcherForNextLinkOptions新增StatusCodes字段(允许把额外 HTTP 状态码视为成功);runtime包新增NewUUID函数;修复Operation-Location策略轮询器在某些情况下无法反序列化最终结果的问题。
1.11.x (2024-04):Location 头轮询的终态判定
- 1.11.1:使用
Location头的轮询器不再把http.StatusRequestTimeout(408)当作终态失败;runtime.Poller[T].Result不再把非终态错误响应当作终态。这两项修复统一了“瞬态错误可重试”的语义; - 1.11.0:
arm/policy.RegistrationOptions新增StatusCodes;azcore.ClientOptions新增InsecureAllowCredentialWithHTTP字段(显式允许对非 TLS 端点使用凭据,默认仍拦截);streaming包新增MultipartContent类型支持自定义 Content-Type 与文件名的 multipart/form 载荷;修复runtime.SetMultipartFormData对[]byte值的错误字符串化。
1.10.0 – 1.9.0 (2023-11 ~ 2024-02)
- 1.10.0:新增日志事件
log.EventResponseError(创建azcore.ResponseError时记录其Error()全文);新增runtime.NewResponseErrorWithErrorCode;新增条件请求类型MatchConditions;修复NullValue/IsNullValue间竞争;runtime.EncodeQueryParams在调用url.ParseQuery前转义分号(Go 的ParseQuery把;当分隔符,见 runtime/request.go 中strings.ReplaceAll(after, ";", "%3B")的处理); - 1.9.2:
runtime.MarshalAsByteArray/MarshalAsJSON保留已有的Content-Type头; - 1.9.1:重试时检查
retry-after-ms与x-ms-retry-after-ms头(此前漏检,导致 Azure 服务建议的精确重试间隔失效); - 1.9.0(重要):移除
fake包的NewTokenCredential(改用字面量&fake.TokenCredential{});runtime.PipelineOptions.TracingNamespace更名为TracingOptions;修复一批安全与稳定性问题——非 TLS 端点阻断 Key/SAS 认证、nil 凭据不再 panic(改为跳过认证)、零值azcore.ResponseError.Error()不再 panic、azcore 创建的 context 值不再跨不相干的 HTTP 请求流动。
1.0 → 1.8.0:从稳定到能力爆发
1.0.0 (2022-05-12):API 固化与破坏性变更
1.0.0 是 azcore 的第一个正式稳定版,Breaking Changes 集中且影响深远,对升级代码有直接参考价值:
cloud.Configuration.LoginEndpoint更名为.ActiveDirectoryAuthorityHost;cloud.AzurePublicCloud更名为cloud.AzurePublic;- 从
arm/ClientOptions与arm/policy.BearerTokenOptions移除AuxiliaryTenants,移除TokenRequestOptions.TenantID(跨租户认证能力推迟到后续版本以新形态回归,见 1.4.0-beta.1 与 1.6.0); Poller[T].PollUntilDone()签名变更:从freq time.Duration改为options *PollUntilDoneOptions,采用统一的 options 模式;- 移除
arm/runtime.Poller[T]、arm/runtime.NewPoller[T]()、arm/runtime.NewPollerFromResumeToken[T]()及arm/runtime.FinalStateVia——ARM 与 core 的轮询实现完成统一,只剩runtime.Poller[T]; runtime.PageProcessor更名runtime.PagingHandler;NewRequestIdPolicy()更名NewRequestIDPolicy();TokenCredential.GetToken改为按值返回AccessToken(而非指针),这是所有 Azure SDK 凭据实现的通用签名,1.x 时代的所有凭据库都遵循该约定;- 内部重构:
internal/pollers/poller.go并入runtime/poller.go;NewPipeline()将ClientOptions提供的策略置于PipelineOptions策略之后;默认 User-Agent 不再包含 azcore 版本号。
0.23.0 (2022-04-04):泛型与 cloud 包
- 新增
runtime.Pager[T any]与runtime.Poller[T any]的中心化泛型实现,成为 1.x 全部分页/轮询 API 的基础形态; - 新增
cloud包提供新的云配置 API,arm.Endpoint被其取代,arm/runtime.NewPipeline()与NewRPRegistrationPolicy()开始返回error; to包改为泛型Ptr[T]/SliceOfPtrs[T],NullValue/IsNullValue改为泛型类型参数。
1.1.x – 1.3.x (2022-06 ~ 2023-01):重试与管道精细化
- 1.1.3 将初始重试延迟调为 800ms(遵循 Azure SDK 指南的指数退避起点);1.1.4 增加约束:
Retry-After延迟超过RetryOptions.MaxRetryDelay时不再重试;runtime.JoinPaths不再无条件在查询串前加斜杠(与 1.21.1 的修复同源,可见该函数多次被查询串边界问题驱动迭代); - 1.2.0 是重要能力版本:新增
ClientOptions.APIVersion(覆盖客户端默认请求的 API 版本,所有 ARM 客户端都支持);新增tracing包(分布式追踪的构建块)与policy.ClientOptions.TracingProvider字段;修复NewPipeline丢失管道级允许头/查询参数、MaxRetryDelay默认值更正为 60s; - 1.3.0:
BearerTokenOptions.AuthorizationHandler允许向runtime.BearerTokenPolicy注入自定义授权逻辑;azcore与arm包新增Client基础类型(普通 HTTP 客户端与 ARM 客户端的最小形态);policy.Request.SetBody()允许替换为空 body。
1.5.0 – 1.8.0 (2023-04 ~ 2023-10):跨租户、CAE 与新凭据类型
- 1.5.0:
policy.RetryOptions.ShouldRetry提供细粒度重试判定钩子;同时把TokenRequestOptions.Claims/TenantID从正式版移除(beta 特性回归 1.6.0 线); - 1.6.0:ARM 跨租户认证落地——设置
arm.ClientOptions.AuxiliaryTenants启用;policy.TokenRequestOptions新增TenantID; - 1.7.0:
azcore.Client新增WithClientName()支持以新名称浅克隆客户端用于 tracing;1.7.1 在默认传输策略启用 TLS 重新协商;1.7.2 修复默认 HTTP 传输在 WASM 环境下的工作问题; - 1.8.0 能力集中爆发(含 1.8.0-beta.N 的累积特性):
- Claims 与 CAE 认证正式进入正式版本;
- 新增
messaging包:messaging.CloudEvent支持按 CloudEvents 1.0 规范序列化/反序列化(beta.1 引入,beta.2 中Data的 JSON 对象由json.RawMessage改为[]byte反序列化); - 新增
azcore包的KeyCredential/SASCredential类型及runtime包的KeyCredentialPolicy/SASCredentialPolicy(含构造函数与 options 类型)——补齐 Bearer 之外的密钥类认证; - 非 TLS 端点阻断 Bearer 认证(安全加固);
- 1.8.0-beta.3:
runtime.FetcherForNextLink/FetcherForNextLinkOptions将“从 next link URL 创建Pager[T].Fetcher”逻辑集中化;WithCaptureResponse、WithHTTPHeader、WithRetryOptions从runtime迁移到policy包导出并弃用旧版; - 1.8.0-beta.2:
server包新增SanitizePagerPollerPath;TokenRequestOptions.EnableCAE指示是否请求 CAE 令牌。
0.x 基础阶段:请求-传输模型与重试的成型(0.1.0 – 0.22.0)
早期 0.x 版本建立了 azcore 至今未变的骨架,理解这些决定有助于读懂 1.x 的 API 形态:
- 0.10.0 (2020-09-10) 是模型定型点:
request与transport接口重构为与标准库对齐的模式;NewRequest()改用http.NewRequestWithContext()并新增 context 参数;Policy与Transport接口移除 context 参数(context 挂在底层http.Request上);Pipeline.Do()在发送前校验请求,避免对畸形请求做无谓重试;Retrier接口被NonRetriableError取代;Request.SetBody()要求传入 content type;路径拼接收拢到JoinPaths()。这一版确立的“策略管道 + 不可变请求”模型就是今天policy.ClientOptions/runtime.Pipeline的雏形; - 重试语义逐步打磨:0.4.0 支持每次调用通过
WithRetryOptions()传入自定义重试选项、从默认重试状态码中移除 429、MaxTries更名MaxRetries;0.9.4 明确 per-try 超时的取消时机(HTTP 请求返回即取消,而非 body 读完)、body 下载失败时不重试非幂等操作; - 日志体系:0.10.1 提供默认 console logger(写 stderr,通过环境变量
AZURE_SDK_GO_LOGGING=all启用);0.18.0 把Logger类型改为包级方法azcore.SetClassifications/azcore.SetListener;0.21.0 为policy.LogOptions增加AllowedHeaders/AllowedQueryParams白名单,并引入azcore.ResponseError类型(非 2xx 时由 API 返回的统一错误类型,即 1.21.1 修复的Error()脱敏对象); - 认证演进:0.17.0 引入
TokenRequestOptions.TenantID与AuthenticationOptions.AuxiliaryTenants;0.20.0 移除azcore.Credential/NewAnonymousCredential(),NewRPRegistrationPolicy直接要求azcore.TokenCredential,runtime.NewPipeline新签名简化自定义认证实现; - LRO 与分页:0.14.4 提供基础 LRO 轮询(
LROPoller);0.14.3 支持 multipart 表单数据(Request.WriteMultipartFormData());0.19.0 把 LRO 轮询逻辑在 ARM 与 core 实现间统一;0.22.0 引入runtime.WithCaptureResponse(默认关闭,启用后 API 调用可取回原始 HTTP 响应); - JSON 编码细节:0.14.2 的
NullValue()/IsNullValue()哨兵值机制、0.15.0 导出Response.Payload()、0.16.0 修复UnmarshalAsByteArray()、0.9.2 的azure:"ro"只读字段注解(请求载荷中自动剔除只读字段并做对象图深拷贝)——这些至今仍是runtime.MarshalAsJSON的行为基础。
关键设计决策的源码印证
结合 vendor 源码可以验证 CHANGELOG 中几项描述的落点:
- 包结构与 0.19.0 的拆分一致:vendor 目录 顶层有
cloud、log、policy、runtime、streaming、to、tracing七个子包加根包(core.go、errors.go、etag.go、doc.go),正是 0.19.0 changelog 所述“按使用场景拆分内容”(核心/通用/SDK 作者)的最终形态; - 错误类型的别名模式:
ResponseError = exported.ResponseError(见 errors.go)表明对外类型由internal/exported维护、对外导出别名——这类内部实现细节(如 1.21.1 的 URL 转义与查询参数脱敏修复)都在internal包中完成,而对外契约保持别名稳定; - 查询串边界问题反复出现:从 0.18.1(
JoinPaths保留 root 中已编码的查询参数)、1.1.4(不无条件在查询串前加斜杠)到 1.21.1(paths 以?开头时不补斜杠),runtime/request.go 中JoinPaths对?的三段式处理(root 拆分、path 拼接、条件补斜杠)是这条修复链的累积结果; - 1.10.0 的分号转义修复同样可在源码中直接看到:
url.ParseQuery(strings.ReplaceAll(after, ";", "%3B")),源码注释还引用了 Go 标准库 issue 说明;分隔符背景。
升级与排查建议
基于 Moby 当前 vendor 的 1.21.1 与 CHANGELOG 的完整历史,给出几条可操作的结论:
- 对齐凭据签名:任何自实现
azcore.TokenCredential的代码必须按 1.0.0 后的签名按值返回AccessToken;若还要响应 CAE(1.15.0 起 azcore 自动处理 challenge),令牌提供方需支持 claims 参数; - 分页/轮询行为:1.11.1 之后,基于
Location/Operation-Location头的轮询器对 408/429 等瞬态状态不再误判终态;1.20.0 起翻页动词可通过HTTPVerb覆盖;如果业务代码自己实现了 next-link 翻页,建议对齐FetcherForNextLink的集中化实现(1.8.0-beta.3 引入); - 日志安全:1.21.1 的错误日志已转义 URL 并脱敏查询参数,若依赖旧版本自建日志管道,应注意
ResponseError文本可能含未脱敏查询串; - 版本升级路径:从 0.x 直升 1.x 必须处理 1.0.0 的 Breaking Changes 清单(
PollUntilDone签名、cloud.AzurePublic更名、ARM poller 统一等);1.9.0/1.8.0 的 beta 特性开关(CAE、tracing、fakes 在不同 beta 间反复增删)说明跨 beta 迁移时需对照具体小版本的 Breaking Changes 段落。
小结
这份 vendored CHANGELOG 完整呈现了 azcore 从 0.1.0 的请求模型原型到 1.21.1 的成熟形态:以 0.10.0 定型策略管道、0.23.0 完成泛型化、1.0.0 固化 API、1.6.0–1.15.0 补齐跨租户/CAE/CAE-challenge 等认证能力、1.9.x–1.21.x 持续强化轮询器、重试与错误日志的稳健性。对 Moby 而言,azcore 作为 azblob 的间接依赖被 vendor 固定在 1.21.1,理解其版本历史可以在依赖升级、Azure 存储链路排障与错误日志审计时给出精确的行为边界判断。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00