Skip to content

更新日志 ​

Snake ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.0.5] - 2026-08-26 ​

新增 ​

  • 自动 WorkerID 推导在启动日志中打印推导结果与来源 IP,便于撞槽排查

变更 ​

  • 跨毫秒时序列号由重置为 0 改为随机偏移起始:两个副本自动推导的 WorkerID 撞车时,同毫秒内不再产出重复 ID

修复 ​

  • Generator 将 (timestamp, sequence) 打包进单个 64 位原子字整体 CAS,消除旧版两步原子操作中 timestamp 已推进、sequence 尚未重置导致的进程内重复 ID 竞态
  • Validate() 拒绝 (timestamp << SequenceBits) 打包状态会溢出 63 位原子字的 SequenceBits 配置(配合新版 Generator 的打包 CAS)

[0.0.4] - 2026-06-19 ​

新增 ​

  • Validate() 新增位宽校验:WorkerIDBits + SequenceBits 超过 63 时返回错误,避免时间戳字段溢出
  • 新增完整单元测试,覆盖率达 97.8%(含并发唯一性、时钟回拨、序列号溢出、位宽边界等场景)
  • 新增 CI 工作流(.github/workflows/ci-snake.yml),集成 Codecov 覆盖率上报

优化 ​

  • 移除 CalculateWorkerID 中两处死代码(fnv.Write 永不返回错误;取模运算保证 workerID 始终在有效范围内)

[0.0.3] - 2026-06-04 ​

依赖升级 ​

  • github.com/zeromicro/go-zero v1.10.0 → v1.10.2
  • go.opentelemetry.io/otel* v1.24.0 → v1.40.0(indirect,主动不升 v1.44+ 避免强制要求 go 1.25)
  • 同步 go mod tidy 清理无用 indirect 依赖
  • go directive 保持 1.24.0

[0.0.2] - 2026-03-20 ​

  • 升级 Go 版本至 1.24.0
  • 升级 go-zero 至 v1.10.0
  • 更新依赖版本

[0.0.1] - 2026-01-26 ​

  • 项目初版发布

Cron ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.1.2] - 2026-08-06 ​

变更 ​

  • 定时任务去重从固定 TaskID 改为 asynq.Unique:原方案以 task type 作为固定 TaskID,而 asynq 判定 ID 冲突的唯一依据是 task key 是否存在,这个 key 的寿命由上一次执行的结局决定(成功即删、带 Retention 时按保留时长、归档默认 90 天、还在跑时按执行时长),没有一种情况等于定时周期。现在改注入 asynq.Unique(TTL),其底层是一把 Redis SET NX EX 锁,键由队列名 + task type 决定,TTL 是相对时长,天然与周期对齐。
    • TTL 由 spec 与实际超时共同推导:TTL = max(最短触发间隔 − 1s, 实际超时, 1s),无需调用方指定
    • TTL ≥ 实际超时 保证「上一次还在跑就投不进第二份」;TTL < 最短触发间隔(超时小于间隔时)保证一次失败最多堵不足一个周期
    • 实际超时从 opts 中的 asynq.Timeout 反查,未显式传入时按 asynq 的 30 分钟默认值计算
    • 行为变化:重叠执行的保护窗口从「上一次任务在世期间」(可长达 90 天)变为「一个 TTL」。超时不小于触发间隔时锁会活过下一个 tick,该 tick 被跳过,这是「任务可能跑得比周期还久」应有的语义
    • 显式传入的 asynq.Unique 会被覆盖

修复 ​

  • 一次执行失败不再导致定时任务永久停摆:归档任务不再参与去重判定,去重锁自带有界过期(asynq 归档任务时不清理该锁),失败后最多堵住一个 TTL,下一个 tick 即恢复
  • 到点入队失败不再静默:SchedulerOpts.PostEnqueueFunc 原先只统计入队成功的情况,且未设置 EnqueueErrorHandler,入队失败时 asynq 直接返回,既无日志也无指标。现在失败会同时打日志和记指标
  • CronAdd 不再写进调用方 opts 的空余容量:原先直接在入参 opts 上 append 队列与去重选项,调用方传 opts... 且该 slice 有空余容量时,会踩进它的底层数组。现在先复制再追加。变参直接调用(包括 cztctl 生成的 workers.go)cap == len,不受影响

新增 ​

  • 指标 cron_server_scheduler_enqueue_error_total{task_type, reason}:定时任务到点入队失败次数。reason=duplicate 是多副本部署下的正常结果(每个 tick 有副本数 −1 次),只记 debug 日志;reason=other(如 Redis 不可用)响亮报错,是发现该类故障的唯一入口

依赖 ​

  • github.com/zeromicro/go-zero v1.10.2 → v1.10.3
  • github.com/redis/go-redis/v9 v9.20.0 → v9.21.0(随 go-zero v1.10.3 的最低要求上浮)
  • github.com/robfig/cron/v3 v3.0.1 从 indirect 提为 direct:用于解析 spec 推导最短触发间隔,解析器与 asynq Scheduler 内部一致
  • github.com/alicebob/miniredis/v2 v2.38.0 从 indirect 提为 direct:单元测试直接依赖
  • go mod tidy 清理 22 项不再需要的 indirect 依赖(grpc、grpc-gateway、otel exporters、pyroscope、zipkin 等)
  • 有意保持 go.opentelemetry.io/otel* 在 v1.40.0(v1.44+ 强制 go 1.25,为兼容性不升级)
  • go 指令保持 1.24.0

[0.1.1] - 2026-06-04 ​

依赖升级 ​

  • github.com/zeromicro/go-zero v1.10.0 → v1.10.2
  • github.com/redis/go-redis/v9 v9.17.3 → v9.20.0
  • 同步 go mod tidy 清理无用 indirect 依赖
  • 主动保留 go.opentelemetry.io/otel* v1.40.0(v1.44+ 强制要求 go 1.25,为兼容使用方不升)
  • go directive 保持 1.24.0

[0.1.0] - 2026-06-04 ​

破坏性变更 (Breaking) ​

  • CronAdd 签名调整:新增必传参数 handler HandlerFunc,一步完成调度注册与 handler 注册,避免同一 task type 在 CronAdd/Add 两处重复书写
    • 旧用法:CronAdd(spec, pattern, opts...) + Add(pattern, handler)
    • 新用法:CronAdd(spec, pattern, handler, opts...)
  • 定时任务超时改由 go-zero RestConf.Timeout 接管:v0.1.0 之前定时任务未注入超时,行为回落到 asynq 默认 30 分钟硬编码常量;v0.1.0 起推荐在 workers.go 将 serverCtx.Config.Timeout(go-zero rest.RestConf.Timeout)通过 asynq.Timeout(d) 注入 CronAdd,使 handler 收到的 ctx 自带 Deadline,与 go-zero HTTP 超时管控统一
    • cztctl 模板将在后续版本同步联动,业务方升级时需手动调整 workers.go,详见迁移指引

迁移指引 ​

API 签名迁移

diff
- serverCtx.CronServer.CronAdd("*/1 * * * *", "GDemoB")
- serverCtx.CronServer.Add("GDemoB", demoA.GDemoBHandler(serverCtx))
+ serverCtx.CronServer.CronAdd("*/1 * * * *", "GDemoB", demoA.GDemoBHandler(serverCtx))

接入 go-zero 超时管控

diff
+ import (
+     "time"
+     "github.com/hibiken/asynq"
+ )
+
  func RegisterHandlers(server *service.ServiceGroup, serverCtx *svc.ServiceContext) {
+     var taskOpts []asynq.Option
+     taskOpts = append(taskOpts,
+         asynq.Timeout(time.Duration(serverCtx.Config.Timeout)*time.Millisecond),
+         asynq.MaxRetry(0),
+     )
-     serverCtx.CronServer.CronAdd("*/1 * * * *", "GDemoB", demoA.GDemoBHandler(serverCtx))
+     serverCtx.CronServer.CronAdd("*/1 * * * *", "GDemoB",
+         demoA.GDemoBHandler(serverCtx), taskOpts...)
      server.Add(serverCtx.CronServer)
  }

rest.RestConf.Timeout 默认 3000ms,对 IO 密集型定时任务偏短,建议在 yaml 中显式调大(如 Timeout: 30000)。

新增 ​

  • CronAdd / Client.Push* 可通过 asynq.Timeout(d) opt 为单个任务设置任意时长超时(不受 asynq 默认 30 分钟限制),例:CronAdd("*/1 * * * *", "X", h, asynq.Timeout(time.Hour))
  • README 进阶指南新增「任务超时控制」章节,详述定时任务与投递任务的超时注入机制

修复 ​

  • ExponentialRetryDelay 公式修正为 2^(n+1) - 1:asynq 传入的 n 为上次已重试次数(0-indexed),原公式 2^n - 1 在第 1 次重试时返回 0s,导致首次重试无退避;修正后重试序列稳定为 1s, 3s, 7s, 15s, 31s, ...

[0.0.9] - 2026-06-04 ​

新增 ​

  • 新增 SetBaseContext(ctx context.Context) 方法,支持注入基础上下文,所有任务 handler 的 ctx 将以此为父级

变更 ​

  • asynq.Server 延迟到 Start() 时创建,支持在构造后、启动前动态配置上下文

[0.0.8] - 2026-06-04 ​

新增 ​

  • 新增 GetTaskID、GetRetryCount、GetMaxRetry、GetQueueName 包装函数,Handler 层无需直接依赖 asynq 即可获取任务元信息

变更 ​

  • README.md 全面重构:完整示例按 go-zero / 独立脚本 + Server / Client 四象限组织
  • 进阶指南新增任务分组聚合、放弃重试用法示例
  • 补充 asynq.SkipRetry 包装注意事项(pkg/errors 不兼容)
  • 监控指标章节标题层级修正

[0.0.7] - 2026-06-04 ​

新增 ​

  • 新增 WithGroupAggregator ServerOption,支持注入任务分组聚合器,使 Group 分组功能可用
  • 新增 WithRetryDelayFunc ServerOption,支持自定义重试延迟策略
  • 新增 ExponentialRetryDelay 内置重试策略(2^n - 1 秒:1s, 3s, 7s, 15s, 31s...)
  • CronAdd 自动以 realPattern 作为 TaskID,多实例部署时定时任务不会重复投递

修复 ​

  • 移除 ServerConfig.Validate() 中 GroupGracePeriod 的死代码校验(int64 不可能 >0 且 <1)

变更 ​

  • GroupMaxDelay 默认值从 0(无限制)调整为 300 秒(5分钟),防止任务持续到来时永不聚合
  • Server 默认重试策略从 asynq 内置的 n⁴ 指数退避改为 ExponentialRetryDelay(2^n - 1 秒)
  • Add 日志统一为 [CRON] Worker registered: %s

[0.0.6] - 2026-05-20 ​

变更 ​

  • metrics.go 中 log.Printf 替换为 logx.Errorf,统一使用 go-zero 日志规范
  • 移除 LoggingMiddleware,避免与 asynq 内部错误日志重复
  • 移除 RecoveryMiddleware 中冗余的 logc.Errorf,asynq perform 已内置 panic recovery 日志

[0.0.5] - 2026-05-15 ​

新增 ​

  • 新增完整监控指标体系
    • Server 端:cron_server_consume_total、cron_server_consume_duration_ms、 cron_server_consume_bytes、cron_server_active_workers、cron_server_retry_total、 cron_server_skip_retry_total、cron_server_panic_total、queue_groups、 tasks_aggregating_total、cron_scheduler_trigger_total、cron_scheduler_registered、 cron_tasks_enqueued_total、cron_queue_size、cron_queue_latency_seconds
    • Client 端:cron_client_push_total、cron_client_push_duration_ms、cron_client_push_bytes、cron_client_cancel_total
  • 新增队列白名单过滤,解决多服务共用 Redis 时指标混杂问题
  • Client 默认不重试(MaxRetry=0),用户可通过 opts 覆盖

变更 ​

  • 监控指标命名空间从 asynq_ 改为 cron_
  • Server 端指标添加 server subsystem

[0.0.4] - 2026-04-10 ​

变更 ​

  • 升级 Go 版本至 1.24.0
  • 升级 go-zero 至 v1.10.0
  • 更新依赖版本

ConfigCenter (Consul) ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.1.2] - 2026-06-04 ​

依赖升级 ​

  • github.com/zeromicro/go-zero v1.10.0 → v1.10.2
  • 同步 go mod tidy 清理无用 indirect 依赖
  • 主动锁定 github.com/hashicorp/consul/api v1.25.1(v1.33+ 强制要求 go 1.25,为兼容 go 1.24 不升)
  • go directive 保持 1.24.0

[0.1.1] - 2026-03-20 ​

  • 升级 Go 版本至 1.24.0
  • 升级 go-zero 至 v1.10.0
  • 更新依赖版本

[0.1.0] - 2025-11-26 ​

  • 项目初版发布

RegisterCenter (Consul) ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.1.7] - 2026-06-04 ​

依赖升级 ​

  • github.com/zeromicro/go-zero v1.10.0 → v1.10.2
  • google.golang.org/grpc v1.65.0 → v1.80.0
  • go.opentelemetry.io/otel/trace v1.24.0 → v1.40.0(indirect)
  • 同步 go mod tidy 清理无用 indirect 依赖
  • 主动锁定 github.com/hashicorp/consul/api v1.25.1(v1.33+ 强制要求 go 1.25,为兼容 go 1.24 不升)
  • go directive 保持 1.24.0

[0.1.6] - 2026-03-20 ​

  • 升级 Go 版本至 1.24.0
  • 升级 go-zero 至 v1.10.0
  • 更新依赖版本

[0.1.5] - 2025-12-01 ​

  • 优化版本

[0.1.3] - 2025-12-01 ​

  • 优化版本

[0.1.2] - 2025-12-01 ​

  • 优化版本

[0.1.1] - 2025-12-01 ​

  • 优化版本

[0.1.0] - 2025-12-01 ​

  • 项目初版发布

RabbitMQ ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.2.0] - 2026-08-03 ​

整库重新设计。0.1.6 未发版,其内容已并入本版本。

所有新增配置字段均有默认值,配置中心里的现有配置无需任何改动即可升级。

破坏性变更 ​

1. 拦截器抽象统一为中间件 ​

删除 Interceptor / SenderInterceptor / SenderFunc / SenderChain,改为一套 Meta / Handler / Middleware / Chain:

diff
-type Interceptor func(ctx context.Context, queueName string, message []byte, next func(context.Context, []byte) error) error
-type SenderInterceptor func(ctx context.Context, exchange, routeKey string, msg []byte, next SenderFunc) error
+type Handler func(ctx context.Context, meta Meta, body []byte) error
+type Middleware func(next Handler) Handler

说明:原 Chain 与 SenderChain 逻辑完全一致,仅因签名不同而复制。Meta 统一描述消息坐标(消费侧填 Queue,投递侧填 Exchange 与 RouteKey)后,两组同构类型合为一套。当前无第三方使用者,破坏面仅限自定义拦截器。

新增中间件注入点 WithConsumeMiddlewares / WithPublishMiddlewares:拦截器链此前硬编码在构造函数内,调用方无法追加。

2. Send 阻塞等待 confirm,错误细分为五类哨兵 ​

go
err := sender.Send(ctx, exchange, routeKey, body)
switch {
case errors.Is(err, rabbitmq.ErrPublishUnroutable): // routeKey 或绑定配置错误
case errors.Is(err, rabbitmq.ErrPublishNacked):     // broker 拒绝,框架内已重试
case errors.Is(err, rabbitmq.ErrPublishTimeout):    // 无法判断是否已达 broker
case errors.Is(err, rabbitmq.ErrPublishUnknown):    // 确认到达前 channel 已关闭,同属结果未知
case errors.Is(err, rabbitmq.ErrSenderClosed):      // Sender 已关闭
}

说明:原实现下 PublishWithContext 返回 nil 仅代表写入 socket,[RABBITMQ_SEND_OK] 日志并不成立。现在返回 nil 即代表 broker 已确认收下。代价是延迟上升、吞吐下降,由 PoolSize 补偿。

哨兵的划分只按一条界线:投递结果是否确定。ErrPublishNacked 与 ErrPublishUnroutable 均已收到 broker 的完整回应,框架因此能自行决断——前者退避重试,后者不重试因为结果必然相同。ErrPublishTimeout 与 ErrPublishUnknown 都没等到确认,消息可能已落地也可能没有,二者均不重试:重投会在调用方无感的情况下造成重复投递,能否容忍只有业务知道。ErrPublishUnknown 虽与 ErrPublishTimeout 同命,仍单独成类,因为二者的排查方向完全相反:超时指向 PublishTimeout 配置与 broker 负载,channel 断开指向网络与连接稳定性。合为一类会让 timeout 指标上涨时把人引向错误的修法。

3. 投递默认持久化 + mandatory ​

说明:原实现未设 DeliveryMode,而 QueueConf.Durable 默认为 true——典型的半持久化陷阱:broker 重启后 durable 队列尚存,消息全丢。mandatory: false 则让 routeKey 打错时被 broker 静默丢弃且 confirm 仍返回 ack。现在 routeKey 无匹配队列会返回 ErrPublishUnroutable 而非静默成功。

4. 删除 ConsumerConf.NoLocal、ChannelQosConf.Global 与 RabbitListenerConf.ContentType ​

diff
  ChannelQos:
    PrefetchCount: 10
-   Global: false
  ListenerQueues:
    - Name: demoA
-     NoLocal: true

说明:RabbitMQ 从未实现 no-local,服务端对该标志静默忽略——保留反而更危险:业务以为「已禁止消费自己推送的消息」,实际仍会收到。ContentType 在消费端配置中为死字段。Global 同样是个假旋钮:该标志只在同一 channel 内区分预取额度的归属(每 consumer 各一份,还是整个 channel 共享一份),从不跨 channel;而本库每队列独占 channel、且其上恰好一个 consumer,两种取值下额度归属完全相同——看上去能调流控,实际调不了。Qos 现固定传 false。上述字段删除后,多余的 yaml 键被忽略,存量配置不受影响。

5. Admin 新增 NewAdmin 与 Close ​

diff
-admin := rabbitmq.MustNewAdmin(conf)
+admin, err := rabbitmq.NewAdmin(conf)
+if err != nil {
+    return err
+}
+defer admin.Close()

说明:原实现无 Close,每次调用泄漏一条 TCP 连接;且打开 channel 失败时 log.Fatalf,连接不会被关闭。MustNewAdmin 保留。

6. MustNewListener 返回自有 Listener 接口 ​

diff
-func MustNewListener(c RabbitListenerConf, handler ConsumeHandler) queue.MessageQueue
+func MustNewListener(c RabbitListenerConf, handler ConsumeHandler, opts ...ListenerOption) Listener

说明:Listener 的方法集(Start() / Stop())与 go-zero 的 queue.MessageQueue 完全一致,因此仍可直接交给 service.ServiceGroup 托管,listeners.go 与 ServiceContext 无需改动。改动只为去掉公开签名对 go-zero 类型的依赖:本模块并未使用 queue 包的其他任何能力,暴露该类型会让调用方误以为存在 go-zero 的队列语义。同时新增 NewListener,与 NewSender 口径一致——原实现只有 Must 版本,配置错误只能靠 panic 暴露。

7. 链路上下文从消息信封改走 AMQP header ​

RabbitMsgBody 删除,Meta 新增 Headers:

diff
-type RabbitMsgBody struct {
-	Carrier *propagation.HeaderCarrier // OpenTelemetry 链路头
-	Msg     []byte                     // 业务消息内容
-}
+type Meta struct {
+	Queue    string
+	Exchange string
+	RouteKey string
+	Headers  map[string]any // 链路上下文由此透传
+}

生产端将链路上下文注入 Meta.Headers,最终落到 amqp.Publishing.Headers;消费端从 amqp.Delivery.Headers 提取。两端都不再触碰消息体,因此 rabbitmq_listener_parse_error_total 随信封一同删除——已不存在会解析失败的东西。

说明:把链路上下文塞进消息体,正是本模块只能与自己互通的根源。改由 header table 携带——OpenTelemetry 的消息语义约定对 RabbitMQ 正是如此规定——一次解决四件事:他方系统投递的消息可以消费了(见下文对应的修复项),消息体不再为多一层 JSON 与 encoding/json 对 []byte 字段的 33% base64 膨胀付费,链路真正能跨语言延续,管理界面里的消息体也可读了。

这是一次传输格式变更。 0.2.0 的消费端不会拆 0.1.x 的信封,而是把信封 JSON 原样交给 handler。因此共用同一队列的生产端与消费端需一同升级,且升级前应先把队列里信封形态的消息消完。

8. 连接类指标新增 endpoint 与 vhost label ​

rabbitmq_sender_reconnect_total、rabbitmq_sender_disconnect_total、rabbitmq_listener_reconnect_total、rabbitmq_listener_disconnect_total 原本完全没有 label,现统一携带 endpoint(host:port)与 vhost。本版本新增的两项池指标(rabbitmq_sender_pool_wait_duration_ms、rabbitmq_sender_pool_in_use)采用同一对维度。

理由:同一进程内可以存在多个 Sender 与 Listener,连的可能是不同集群,无维度的计数器会把它们全部堆到一条曲线上,报警时无从分辨是哪个 broker 在抖。vhost 未配时归一为 AMQP 默认值 /,避免同一个 vhost 因写法不同(省略或显式写 /)分裂成两条曲线。两个 label 均不含凭据:指标会被拉取到监控系统并长期留存。

这会改变既有曲线的基数。 查询上述四项指标的看板与报警规则需补上聚合(sum without (endpoint, vhost) (...) 或等价写法),否则升级前的单条曲线会变成按 broker 拆分的多条。

新增 ​

  • 单队列消费并发:ConsumerConf.Concurrency(默认 1,上限 256)。等于 1 为严格顺序模式,大于 1 启动对应数量的 worker 并行处理。须满足 Concurrency <= ChannelQos.PrefetchCount
  • 处理超时:ConsumerConf.Timeout(默认 0 不限)与 WithConsumeTimeout(d) option。原实现的中间件链根为裸 context.Background(),全程无 deadline。被 go-zero 托管时在 handler 中显式注入宿主的 RestConf.Timeout
  • TLS:RabbitConf.TLS,支持单向与双向认证。原实现硬编码 Scheme: "amqp"
  • 心跳:RabbitConf.Heartbeat(默认 30 秒),用于探测死链触发重连
  • 投递调优:RabbitSenderConf 新增 PoolSize(10) / PublishTimeout(5000) / MaxRetry(3)
  • 优雅停机上限:RabbitListenerConf.GracefulTimeout(默认 10000 毫秒)
  • 投递侧优雅关闭上限:RabbitSenderConf.GracefulTimeout(默认 10000 毫秒),与消费侧字段口径对称——Close 等待在途投递收到 broker 确认的上限
  • 中间件注入:消费侧 WithConsumeMiddlewares(...)、投递侧 WithPublishMiddlewares(...),追加位置均在内置链之后,受超时约束。投递侧位于重试编排之外,因此一次 Send 只执行一次,不随重试重复触发
  • 投递侧 option:WithPublishTimeout(d),与消费侧 WithConsumeTimeout(d) 对称,供宿主框架统一注入超时,优先级高于 RabbitSenderConf.PublishTimeout
  • 5 项指标:rabbitmq_sender_confirm_duration_ms、rabbitmq_sender_pool_wait_duration_ms、rabbitmq_sender_pool_in_use、rabbitmq_sender_retry_total、rabbitmq_listener_in_flight
  • 测试与 CI:单元测试(Validate 全分支、Chain 组合顺序、超时中间件、状态机迁移、channel 池借还)、集成测试(//go:build integration,真 broker)、.github/workflows/ci-rabbitmq.yml。本模块此前是唯一没有 CI 的模块

修复 ​

  • 并发 Send 共享单 channel:amqp091-go 的 Channel 非线程安全,原实现下所有并发投递共用一条 channel,协议帧交错会导致 channel 被 broker 关闭。改为 channel 池承载,池内每条 channel 同时只处理一条在途消息——NotifyReturn 不携带 deliveryTag,这也是正确归因不可路由退回的前提
  • Sender 的 conn/channel 数据竞争:原实现下 Send 裸读 q.channel,reconnect 裸写 q.channel = nil,Sender 无任何锁,可导致数据竞争与 nil dereference panic。现由读写锁保护,投递路径只读走读锁
  • Sender 重连不可中断:原实现固定 10 次 × 2s 死等,与 Listener 的指数退避两套哲学,且无法被停机信号中断。现统一为指数退避 + 可中断
  • Admin 泄漏连接:见上文破坏性变更 5
  • WaitGroup 跳代复用 panic 风险:listenerWg/taskWg 改为按代次分配。原实现下 reconnect 等待超时后 waiter 仍挂在 Wait() 上,新代对同一 wg Add,计数器归零时可触发 sync: WaitGroup misuse 直接打挂进程(触发条件:handler 卡死 + 连接抖动)
  • Stop 最坏耗时翻倍:reconnect 的「等旧协程退出」改为含停机信号的多路 select。原实现用裸 time.After,重连中收到停机需先等满 reconnect 的 GracefulTimeout 再等 Stop 自己的,容易超出停机宽限期
  • 他方投递的消息被静默丢弃:consumerTrace 无条件将每条消息体按信封反序列化,解析失败则返回 error,而「已执行的一律确认」规则又会把它变成 ack。于是 Java 服务投递的、或从管理界面手工投递的消息,handler 根本没被调用就被丢掉。现在消息体完全不再被解析
  • 中间件链自身 panic 使队列静默停摆:handle 的 panic 兜底位于 ack 决策之外,panic 后确认语句整体被跳过,该消息既不 Ack 也不 Reject,永久占住一个 prefetch 名额——累计到 PrefetchCount 条后该队列彻底停止收消息,而日志里只有 panic、没有任何停摆信号,直到重连或停机才释放。触发面不窄:WithConsumeMiddlewares 注入的业务中间件位于 consumerRecovery 之外,任一用户中间件 panic 都走这条路。现将兜底下沉一层(invoke)就地转为 error,ack 必然执行,与「已执行的一律确认」口径一致
  • ErrPublishUnknown 不说明原因:确认通道被关闭时只报一句「结果未知」,不带任何归因。而最常见的配置错误——exchange 名字打错——恰恰走这条路径,broker 给出的 404 NOT_FOUND 只出现在 channel 关闭通知这一路上。现 pubChannel 注册 NotifyClose,把 broker 给出的 code 与 reason 拼在错误末尾,最该可诊断的场景不再最不可诊断
  • 停机把在途投递变成 ErrPublishUnknown:Close 不做等待直接拆连接,已把帧写出的投递其确认通道随之被关闭——而停机钩子是 NewSender 自注册的,等于每次进程退出都在成批制造「结果未知」。现 Close 先在 GracefulTimeout 内等在途投递收到确认,再销毁 channel;窗口耗尽仍有未确认的,记一行 [RABBITMQ_STOP]
  • Close 之后的 Send 干等到投递超时:借用 channel 只在「空闲槽位」与「调用方 ctx」两路上等待,池关闭后槽位已被收走且不会再回填,这条投递只能干等到 PublishTimeout,最后报一个误导的「超时」。现借用同时在池的停机信号上等待,立即返回 ErrSenderClosed

变更 ​

  • Validate 统一为三条规则,每个字段只按一条处理:必填缺失或取值不可能正确 → 返回 error;存在安全默认值的非法值 → 回退默认并记录一行日志;超出协议或资源上限 → 返回 error。原实现混用「报错」与「静默回退」两种口径
  • 首次连接只尝试一次:配置错误应在启动时立刻暴露,运行期的连接故障才由重连负责自愈。Sender 与 Listener 口径一致
  • 超时配置只在调用方未给出时限时兜底:timeoutMiddleware 先判断传入 ctx 是否已带 deadline,已带则原样透传,不再无条件 context.WithTimeout 包一层。后者取「父 deadline 与配置值中较早者」,会把调用方显式要求的更长时限悄悄截断,使配置从兜底变成强制上限。消费侧的消息 ctx 由 Listener 从 context.Background() 派生,本身无 deadline,行为不受影响;受影响的是 Send——调用方 ctx 若已带 deadline(如在 go-zero rest handler 中),PublishTimeout 不再介入
  • 文件按职责拆分:conf.go / errors.go / const.go / message.go / middleware.go / metrics.go / conn.go / consumer.go / listener.go / chanpool.go / sender.go / admin.go。原 RabbitListener 单结构体承担连接管理、channel 生命周期、代次编排、消息分发、Ack 决策 5 类职责,16 个字段中含 4 个同步原语 + 3 个 atomic
  • Listener 生命周期改为显式状态机:stateNew → stateRunning → stateStopping → stateStopped,代次由分层 context 表达。原实现的状态判断散落于 7 处 closed.Load() 与 4 处 epoch.Load()

依赖升级 ​

  • github.com/rabbitmq/amqp091-go v1.11.0 → v1.13.0
  • go.opentelemetry.io/otel/sdk 由 indirect 提为直接依赖:链路传播往返测试需驱动真实的 TracerProvider
  • go directive 保持 1.24.0
  • example/ 独立为自有模块(example/go.mod,以 replace 指回 ../):示例依赖配置中心与注册中心,此前与库共处一个模块,在库目录下执行 go mod tidy 会把 consul 与 etcd 的依赖树写进本模块的 go.mod。独立后库目录下的 go mod tidy 与 go build ./... 均不再涉及示例
  • go.mod 与 go.sum 收敛:indirect 由 42 条降至 20 条,go.sum 由 139 行降至 85 行。清掉的是 0.1.x 遗留、当前已无人 import 的条目(gRPC、Zipkin 与 OTLP exporter、genproto、pyroscope、gonum、k8s.io/utils 等)。实际参与编译的传递依赖数不变(281 个包)——这些残留只存在于 go.mod 的声明里,不影响构建,但会让依赖审计与 SBOM 把一批与本库无关的包算进依赖面

文档 ​

  • README 与 readme-cn 按新模型重写,补齐投递语义、消费语义、超时体系、中间件、指标清单与升级指南
  • 明确 PrefetchCount 不是并发度:它是流控参数(由消息大小与网络 RTT 决定),并发度由 Concurrency 决定(由下游承载能力决定)
  • 明确 at-least-once 的代价:重试必然带来重复投递,消费侧必须幂等
  • 明确 deadline 是协作式的:handler 必须把 ctx 透传给下游阻塞调用,否则超时不生效
  • 明确消费侧与投递侧 ctx 来源不同导致的超时生效差异

与设计文档的偏离 ​

实现过程中有六处与最初的设计方案不同的决定:

  • recovery 位于中间件链最内层,设计文档将其列在最外层。置于最外层时 panic 会穿透 metrics 与 logging,导致 panic 的消息不计入 consume_total、也不产生一行日志——而 panic 恰是最需要被观测到的情形
  • 未实现 rabbitmq_listener_worker_in_use:该值可由 rabbitmq_listener_in_flight 除以 Concurrency 得出,独立 gauge 只会在每条消息的收尾路径上多两次原子写,且两个同源指标一旦漂移会互相矛盾
  • 未引入独立的 inflightWg:按代次分配的 taskWg 已表达「等待在途消息处理完」的语义,再加一个 waitgroup 会让「停机在等谁」变得含糊,而这正是原实现最难读的地方
  • 中间件注入点拆为对称的两个:设计文档只给了 WithMiddlewares(仅消费侧)。投递侧同样需要注入点,而单一名字无法表达它作用于哪一侧;两侧的执行语义也不同(投递侧位于重试编排之外,一次 Send 只执行一次),共用一个名字会掩盖这个差异
  • 未改动 cztctl 模板(设计文档 §8 「cztctl 联动」):cztctl 的 handler 模板由远程仓库提供,仓库内的 .tpl 并非生成时实际使用的那份,因此在本仓改它不会生效。宿主超时注入改为在文档中给出写法,由调用方在 handler 里显式添加
  • 链路上下文由 AMQP header 携带,而非消息信封:设计文档保留了信封(message.go 的职责、以及两个 trace 中间件的职责,均按包裹与拆包描述)。信封使每条被消费的消息都多一次 JSON 解析,而不是信封形态的消息会在没触及 handler 的情况下被确认掉。其所谓的代价——「信封 JSON 解析不受 deadline 约束,但解析为纯 CPU 且有界,可接受」——在已不存在解析的前提下自然失效

迁移 ​

  • 无需改动:配置中心的现有配置、listeners.go(生成文件)、ServiceContext
  • 需要改动:若曾自定义拦截器;Send 调用方若需区分错误类型;MustNewAdmin 的调用点需补 defer admin.Close();共用同一队列的生产端与消费端需一同升级,因为链路上下文已移出消息体(破坏性变更 7);查询重连 / 断链指标的看板与报警规则需补聚合(破坏性变更 8)
  • 建议改动:为存量 handler 补上宿主超时注入,即在 MustNewListener 调用处手工添加 rabbitmq.WithConsumeTimeout(...) 一行(imports 补 "time")。cztctl 的 handler 模板由远程仓库提供,本模块不介入;且 handler 文件在生成时已存在则跳过,存量服务无论如何都需手工补
  • 注意:rest.RestConf.Timeout 默认仅 3000ms。一旦注入,消息处理就会被隐式限在 3 秒内,消费场景通常需要在 yaml 中显式放大 Timeout

[0.1.5] - 2026-06-04 ​

依赖升级 ​

  • github.com/rabbitmq/amqp091-go v1.10.0 → v1.11.0
  • github.com/zeromicro/go-zero v1.10.0 → v1.10.2
  • go.opentelemetry.io/otel* v1.24.0 → v1.40.0(主动不升 v1.44+,避免强制要求 go 1.25)
  • 同步 go mod tidy 清理无用 indirect 依赖
  • go directive 保持 1.24.0

[0.1.4] - 2026-03-20 ​

破坏性变更 ​

1. MustNewSender 去掉 ctx 参数 ​

diff
- rabbitmq.MustNewSender(ctx, conf)
+ rabbitmq.MustNewSender(conf)

说明: 与 MustNewListener 保持一致,初始化时不需要 ctx

[0.1.3] - 2026-03-20 ​

新增功能 ​

1. 连接可靠性增强 ​

  • NotifyClose 监听: Sender 和 Listener 同时监听 Connection 和 Channel 的关闭事件
  • 自动重连: 连接断开后自动尝试重连(最多 10 次)
  • 线程安全: 使用 atomic.Bool 保证 closed 标志线程安全
  • 双重检查: 避免重复重连(加锁前检查 + 加锁后检查)
  • 优雅停机: 收到 go-zero proc 停止信号后不再重连

2. Sender 优雅停机 ​

  • 自动注册 proc.AddShutdownListener 关闭钩子
  • 停机时标记 closed,不再重连

3. 监控指标大幅扩展 ​

Sender 指标(5个):

指标名类型Labels说明
rabbitmq_sender_send_totalCounterexchange, route_key, status发送总数
rabbitmq_sender_send_duration_msHistogramexchange, route_key发送耗时
rabbitmq_sender_send_size_bytesHistogramexchange, route_key消息大小
rabbitmq_sender_reconnect_totalCounter-重连次数
rabbitmq_sender_disconnect_totalCounter-掉线次数

Listener 指标(9个):

指标名类型Labels说明
rabbitmq_listener_consume_totalCounterqueue, status消费总数
rabbitmq_listener_consume_duration_msHistogramqueue消费耗时
rabbitmq_listener_consume_size_bytesHistogramqueue消息大小
rabbitmq_listener_in_flightGaugequeue当前处理中消息数
rabbitmq_listener_parse_error_totalCounterqueue解析失败数
rabbitmq_listener_panic_totalCounterqueuePanic 次数
rabbitmq_listener_ack_totalCounterqueue, typeACK/Reject 计数
rabbitmq_listener_reconnect_totalCounter-重连次数
rabbitmq_listener_disconnect_totalCounter-掉线次数

4. 拦截器优化 ​

  • 调整顺序为:recovery → prometheus → logging → trace
  • 确保所有拦截器都能执行(即使 trace 解析失败)

5. 其他优化 ​

  • StartConsumerSpan 增加 carrier nil 防护
  • 消息解析移至 traceInterceptor,避免重复解析
  • ACK/Reject 逻辑统一放到 processMessage 外层

删除的功能 ​

  • 删除 client.go 文件
  • 删除 parseMessage 方法(消息解析移至 traceInterceptor)
  • 删除 requeueMessage 重复消费逻辑

1. 指标名称变更 ​

diff
- mq_consume_total
+ rabbitmq_listener_consume_total

- mq_consume_duration_ms
+ rabbitmq_listener_consume_duration_ms

影响: 需要更新 Prometheus 查询和 Grafana 仪表盘

2. client.go 已删除 ​

diff
- client, err := rabbitmq.NewClient(ctx, conf)
+ sender, err := rabbitmq.NewSender(conf)
// 或
+ sender := rabbitmq.MustNewSender(conf)

3. Sender 自动注册 shutdown hook ​

  • NewSender 和 MustNewSender 会自动注册 proc.AddShutdownListener
  • 在 go-zero 环境下不需要手动调用 Close()
  • 非 go-zero 环境仍需手动调用 Close()

4. MustNewListener 去掉 ctx 参数 ​

diff
- rabbitmq.MustNewListener(ctx, conf, handler)
+ rabbitmq.MustNewListener(conf, handler)

说明: 消费者内部直接使用 context.Background() 派生,外部传入的 ctx 无实际作用

Aliyun Gateway ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.0.3] - 2026-06-14 ​

修复 ​

  • MultipartBuilder.File 忽略 CreateFormFile 错误可能导致 nil panic,改为错误积累模式
  • MultipartBuilder.Build() 签名变更为 (contentType string, body []byte, err error),统一返回构建过程中的错误

优化 ​

  • uuid.New().String() 替换为 uuid.NewString(),减少中间 UUID 结构体分配

[0.0.2] - 2026-06-14 ​

优化 ​

  • sortedQuery 改用 strings.IndexByte 零分配遍历,消除 strings.Split 的 []string 分配
  • sortedQuery 消除冗余 result 切片,改用 strings.Builder 直接输出;map/slice 预分配容量
  • signOption 对 form/multipart body 利用 GetBody 跳过全量缓冲,避免大文件上传时的无谓内存拷贝
  • []byte(AppSecret) 在 NewClient 时闭包外预算一次,不再每次签名重复转换
  • strings.Join(signHeaders) 提升为包级 signHeadersValue,只算一次

修复 ​

  • signRequest 中 Date 和 Timestamp 现共享同一次 time.Now(),消除跨毫秒边界导致两者不一致的隐患

[0.0.1] - 2026-06-13 ​

新增 ​

  • 阿里云 API 网关 Go 客户端,基于 go-zero httpc 封装,自动完成 HMAC-SHA256 v1 签名
  • Do 方法:结构化请求,支持 path / form / json / header tag 自动映射
  • DoRaw 方法:原始字节请求,支持文件上传、XML、纯文本等自定义 body
  • WithClient Option:注入自定义 *http.Client(TLS、连接池等)
  • Parse 函数:封装 go-zero httpc.Parse,接收 Do/DoRaw 返回的 (resp, err),自动解析 JSON 响应并关闭 Body
  • NewMultipart() / MultipartBuilder:链式构造 multipart/form-data 请求体
  • Conf.Validate() 自动去除 Host 尾部多余 /
  • 底层集成 go-zero 熔断器,同一 Host 自动共享

Kong HMAC Auth ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[0.0.1] - 2026-06-18 ​

新增 ​

  • Kong HMAC Auth Go 客户端,基于 go-zero httpc 封装,自动完成 HMAC 签名,遵循 Kong HMAC Auth 插件 官方规范
  • Do 方法:结构化请求,支持 path / form / json / header tag 自动映射
  • DoRaw 方法:原始字节请求,支持文件上传、XML、纯文本等自定义 body
  • WithClient Option:注入自定义 *http.Client(TLS、连接池等)
  • Parse 函数:封装 go-zero httpc.Parse,接收 Do/DoRaw 返回的 (resp, err),自动解析 JSON 响应并关闭 Body
  • 支持 5 种 HMAC 算法:hmac-sha1、hmac-sha224(Kong 3.14+)、hmac-sha256、hmac-sha384、hmac-sha512
  • @request-target 伪头支持,值为 method /path?query(method 小写)
  • Conf.Headers 可自定义参与签名的 header 列表,默认 ["date", "@request-target"]
  • Digest 头自动计算(SHA-256=base64(sha256(body))),支持空 body 零长度摘要,form / multipart 跳过
  • Date 头自动注入(GMT 格式),用于 Kong clock skew 校验
  • User-Agent 头自动注入(Go-Kong-HmacAuth-Client),可被调用方覆盖
  • Host 头注入与签名取值统一使用 r.Host,确保签名值与实际发送一致
  • Conf.Algorithm 和 Conf.Headers 支持 go-zero optional / default tag,YAML 配置可省略
  • 底层集成 go-zero 熔断器、tracing、metrics,同一 Host 自动共享

cztctl ​

English

所有版本变更记录。格式基于 Keep a Changelog。

[1.10.11] - 2026-08-03 ​

变更 ​

  • 破坏性变更 cztctl api rabbitmq 生成的 handler 与 logic 改为面向 czt-contrib/mq/rabbitmq v0.2.0+,本版本生成的代码在更早的库版本上编译不过
    • handler 闭包与 logic 构造函数均新增 meta rabbitmq.Meta 参数,业务通过 l.meta.Queue 判断消息来自哪个队列,一个 handler 挂多队列才得以据此分流
    • handler 无条件注入 rabbitmq.WithConsumeTimeout(time.Duration(svcCtx.Config.Timeout)*time.Millisecond),使 MQ 消费与 HTTP 请求共用 RestConf.Timeout 这一个时限。注意此 option 优先级高于配置文件中的 per-queue ListenerQueues[].Timeout,后者在生成的服务里不再生效
    • DSL 声明了消息体类型时(如 order.created(GOrderOrderCreatedReq)),由 handler 执行 json.Unmarshal,logic 业务方法收 *types.XxxReq;未声明类型的 route(如 payment.success)生成的业务方法不带任何参数,签名由 func(req []byte) error 变为 func() error,原先直接读字节流的业务代码需改为在 DSL 中声明类型
  • github.com/zeromicro/go-zero 升至 v1.10.3,github.com/zeromicro/go-zero/tools/goctl 升至 v1.10.2
    • api/swagger 依赖 goctl 的 api/spec 与 pkg/parser/api/parser,本次 spec.Type 与 parser.Parse 均无签名变化,调用处无需适配
    • README 中 --version 与 cztctl env 的示例输出已同步刷新(1.10.11、go-zero v1.10.3)

修复 ​

  • 修复 DSL 声明消息体类型时生成的代码编译失败:internal/types 在 handler 与 logic 中均被 import 却从未被引用,触发 Go 的未使用 import 检查
    • 现仅在 route 确实声明了请求类型时才引入 internal/types
  • 修复报错文本含 % 时被扭曲:拼接后的文本被当作格式串传给 fmt.Errorf,使 Foo%sBar 变成 Foo%!s(MISSING)Bar;现改走 errors.New,原样输出(errorManager.error、Parser.CheckErrors)
    • 同时消除 Go 1.24 vet 报为错误的 non-constant format string in call to fmt.Errorf,此前它使 go vet ./... 与 go test ./... 持红

[1.10.10] - 2026-06-18 ​

修复 ​

  • 修复 cztctl rpc sdk 生成 .kong.proto 时,proto 文件为 CRLF(Windows)换行导致 rpc 行分号未被去除、注解错位的问题
    • 根因:strings.Split(data, "\n") 切行后行尾残留 \r,使 TrimSuffix(";") 末尾匹配到 \r 而非 ;,分号保留、 { 错位
    • 修复:读取时统一将 \r\n / \r 规范化为 \n,从源头消除 \r 对后缀判断的干扰

变更 ​

  • rpcMethodRe 正则改用 returns 关键字识别 rpc 方法声明,比原 \( 括号匹配更语义化(有 returns 才是真正的 rpc 方法)

[1.10.9] - 2026-06-18 ​

修复 ​

  • 修复 cztctl rpc sdk 生成 .kong.proto 时,rpc 行使用 {} 空块写法导致注解错位的问题
    • 原判断 strings.Contains(line, "{") 将 {} 空块误判为已有开括号,导致 option (google.api.http) 注解游离到块外并多出闭合括号
    • 改为先剥除 {} 的闭合括号,再用 HasSuffix("{") 判断,覆盖分号 / 开括号 / 空块三种 rpc 行风格

[1.10.8] - 2026-06-16 ​

新增 ​

  • cztctl rpc sdk 自动生成 .kong.proto 文件(Kong gRPC-gateway HTTP 注解)
    • 执行 cztctl rpc sdk 时自动在 _sdk/ 目录中生成与 proto 同名的 .kong.proto 变体
    • 自动添加 import "google/api/annotations.proto"
    • 为每个 rpc 方法生成 option (google.api.http) 注解
    • 路径规则:/{ServiceName}/{RpcMethodName}
    • HTTP 方法统一 POST + body: "*"
    • 若 proto 已包含 annotations import 则跳过插入

[1.10.7] - 2026-06-04 ​

变更 ​

  • cztctl api cron 生成器适配 cron v0.1.0 新 API
    • CronAdd 一体化签名:调用时直接传入 handler,内部完成注册 + 调度,不再需要额外 Add
    • 定时任务默认注入 asynq.Timeout(time.Duration(serverCtx.Config.Timeout) * time.Millisecond),超时由 go-zero RestConf.Timeout 接管
    • 多个定时任务时抽取 timeoutOpt 局部变量,避免重复书写超时表达式
    • MaxRetry 仍按 per-task CronRetry 配置
    • 非定时任务(外部投递消费端)保持仅注册 handler,不变

依赖升级 ​

  • github.com/zeromicro/go-zero v1.10.1 → v1.10.2
  • github.com/zeromicro/go-zero/tools/goctl 保持 v1.10.1(上游未跟版发 v1.10.2)

[1.10.6] - 2026-05-27 ​

新增 ​

  • cztctl rpc sdk — 将 RPC 客户端代码自动生成为独立 Go 模块并发布到 Git 仓库
    • 自动克隆/初始化 SDK 仓库,支持 HTTPS + Token 认证
    • 递归解析 proto import 依赖,自动复制所有相关 proto 文件
    • 调用 goctl 生成客户端代码,清理服务端代码仅保留 client/
    • 自动执行 go mod tidy 整理依赖
    • SemVer 版本号管理:自动递增 patch,patch 到 99 自动进位 minor
    • Git 自动提交、打标签、推送(分支 + 标签)
    • 支持 --remote / --branch goctl 远程模板透传
    • 支持 --multiple 多服务模式
    • 支持 --goproxy 自定义代理
    • 支持 --repo-branch 指定 SDK 仓库分支(默认 main)
    • goctl 版本前置检查(未安装为硬错误,版本低为软警告)

[1.10.5] - 2026-04-09 ​

修复 ​

  • 修复 cztctl api cron 生成 workers.go 时,CronAdd 错误包含 handler 参数的问题
    • 定时任务(@cron)现在正确生成两行:先 Add(pattern, handler) 注册处理函数,再 CronAdd(cronExpr, pattern, opts...) 注册定时调度
    • 纯异步任务(无 @cron)仍只生成 Add(pattern, handler)
  • 修复 go.sum 中 goctl 校验和不匹配导致 go install 失败的问题

变更 ​

  • 升级 goctl 依赖 v1.10.0 → v1.10.1
  • 升级 go-zero 依赖 v1.10.0 → v1.10.1

[1.10.3] - 2026-04-07 ​

新增 ​

  • .cron 路由名支持 -(横杠)和 :(冒号)分隔符,如 sync-order、email:send
  • .rabbitmq 路由名支持 -(横杠)分隔符,如 payment-refund、order.pay-callback
  • 路由名分隔符按文件类型语义隔离:.cron 仅允许 - :,.rabbitmq 仅允许 . -

[1.10.2] - 2026-03-22 ​

新增 ​

  • cztctl api swagger — 从 .api 文件生成 Swagger 2.0 文档
    • 支持 info 块全量属性映射(title / description / version / host / basePath / schemes 等)
    • 支持 @server 注解(tags / summary / prefix / group / deprecated / operationId / authType)
    • 支持 validate tag 自动生成参数约束注释
    • 支持字段头部多行注释解析
    • 支持 useDefinitions 模式($ref 引用)
    • 支持 wrapCodeMsg 响应包装
    • 支持 JSON / YAML 双格式输出
  • cztctl api cron — 从 .cron 文件生成分布式定时任务服务
    • 基于 czt-contrib/cron 框架
    • 支持内部定时任务(@cron 表达式 + @cronRetry 重试)
    • 支持外部触发任务(无 @cron,通过 asynq.Client.Enqueue 触发)
    • 生成完整目录结构:etc / config / handler / logic / svc / types / worker / main
    • 支持 @doc 字符串与 KV 两种写法
    • 支持 @server 分组(group / tags / summary / middleware)
    • 支持 --remote / --branch 远程模板
    • 支持 --style 文件命名风格(gozero / go_zero / goZero)
  • cztctl api rabbitmq — 从 .rabbitmq 文件生成 RabbitMQ 消费者服务
    • 基于 czt-contrib/mq/rabbitmq 框架
    • 支持点分隔队列名称(如 order.created、payment.refund.success)
    • 支持可选消息参数类型
    • 生成完整目录结构:etc / config / handler / logic / svc / types / listener / main
    • 支持 --remote / --branch 远程模板
    • 支持 --style 文件命名风格
  • cztctl env — 环境变量管理
    • 查看当前环境变量(CZTCTL_OS / CZTCTL_ARCH / CZTCTL_HOME / CZTCTL_CACHE / CZTCTL_VERSION)
    • 编辑环境变量(cztctl env -w KEY=VALUE)
    • CZTCTL_EXPERIMENTAL 开关:off 使用 ANTLR4 解析器,on 使用手写递归下降解析器
  • DSL 语法解析
    • .cron 和 .rabbitmq 共享基础语法:syntax / info / import / type / @server
    • ANTLR4 解析器(默认)+ 手写递归下降解析器(实验性)
    • 支持完整类型系统:基本类型、切片、map、指针、嵌套结构体、struct tag
    • 支持 import 跨文件类型引用
  • 版本号规则:v<go-zero主版本>.<微版本>(当前基于 go-zero v1.10.0)