跳转至正文

Horizon ​


简介 ​

PrismGo Horizon 提供队列运行时监控与 supervisor 管理能力,对应 Laravel Horizon 的核心功能。它围绕 github.com/prismgo/framework/queue 的事件、worker、failed store 和 batch store 构建,负责队列运行视图、控制命令、指标聚合、Dashboard API 和进程心跳,不替代队列 driver 本身。

核心进程模型:

概念说明
MasterHorizon 主进程,加载当前环境 supervisor 配置并派生子进程
Supervisor一组队列 worker 的配置单元,声明 connection、queue、进程数、重试和超时策略
Worker真实消费队列任务的 horizon:work 子进程

Horizon 的状态与队列消息分离。队列消息仍由 github.com/prismgo/framework/queue 的 Redis、RabbitMQ 或其他 driver 管理;Horizon Store 只保存监控和控制数据。

安装 ​

Horizon 是独立的可选 module。先安装依赖:

bash
go get github.com/prismgo/horizon@latest

然后在应用 Builder 的扩展层注册包级 Provider:

go
import (
    "github.com/prismgo/framework/foundation"
    "github.com/prismgo/horizon"
)

app := foundation.Configure(basePath...).
    WithExtensionProviders(horizon.ServiceProvider{}).
    WithProviders(Providers()...).
    Create()

horizon.ServiceProvider 在框架默认 Provider 之后、业务 Provider 之前执行 Register 和 Boot;注册过程不会连接 Redis 或 RabbitMQ。随后使用 horizon:install 命令生成配置文件和应用 Provider 桩文件:

bash
go run ./ horizon:install

该命令会在文件不存在时创建 config/horizon.go 和 app/providers/horizon_service_provider.go,已存在的文件不会被覆盖。把生成的 app/providers.HorizonServiceProvider{} 加入 bootstrap/provider.go 返回的业务 Provider 列表,用于挂载 Dashboard 路由和应用鉴权;它与上面的包级扩展 Provider 职责不同。

Dashboard 资源已内嵌到二进制中,无需额外的 publish 步骤。

配置 ​

配置入口在 config/horizon.go。所有配置通过 horizon 命名空间注册,支持环境变量覆盖。

基础配置 ​

配置键环境变量默认值说明
horizon.useHORIZON_STOREredisHorizon Store 类型。生产推荐 redis;测试可使用 memory
horizon.pathHORIZON_PATHhorizonDashboard 和内部 API 的挂载前缀,不包含首尾斜杠
horizon.connectionHORIZON_CONNECTIONdefaultHorizon Redis Store 使用的 Redis 连接名,独立于 queue/cache/session 连接
horizon.prefixHORIZON_PREFIXprismgo_horizonHorizon Store 的 key 前缀,应与业务队列 key 前缀区分
horizon.encodingHORIZON_ENCODING空Store record 的 Payload Encoding 名称;空值继承 encoding.default(默认 msgpack),可显式设为 json 便于排障
horizon.heartbeat_ttl_secondsHORIZON_HEARTBEAT_TTL_SECONDS60master/supervisor/worker heartbeat 被视为存活的时间窗口(秒)。超过该窗口未刷新 heartbeat 的进程会被标记为 stale
horizon.fast_termination—falseterminate 时是否允许新 master 先启动
horizon.memory_limit—128Horizon worker 默认内存限制(MB)
horizon.waits—空按 connection:queue 保存长等待阈值秒数,供 waits 观测复用

环境选择 ​

Horizon 按以下优先级确定当前环境名:

  1. horizon.environment — 允许 Horizon 独立覆盖应用环境
  2. app.env — 项目级配置来源
  3. APP_ENV 环境变量 — 兼容 fallback
  4. 默认值 production

环境名用于从 horizon.environments 中选择对应的 supervisor 配置。环境匹配支持 Laravel Str::is 风格的通配符,例如 production-* 可以匹配 production-web、production-worker 等环境名,精确匹配优先于通配匹配。

Supervisor 配置 ​

horizon.defaults 是所有环境共享的 supervisor 基线;horizon.environments.{env} 中的同名 supervisor 会覆盖 defaults 中的字段。只存在于 environment 中的 supervisor 也会被解析,便于按环境新增队列消费组。

配置字段 ​

字段类型默认值说明
connectionstring必填队列连接名,决定 worker 从哪个 queue connection 取任务
queuestring 或 []string必填队列名称列表,支持逗号分隔字符串或数组。解析后会去空白、去重并保持配置顺序
balancestringfalse负载均衡策略:false、simple 或 auto
min_processesint0supervisor 最小 worker 数
max_processesint0supervisor 最大 worker 数,必须 >= min_processes
triesint0单个任务最大尝试次数,达到后进入 failed store
timeoutint0单个任务执行超时秒数
sleepint0空队列轮询间隔秒数
max_jobsint0worker 处理指定任务数后退出,0 表示不限制
max_timeint0worker 运行指定秒数后退出,0 表示不限制
retry_afterint0reserved 任务重新可见窗口秒数,应始终大于 timeout,避免同一任务被并发重复消费
backoffint 或 []int空失败重试退避秒数列表,支持单个数字、逗号分隔字符串或数组
stop_when_emptyboolfalse队列为空后 worker 是否退出,适合一次性消费场景
memoryint0worker 内存限制 MB(兼容字段,当前 Go 实现只解析和展示)
niceint0进程优先级(兼容字段,当前 Go 实现只解析和展示)
auto_scaling_strategystringtimeauto balance 使用的策略:time(按预计清空时间)或 size(按队列长度)
balance_max_shiftint1auto balance 单次扩缩容最多移动的 worker 数,限制扩缩容幅度
balance_cooldownint3两次 auto balance 计算之间的最小间隔秒数,降低扩缩容抖动

注意:配置只支持 snake_case 字段名。camelCase 字段(如 maxProcesses、minProcesses、retryAfter 等)会在解析时报错,并提示使用对应的 snake_case 名称。

配置示例 ​

go
"defaults": map[string]interface{}{
    "supervisor-default": map[string]interface{}{
        "connection":    "redis",
        "queue":         []interface{}{"high", "default"},
        "balance":       "auto",
        "min_processes": 1,
        "max_processes": 4,
        "tries":         3,
        "timeout":       60,
        "retry_after":   90,
        "sleep":         3,
    },
},
"environments": map[string]interface{}{
    "production": map[string]interface{}{
        "supervisor-default": map[string]interface{}{
            "max_processes": 10,
        },
        "supervisor-notifications": map[string]interface{}{
            "connection":    "redis",
            "queue":         "notifications",
            "balance":       "false",
            "min_processes": 2,
            "max_processes": 2,
            "tries":         3,
            "timeout":       30,
        },
    },
},

场景建议 ​

场景建议
本地开发max_processes=1,降低并发带来的调试噪声
普通生产队列balance=auto,min_processes=1,按吞吐设置 max_processes
高优先级通知/支付队列单独 supervisor,独立 queue 和 max_processes
一次性补偿任务stop_when_empty=true,配合较小 max_time
长任务增大 timeout,并同步增大 retry_after

负载均衡策略 ​

Horizon 支持三种负载均衡策略,对应 Laravel Horizon 的 balance 配置:

balance=false(默认) ​

不做自动均衡。所有配置队列由一个 process pool 统一消费,worker 数量根据队列积压在 min_processes 与 max_processes 之间调整。适用于每个队列固定进程数或不需要自动调度的场景。

balance=simple ​

在配置队列间做固定分配。每个队列获得 max_processes / len(queues) 个 worker,结果被限制在 [min_processes, max_processes] 范围内。适用于多队列固定简单分配的场景。

balance=auto ​

根据队列 workload 在 min_processes 与 max_processes 间动态调整 worker 数量。受 balance_max_shift 和 balance_cooldown 约束,避免扩缩容过猛或抖动。

auto balance 的 workload 计算由 auto_scaling_strategy 决定:

策略计算方式适用场景
time(默认)weight = ready_jobs × avg_runtime更关心等待时间,贴近 Laravel 默认语义
sizeweight = ready_jobs更关心堆积数量

运行 Horizon ​

启动 Master ​

生产通常由进程管理器启动 horizon master:

bash
go run ./ horizon --environment=production

--environment 指定 Horizon 环境名,为空时由已加载配置决定实际运行环境。Master 进程会加载当前环境的 supervisor 配置并派生 supervisor 子进程。

启动 Worker ​

Worker 通常由 supervisor 自动派生,也可以手动运行:

bash
go run ./ horizon:work redis --queue=default --tries=3 --timeout=60

horizon:work 支持以下选项:

选项类型默认值说明
--namestring空Worker 名称
--queuestringdefault监听的队列名,允许逗号分隔
--connection位置参数空队列连接名
--backoffstring0退避策略
--retry-afterint90任务重试保留窗口(秒)
--max-jobsint0单 worker 最大处理任务数,0 为不限制
--max-timeint0单 worker 最大运行秒数,0 为不限制
--forceboolfalse强制运行标志
--memoryint0内存限制(MB),0 为不限制
--onceboolfalse只处理一个任务后退出
--stop-when-emptyboolfalse队列空时停止
--sleepint3空队列时休眠秒数
--restint0任务间休息秒数
--supervisorstring空所属 supervisor 名称
--timeoutint60单任务超时秒数
--triesint1最大重试次数
--jsonboolfalseJSON 输出模式
--environmentstring空Horizon 环境名
--prefixstring空Store key 前缀

本地开发监听 ​

bash
go run ./ horizon:listen

horizon:listen 是本地开发辅助命令,监听文件变化并重启 Horizon。支持以下选项:

选项类型默认值说明
--environmentstringlocalHorizon 环境名
--pollint1000文件轮询间隔(毫秒)

注意:horizon:listen 仅适用于本地开发,不推荐在生产环境使用。

控制命令 ​

暂停与恢复 ​

暂停所有 supervisor:

bash
go run ./ horizon:pause

恢复所有 supervisor:

bash
go run ./ horizon:continue

暂停指定 supervisor:

bash
go run ./ horizon:pause-supervisor supervisor-default

恢复指定 supervisor:

bash
go run ./ horizon:continue-supervisor supervisor-default

暂停/恢复通过 Store 控制标记实现,不会直接终止进程。暂停后的 worker 不会消费新任务,但已开始的任务会继续执行完成。

优雅终止 ​

bash
go run ./ horizon:terminate
go run ./ horizon:terminate --wait

--wait 标志控制终止等待策略。terminate 请求的优先级高于 pause,写入后会通知 fresh master/supervisor 尽快退出。

诊断命令 ​

命令说明
horizon:status显示全局运行状态快照,包括状态、暂停/终止标记、supervisor/worker 计数和 stale 计数
horizon:list列出运行中的 master machines,显示 Name、PID、Supervisors、Status
horizon:supervisors列出所有 supervisor 的基础状态
horizon:supervisor-status <name>显示指定 supervisor 的详细状态,包括 Pools、Connection、Queues 等
horizon:timeout [environment]显示指定环境下的最大 worker timeout 秒数,默认 production
horizon:stale列出所有 heartbeat 超过 TTL 的 stale 进程(master/supervisor/worker),只读不写

维护命令 ​

命令说明
horizon:snapshot持久化队列长度快照和 collector 当前事件派生 metrics 到 Store
horizon:clear-metrics清理 Store 中的事件派生 metrics 和 collector 内存聚合。不清除 heartbeat、控制标记、队列数据或 failed records
horizon:clear <connection> --queue=<name> --force清空由当前环境 supervisor 配置覆盖的队列。必须传入 --force 标志
horizon:forget <id>删除指定 failed job 记录
horizon:forget --all删除所有 failed job 记录
horizon:purge --signal=SIGTERM清理不再属于 active supervisor pool 的孤儿 worker 进程

Dashboard ​

Dashboard 路径由 horizon.path 控制,默认是 /horizon。内部 API 使用同一前缀下的只读接口。

路由注册 ​

在应用路由注册阶段调用 RegisterHTTPRoutes:

go
horizon.RegisterHTTPRoutes(horizon.HTTPOptions{
    Manager: manager,
    Auth:    []gin.HandlerFunc{authMiddleware, permissionMiddleware},
})

HTTPOptions 字段说明:

字段类型说明
Manager*Manager提供 Horizon 静态配置和 Store 解析;为空时使用默认 Manager
Auth[]gin.HandlerFunc业务应用注入的认证中间件,通常包含登录校验、权限加载和 horizon.view 校验

权限控制 ​

Dashboard 和 API 共用 horizon.view 权限标识。当前只开放观察面,不开放 retry、pause、terminate 等写入口。生产环境建议在业务路由层为 /horizon 增加鉴权和 IP allowlist。

HTTP API 参考 ​

所有 API 为只读 GET 接口,挂载在 /{horizon.path}/api 前缀下。支持分页的接口接受 page 和 page_size 查询参数。

全局状态 ​

GET /{horizon.path}/api/status

返回 Dashboard 首屏需要的轻量运行状态摘要,包括全局状态、队列长度和能力列表。

响应示例:

json
{
  "status": {
    "status": "running",
    "global_paused": false,
    "terminate_requested": false,
    "supervisor_count": 2,
    "worker_count": 8,
    "stale_supervisor_count": 0,
    "stale_worker_count": 0,
    "queue_count": 3,
    "jobs_per_minute": 150.5,
    "jobs_past_hour": 9030,
    "total_processed": 25000
  },
  "queue_lengths": { "captured_at": "...", "queues": [...] },
  "capabilities": {
    "batches": "supported",
    "high_value_detail": "supported",
    "queue_lengths": "supported",
    "event_metrics": "supported",
    "waits": "supported",
    "http_writes": "unsupported"
  }
}

Master 列表 ​

GET /{horizon.path}/api/masters?page=1&page_size=25

返回运行中的 master 进程列表,包含进程身份、heartbeat、goroutine 和内存指标。

Supervisor 列表 ​

GET /{horizon.path}/api/supervisors?page=1&page_size=25

返回 supervisor 列表,包含名称、状态、worker 数、connection、queues 和 process pool 状态。

Worker 列表 ​

GET /{horizon.path}/api/workers?page=1&page_size=25

返回 worker 列表,包含进程身份、状态、配置队列和资源指标。

Stale 进程 ​

GET /{horizon.path}/api/stale?page=1&page_size=25

返回 heartbeat 超过 TTL 的 stale supervisor 和 worker 列表。

队列视图 ​

GET /{horizon.path}/api/queues?page=1&page_size=25

返回队列聚合视图,结合队列长度和 event metrics 展示每个 connection:queue 的吞吐、等待和运行时信息。

Metrics 当前值 ​

GET /{horizon.path}/api/metrics/current

返回当前 event metrics 聚合视图。默认展示最近 24 小时数据。

查询参数:

参数类型说明
fromRFC3339时间范围下界(窗口 WindowEnd > From)
toRFC3339时间范围上界(窗口 WindowStart < To)
source_hoststring按主机精确过滤
source_environmentstring按 Horizon environment 精确过滤
source_supervisorstring按 supervisor 精确过滤
connectionstring按 queue connection 精确过滤
queuestring按 queue 名称精确过滤
source_detailsbool是否包含来源分片明细,默认省略
summary_onlybool只返回 queue 聚合 summary
page / page_sizeint分页参数

时间范围不能超过 24 小时。from 必须早于 to。所有时间参数必须带时区。

Metrics 来源 ​

GET /{horizon.path}/api/metrics/sources

返回 event metrics 的来源维度列表,用于 Dashboard 下钻。支持与 /metrics/current 相同的过滤参数。

Metrics 历史 ​

GET /{horizon.path}/api/metrics/history/{kind}/{key}

返回指定维度的 metrics 历史数据点。当前 kind 只支持 queue,key 格式为 connection:queue。

查询参数与 /metrics/current 相同。

高价值诊断明细列表 ​

GET /{horizon.path}/api/high-value-detail

返回 failed、poison、slow_job 三类高价值诊断摘要列表。

查询参数:

参数类型说明
kindstring过滤类型:failed、poison 或 slow_job
occurred_fromRFC3339事件发生时间下界
occurred_toRFC3339事件发生时间上界
page / page_sizeint分页参数

高价值诊断明细详情 ​

GET /{horizon.path}/api/high-value-detail/{id}

返回指定 ID 的诊断摘要详情。未找到时返回 404。

批次摘要列表 ​

GET /{horizon.path}/api/batches

返回批次安全摘要列表,支持 query 或 search 参数按 ID 或名称搜索。

批次详情 ​

GET /{horizon.path}/api/batches/{id}

返回指定 ID 的批次摘要详情。未找到时返回 404。

观测配置 ​

Horizon 通过 queue events 生成等待时间、运行时间、失败、poison、批次摘要和队列长度指标。观测配置集中在 horizon.observability。

预设 ​

预设说明
full开发和排障优先,保留完整观测能力,全量采样
production_light保留核心健康、队列长度和队列级聚合,降低 per-job 成本,10% 采样率
minimal只保留核心健康和队列长度,关闭 event_metrics 和 per-job 明细

预设只提供默认值,所有显式子字段都会覆盖预设。这样可以从 production_light 出发逐项打开诊断能力。

观测能力开关 ​

配置键环境变量默认值(full)说明
observability.presetHORIZON_OBSERVABILITY_PRESETfull观测预设
observability.event_metricsHORIZON_OBSERVABILITY_EVENT_METRICStrue是否采集 queue event 派生的队列级 counters 和 runtime 聚合
observability.waitsHORIZON_OBSERVABILITY_WAITStrue是否保留排队等待时间状态和 long wait 事件。需要 event_metrics=true 且 queued_waits_max>0
observability.batch_summariesHORIZON_OBSERVABILITY_BATCH_SUMMARIEStrue是否保存 batch 只读摘要
observability.process_healthHORIZON_OBSERVABILITY_PROCESS_HEALTHtrue是否启用 heartbeat、状态和控制标记等核心健康能力
observability.queue_lengthsHORIZON_OBSERVABILITY_QUEUE_LENGTHStrue是否采样队列后端长度
observability.queued_waits_maxHORIZON_OBSERVABILITY_QUEUED_WAITS_MAX10000等待时间 per-job 状态数量上限,0 表示不保留
observability.processing_spans_maxHORIZON_OBSERVABILITY_PROCESSING_SPANS_MAX10000processing span 数量上限,0 表示不保存
observability.processing_cleanup_interval_secondsHORIZON_OBSERVABILITY_PROCESSING_CLEANUP_INTERVAL_SECONDS60processing span TTL 清理节流间隔秒数

能力开关之间存在依赖关系:

  • waits 需要 event_metrics=true 且 queued_waits_max>0
  • high_value_detail 需要至少一个明细通道(failed_detail_enabled、poison_detail_enabled、slow_job_detail_enabled)开启,且采样率 > 0
  • processing_spans 需要 event_metrics=true 且 processing_spans_max>0

采集与写入 ​

配置键环境变量默认值(full)说明
observability.metrics_windowHORIZON_OBSERVABILITY_METRICS_WINDOW1mevent_metrics 的事件时间聚合桶宽度,独立于 flush_interval
observability.flush_intervalHORIZON_OBSERVABILITY_FLUSH_INTERVAL1mcollector 到 Store 的周期 flush 间隔
observability.flush_timeoutHORIZON_OBSERVABILITY_FLUSH_TIMEOUT5s单次 flush 写 Store 的等待上限
observability.batch_sizeHORIZON_OBSERVABILITY_BATCH_SIZE500一次 flush 最多写入的增量或明细数量
observability.batch_summary_sizeHORIZON_OBSERVABILITY_BATCH_SUMMARY_SIZE500一次最多保留或写入的 batch summary 数量;未显式配置时等于 batch_size
observability.buffer_sizeHORIZON_OBSERVABILITY_BUFFER_SIZE10000collector 与 flusher 之间的有界内存 buffer 条数
observability.max_events_per_secondHORIZON_OBSERVABILITY_MAX_EVENTS_PER_SECOND0collector 入口速率上限,0 表示不额外限速
observability.drop_policyHORIZON_OBSERVABILITY_DROP_POLICYdrop_oldestbuffer 满或降级时的丢弃策略:drop_oldest(优先丢弃最旧)或 drop_newest(丢弃当前入队)

数据流:queue event → Collector(非阻塞入队)→ 内存聚合窗口 → Flusher(周期批量写入)→ Store

采样 ​

配置键环境变量默认值(full)说明
observability.event_metrics_sample_rateHORIZON_OBSERVABILITY_EVENT_METRICS_SAMPLE_RATE1queue event 进入 event_metrics 管线的采样率。1 表示全量,0 表示关闭,0.1 表示 10%
observability.high_value_detail_sample_rateHORIZON_OBSERVABILITY_HIGH_VALUE_DETAIL_SAMPLE_RATE空failed、poison、slow job 明细的独立采样率;空值继承当前实际 event_metrics 采样率
observability.sample_reservoir_sizeHORIZON_OBSERVABILITY_SAMPLE_RESERVOIR_SIZE2048P95/P99 估算所需的样本池大小
observability.max_aggregate_keysHORIZON_OBSERVABILITY_MAX_AGGREGATE_KEYS10000聚合 key 基数上限(connection+queue/job type),防止 key 过多撑爆内存
observability.aggregate_key_ttlHORIZON_OBSERVABILITY_AGGREGATE_KEY_TTL30m低活跃聚合 key 的过期窗口
observability.dynamic_sampling_enabledHORIZON_OBSERVABILITY_DYNAMIC_SAMPLING_ENABLEDtrue是否允许压力下动态降低实际采样率
observability.min_sample_rateHORIZON_OBSERVABILITY_MIN_SAMPLE_RATE0.01动态采样降级时的最低采样率

采样率影响数据质量标记:

质量标记含义
exact全量事件派生,无采样或丢弃降级
estimated由采样事件估算派生
degraded受到丢弃、Store 失败或其他降级影响
unknown存在不可量化丢失,不能作为估算或精确值展示
partialshutdown best-effort flush 写入了未完成窗口

高价值诊断明细 ​

配置键环境变量默认值(full)说明
observability.failed_detail_enabledHORIZON_OBSERVABILITY_FAILED_DETAIL_ENABLEDtrue是否保存 failed job 安全摘要
observability.poison_detail_enabledHORIZON_OBSERVABILITY_POISON_DETAIL_ENABLEDtrue是否保存无法解析 payload 的 poison envelope 摘要
observability.slow_job_detail_enabledHORIZON_OBSERVABILITY_SLOW_JOB_DETAIL_ENABLEDtrue是否保存慢任务摘要
observability.slow_job_thresholdHORIZON_OBSERVABILITY_SLOW_JOB_THRESHOLD30s慢任务诊断阈值

高价值诊断明细只保存安全摘要(connection、queue、job name、runtime、截断的错误摘要),不保存 job payload、raw envelope 或完整错误堆栈。

数据保留与清理 ​

配置键环境变量默认值(full)说明
observability.event_metrics_retentionHORIZON_OBSERVABILITY_EVENT_METRICS_RETENTION24hevent_metrics 聚合数据保留期
observability.high_value_detail_retentionHORIZON_OBSERVABILITY_HIGH_VALUE_DETAIL_RETENTION24h高价值诊断明细保留期
observability.batch_summary_retentionHORIZON_OBSERVABILITY_BATCH_SUMMARY_RETENTION24hbatch summary 保留期
observability.diagnostics_retentionHORIZON_OBSERVABILITY_DIAGNOSTICS_RETENTION24hdrop/degradation 诊断数据保留期

过期数据由 Store 的 Trim 操作清理,在 supervisor 运行循环中周期执行。

诊断与降级 ​

当 collector/flusher 发生丢弃或降级时,会写入 ObservabilityDiagnostic 记录,包含稳定的原因标识和计数。常见丢弃原因:

原因说明
buffer_full有界 buffer 已满导致观测数据被丢弃
rate_limitedmax_events_per_second 限流
aggregate_key_overflow聚合 key 达到上限
store_unavailableflush 写入 Store 失败或超时
flush_lag_exceeded周期 flush 距离上次成功超过安全窗口
flush_timeout_nearflush 耗时接近或超过 flush_timeout
batch_summary_limitbatch summary 达到内存或写入上限
collector_paniccollector 主循环 panic 并自动重启
flusher_panicflusher 主循环 panic 并自动重启

诊断数据可通过 /metrics/current API 的 diagnostics 字段和 horizon:snapshot 命令查看。

Metrics ​

Horizon 通过 collector 监听 queue 事件并聚合为 event_metrics 窗口。每个窗口按事件时间归属,包含以下计数:

指标说明
processed成功处理的任务数
failed失败的任务数
released释放重试的任务数
poison无法解析的 poison envelope 数
queued入队任务数
runtime_ms任务运行耗时总量(毫秒)

窗口还包含采样率和质量标记,用于 Dashboard 展示数据可信度。

手动生成快照:

bash
go run ./ horizon:snapshot

horizon:snapshot 会等待调用开始前 collector 已接受的事件完成聚合,再持久化本次快照;因此无需通过额外延时来等待后台 collector。

清理指标:

bash
go run ./ horizon:clear-metrics

失败任务 ​

Horizon 不替代 github.com/prismgo/framework/queue 的 FailedStore,但提供 horizon:forget 命令维护失败记录:

bash
# 删除单条失败记录
go run ./ horizon:forget <id>

# 删除所有失败记录
go run ./ horizon:forget --all

失败任务的安全摘要(不含 payload 和完整堆栈)通过高价值诊断明细通道采集,可在 Dashboard 的 /high-value-detail?kind=failed 查看。

长等待事件 ​

当队列等待时间超过 horizon.waits 中配置的阈值时,Horizon 会发出 horizon.long_wait 事件。业务应用可以通过 github.com/prismgo/framework/event 监听该事件,将事件转换为通知、日志或外部告警。

go
event.Listen("horizon.long_wait", func(ctx context.Context, e event.Event) error {
    var evt horizon.LongWaitEvent
    // 解析事件,包含 connection、queue、threshold_ms、wait_ms、sampled_at
    return nil
})

LongWaitEvent 只包含 connection、queue、阈值、观测值和采样时间,不包含 job payload。

批次摘要 ​

当 observability.batch_summaries 启用时,Horizon 会监听 queue.EventBatchCreated、queue.EventBatchUpdated、queue.EventBatchCancelled 和 queue.EventBatchFinished 事件,生成批次安全摘要。

批次摘要只保存进度、状态和时间戳,不暴露 batch 内部 job payload、raw envelope 或 broker 字段。可通过 Dashboard 的 /batches API 查看。

Store 接口 ​

Horizon Store 是状态存储的抽象接口,支持 Redis 和 Memory 两种实现。Store 保存以下数据:

数据类型说明
Master/Supervisor/Worker heartbeat进程心跳,用于存活判断和状态展示
ControlState全局和 supervisor 级控制标记(pause/terminate)
StatusSnapshot全局运行状态派生视图
EventMetricWindow事件时间聚合窗口
QueueLengthSnapshot队列长度采样
HighValueJobDetail高价值诊断摘要
ObservabilityDiagnostic丢弃和降级诊断
BatchSummary批次安全摘要
OrphanProcess孤儿进程记录

Store 接口定义了 30+ 方法,涵盖心跳写入、控制标记、metrics 读写、诊断和孤儿进程管理。生产推荐使用 Redis Store,测试可使用 Memory Store。

注意:Memory Store 仅适用于本地/测试环境,不推荐在生产环境使用。使用 Memory Store 时,Horizon 会在命令启动时输出警告。

部署 Horizon ​

进程管理 ​

Horizon master 使用 systemd、supervisord、Docker 或 Kubernetes 管理。部署流程:

  1. 发送 horizon:terminate 请求优雅退出当前 master
  2. 进程管理器检测到退出后拉起新 master
  3. 新 master 加载最新配置并派生 supervisor

配置要点 ​

  • timeout 应小于队列连接的 retry_after,避免同一任务被并发重复消费
  • 认证、支付、通知等队列应拆分 supervisor,便于独立扩缩容
  • 保持 HORIZON_PREFIX 与业务队列 key 前缀不同,避免状态混淆
  • 高吞吐生产环境优先使用 production_light 或调低采样率
  • 当 job type、tenant、tag 基数很高时,优先限制 max_aggregate_keys、降低采样率或使用 production_light

已移除的配置 ​

以下配置字段和环境变量已被移除,使用时会报错:

已移除替代方案
horizon.trim使用 observability.event_metrics_retention / high_value_detail_retention / batch_summary_retention / diagnostics_retention
horizon.silenced / horizon.silenced_tags高价值明细不再按 silenced 规则过滤
horizon.metrics.trim_snapshots使用 observability.event_metrics_retention
observability.recent_jobs使用 failed_detail_enabled 或 poison_detail_enabled
observability.recent_jobs_max使用 buffer_size 或 max_aggregate_keys
observability.job_history / observability.queue_history使用 event_metrics
observability.success_detail_enabled成功任务明细已移除,不再采集
HORIZON_TRIM_RECENT / HORIZON_TRIM_FAILED / HORIZON_TRIM_MONITORED使用对应的 retention 环境变量
HORIZON_SILENCED / HORIZON_SILENCED_TAGSsilenced 规则已移除