模板预热(Template Cache)功能用于提前准备模板(Template)构建后的镜像数据,以降低首次创建沙箱(Sandbox)时因拉取镜像导致的冷启动耗时。
功能介绍
不同类型模板的预热策略及计费规则如下:
官方模板:由平台自动完成预热,无需用户干预,且不收取预热费用。
自定义模板:需主动调用 API 进行预热,系统将根据预热数据的实际存储量进行计费。建议在模板发布上线或批量创建沙箱前,按需执行预热操作。
适用范围
模板已完成构建,即
GetTemplate返回的构建状态status.state为ready。具体操作,请参见使用代码构建和管理自定义模板或控制台管理自定义模板。已创建 Team 并获取 Team ID。具体操作,请参见创建 Team。
已准备具备接口调用权限的 AccessKey 或 STS(Security Token Service,安全令牌服务)临时凭证,且凭证所属账号、模板与 Team 属于同一用户空间。具体操作,请参见阿里云 SDK & API 说明。
已确认服务接入点(Endpoint)与目标地域。具体操作,请参见阿里云 SDK & API 说明。
操作步骤
步骤一:初始化 SDK 客户端
安装 Go SDK(Software Development Kit,软件开发工具包)及依赖。
go get github.com/alibabacloud-go/sandbox-20260820/client
go get github.com/alibabacloud-go/darabonba-openapi/v2/utils
go get github.com/alibabacloud-go/tea/dara设置访问凭证:
export ALIBABA_CLOUD_ACCESS_KEY_ID="<YOUR-ACCESS-KEY-ID>"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="<YOUR-ACCESS-KEY-SECRET>"
# 使用 STS 临时凭证时,还需设置:
# export ALIBABA_CLOUD_SECURITY_TOKEN="<YOUR-SECURITY-TOKEN>"以下示例均基于 OpenAPI 版本 2026-08-20。客户端初始化方法在后续各步骤中复用,不再重复列出 import 语句。
package main
import (
"fmt"
"os"
"time"
openapiutil "github.com/alibabacloud-go/darabonba-openapi/v2/utils"
sandbox "github.com/alibabacloud-go/sandbox-20260820/client"
"github.com/alibabacloud-go/tea/dara"
)
func newClient(region string) (*sandbox.Client, error) {
return sandbox.NewClient(&openapiutil.Config{
AccessKeyId: dara.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
AccessKeySecret: dara.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
SecurityToken: dara.String(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN")),
Endpoint: dara.String("sandbox." + region + ".aliyuncs.com"),
Protocol: dara.String("https"),
})
}长期 AccessKey 无需设置 ALIBABA_CLOUD_SECURITY_TOKEN;使用 STS 临时凭证时必须设置。步骤二:创建预热任务并轮询至就绪
调用 CreateTemplateCache 提交预热任务,再轮询 DescribeTemplateCache 直到 status 变为 ready。请求成功表示任务已被平台受理,预热在后台异步完成,受理成功不代表预热完成。示例每 15 秒轮询一次,最长等待 20 分钟,超时后继续查询任务状态,不要重复创建。模板尚未完成构建时,CreateTemplateCache 返回 409 TemplateNotReady,且不会创建预热任务。
func createAndWait(client *sandbox.Client, teamID, templateID string) error {
resp, err := client.CreateTemplateCache(&sandbox.CreateTemplateCacheRequest{
Body: &sandbox.CreateTemplateCacheInput{
TeamID: dara.String(teamID),
TemplateID: dara.String(templateID),
},
})
if err != nil {
return fmt.Errorf("CreateTemplateCache: %w", err)
}
cache := resp.Body.TemplateCache
fmt.Printf("accepted: status=%s requestId=%s\n",
dara.StringValue(cache.Status), dara.StringValue(resp.Body.RequestId))
deadline := time.Now().Add(20 * time.Minute)
for time.Now().Before(deadline) {
got, err := client.DescribeTemplateCache(
dara.String(templateID),
&sandbox.DescribeTemplateCacheRequest{TeamID: dara.String(teamID)},
)
if err != nil {
return fmt.Errorf("DescribeTemplateCache: %w", err)
}
cache = got.Body.TemplateCache
status := dara.StringValue(cache.Status)
fmt.Printf("status=%s progress=%d reason=%q sizeMB=%d requestId=%s\n",
status,
dara.Int32Value(cache.Progress),
dara.StringValue(cache.StatusReason),
dara.Int32Value(cache.ImageSizeMB),
dara.StringValue(got.Body.RequestId),
)
switch status {
case "ready":
return nil
case "failed", "evicted":
return fmt.Errorf("template cache is %s: %s", status, dara.StringValue(cache.StatusReason))
}
time.Sleep(15 * time.Second)
}
return fmt.Errorf("timed out waiting for template cache")
}预热是否完成只以 status 为 ready 为准。progress 仅用于展示任务进度,取值只有 0(未就绪)和 100(已就绪)两种,不会按百分比逐步推进,不作为就绪判定条件。
步骤三:使用预热就绪的模板创建沙箱
status 为 ready 后,即可使用该模板创建沙箱。需等待状态就绪后再创建,才能获得预热加速;预热未完成时创建沙箱通常只是无法提速,若镜像加速数据仍在准备中,可能返回 400 accelerated image not ready,请就绪后重试。具体操作,请参见创建沙箱。
更多操作
查询预热状态
调用 DescribeTemplateCache,传入模板 ID 和 Team ID,根据返回的 status 判断任务状态:
creating:任务已受理,可能正在排队、等待容量、等待并发或执行预热。继续查询,不重复创建。ready:预热完成,可使用该模板创建沙箱。failed:预热失败。查看statusReason排查,先删除再重新创建。evicted:预热数据已被平台回收,不能再提供预热加速。先删除,等待返回 404 后重新创建,并一并删除同地域内同一镜像(imageDigest)的其他evicted任务,否则新任务可能立即回到evicted。
分页查询预热任务
调用 ListTemplateCache 分页查询当前 Team 的预热任务,可通过 templateID 和 status 过滤,maxResults 默认为 20,取值范围为 1 到 100,超出取值范围时按边界值处理,不返回错误。以 nextToken 是否为空判断分页结束,不能根据当前页条数判断。
删除预热任务
不再需要预热时,调用 DeleteTemplateCache 删除预热任务。
func deleteCache(client *sandbox.Client, teamID, templateID string) error {
resp, err := client.DeleteTemplateCache(
dara.String(templateID),
&sandbox.DeleteTemplateCacheRequest{TeamID: dara.String(teamID)},
)
if err != nil {
return fmt.Errorf("DeleteTemplateCache: %w", err)
}
fmt.Printf("delete accepted: requestId=%s\n", dara.StringValue(resp.Body.RequestId))
return nil
}DeleteTemplateCache 返回成功后,继续调用 DescribeTemplateCache,直到返回 404 TemplateCacheNotFound,方可认为预热任务的逻辑删除完成。返回成功仅表示删除请求已被接受,底层镜像数据在没有存活实例继续引用对应镜像后由平台异步安全清理;重复删除返回 404。
对状态为 failed 或 evicted 的任务重新预热时,同样需先删除,再调用 CreateTemplateCache。
各接口的请求参数、授权信息和返回字段说明,请参见阿里云 SDK & API 说明。
使用限制
预热按地域隔离,在一个地域创建的预热任务不会自动同步到其他地域。
每个账号在每个地域默认拥有 10 GiB 预热容量额度,按该地域内不同镜像的预热数据量
imageSizeMB(单位为 MiB)累计核算,同一镜像被多个模板预热时不重复占用额度。如需提升容量额度,请提交工单申请。
已用容量加上本次申请的容量超过当前地域额度时,任务会被受理并保持在
creating等待容量;排队中的新建任务过多时,创建请求才返回429 TemplateCacheLimitExceeded。该判断为账号级聚合,不是仅当单个任务超过额度时才触发。单个任务的容量在额度范围内,但当前剩余容量暂时不足时,任务可能保持
creating,平台会回收符合条件的旧任务后继续处理。预热任务创建后具有 30 分钟的最短驻留时间,超过该时间后才可能成为容量回收候选。平台按容量使用情况以 LRU(Least Recently Used,最近最少使用)策略回收,被回收的任务保留元数据,状态显示为
evicted。同一 Team 内,同一模板只能有一个可见的预热任务。重复创建不会覆盖现有任务,而是返回
409 TemplateCacheAlreadyExists;状态为evicted的任务对象仍然存在,直接重新预热同样返回该错误。删除模板前先删除对应的预热任务,并等待
DescribeTemplateCache返回 404。存在活跃预热任务时,删除模板可能返回409 TemplateHasActiveCache。警告删除后该模板不可用于创建新的沙箱实例,如需再次使用,需重新构建模板。删除前请确认业务已不再依赖该模板。
创建、删除与状态变化均为最终一致。SDK 调用超时或返回 500 时,先调用
DescribeTemplateCache确认结果,再决定是否重试,避免重复操作。
故障排查
错误码 | 含义与处理建议 |
| 模板尚未完成构建。等待 |
| 预热任务已存在,改为查询已有任务。状态为 |
| 排队中的新建任务过多,错误信息提示 |
| 预热任务正在删除。等待返回 404 后再创建。 |
| 预热任务不存在,或删除已完成。 |
| 请求参数不合法:缺少 |
| 模板 ID 不存在,或模板不属于该 Team。 |
| 删除模板前仍存在预热任务。先删除预热任务,再删除模板。 |
| 无权访问该 Team 或模板。检查调用身份与资源归属。Team 或模板归属有误时,平台返回 404 |
| 平台内部错误。先查询确认创建或删除是否已生效,再决定是否重试。 |
任务长时间保持 creating 时,继续查询,不要重复提交;仍未完成则提交工单。业务逻辑应根据稳定的错误码处理,不要匹配英文错误文案。
提交工单时,保留每次响应中的 requestId,并一并提供地域、Team ID、模板 ID、API 名称、请求时间,以及错误码或 statusReason。