Documentation
¶
Overview ¶
Package natsx 提供实例式 NATS 连接、启动期消费注册、通用消息操作和 logit 结果日志。 操作结果成功写 Info,失败写 Error。 Config.LoggerName 指定连接、异步错误及消费入口的命名 Logger,空值或未注册名称回退默认 Logger。 Handler 及其下游沿用消息 ctx 时继承此路由;Publish、Request 及 JetStream 发布始终使用调用方 ctx。 Publish、Request、PublishJetStream、PublishJetStreamAsync 在 ctx 启用 logit.WithStart 时登记请求级耗时, 字段为 NATS_<连接名>_<序号>_duration_ms;日志被过滤时仍登记,供 InfoDuration 等汇总。 耗时不包含日志构建或写入,消费回调不计入下游调用。 操作日志记录完整正文及 Header,不截断或脱敏;Request 同时记录收到的响应。 正文按 UTF-8 字符串输出,非 UTF-8 数据使用 Base64,并记录对应的编码。 Stream/Consumer 使用官方配置;JetStream 消费统一通过 RegisterJetStreamConsumers 注册并自动确认。 第一版原样记录错误文本并保留原始错误链,不脱敏其中可能包含的 URL、密码或 Token。
Config.Namespace 可选,空值保持原样;非空仅允许 ASCII 字母、数字、_、-,在拨号前校验并固定。 四个发布/Request 入口和三个 Register 入口都接受原始名称与主题;Default 工厂不添加前缀。 例如 namespace 为 test1 时,主题 orders.created 变为 test1.orders.created,Stream ORDERS 变为 test1_ORDERS。 注册的 Stream Name、Consumer Stream/Durable/非空 Name、Core Name/非空 Queue 添加 namespace_; Stream Subjects、Consumer FilterSubject/FilterSubjects、Core Subject 添加 namespace.,保留通配符。 空 queue 保持广播,空过滤条件保持整个 Stream;原始参数先校验,转换不修改调用方配置或主题切片。 其他 SDK 高级字段(如 Mirror、Sources、RePublish、SubjectTransform)原样传递,须自行填写实际值。 不猜测或去重已有前缀;客户端实例名、Handler 名称、messageID 不变。 回调、日志、PubAck 和异步 future 保留真实名称及主题;把回调主题重新传入发送入口会再次添加前缀。 Request 回复使用 Msg.Respond/RespondMsg;回复 inbox、JetStream ACK 和管理协议主题保持原样。 原生 Conn()/JetStream() 不添加 namespace,直接操作时须使用完整名称和主题。 每个 Client 独立配置;修改 namespace 不迁移或删除旧 Stream/Durable。
Handler 注册表可独立于客户端使用,供应用按名称选择强类型处理函数:
func HandleTask(context.Context, jetstream.Msg) error {
return nil
}
func HandleBroadcast(context.Context, *nats.Msg) error {
return nil
}
var JetStreamHandlers = natsx.MustNewJetStreamHandlerRegistry(HandleTask)
var CoreHandlers = natsx.MustNewCoreHandlerRegistry(HandleBroadcast)
示例另需导入 context、nats.go 和 nats.go/jetstream。两个注册表零值可用, 包级具名函数默认保留原始大小写,闭包、方法值和泛型函数须用 MustRegister(handler, name) 显式命名。 nil、非法名称及同类重名均 panic;两类名称空间独立,登记不读配置、建连或启动消费。 Handlers 返回名称到函数的独立 map 快照,nil 或空注册表返回空清单;可交给配置装配, 或自行取出函数传入 DefaultJetStreamConsumer / DefaultCoreConsumer 等工厂。 登记与快照读取可并发,首次使用后不得复制;函数捕获的业务依赖仍由调用方管理。 注册表不改变 Client 的一次性注册和关闭语义;运行时通过强类型函数直接调用业务。
共享客户端可在启动阶段使用 NewDefault/NewNamed 创建,由 Default/Named 获取。 默认引用与同名实例相同;独立 New 不登记到注册表,仍由调用方显式关闭。 以下为共享客户端的发布样例(需导入 context 和 natsx):
client, err := natsx.NewDefault(natsx.Config{
Name: "events",
Namespace: "test1",
URLs: []string{"nats://127.0.0.1:4222"},
})
if err != nil {
return err
}
defer natsx.CloseAll()
return client.Publish(context.Background(), "events.created", []byte("hello"))
NewDefault/NewNamed 只在启动阶段串行调用,不能与 CloseAll 并发;失败不占用名称。 注册表先拒绝重复或关闭状态,连接参数统一由 New 校验。 未初始化、名称不存在或 CloseAll 开始后查询会 panic。CloseAll 只关闭已登记实例, 默认实例只关闭一次,并汇总错误;重复调用返回同一次结果。 统一停机先调用 StopConsumers,WaitConsumers(ctx) 等待已接收消息、Handler、ACK 和日志完成。 Core 注册日志在停收锁外写入,成功和失败日志都纳入实际排空;慢日志不阻塞停收和取消。 停收期间保留共享连接和发布/请求能力,不设独立消费排空期限;托管服务共享 30 秒。 排空超时调用 CancelConsumers,然后继续资源栈回收。StopConsumers 与 Close 复用同一次停收状态。 CancelConsumers 也可直接或重复调用:先停收再取消业务,随后仍可通过 WaitConsumers 确认实际收尾。 显式 CancelConsumers 后 Close 不再等待未退出 Handler;断连引起的取消仍保留原有回调等待。 注册表不保证多实例关闭顺序,各实例使用独立的 CloseTimeout,不支持关闭期跨实例依赖。
应用启动时在依赖就绪后创建并持有客户端,依次调用 RegisterStreams、 RegisterJetStreamConsumers 和 RegisterCoreConsumers;运行期间保持消费关系固定。 受管服务先通过 StopConsumers/WaitConsumers 排空,再由资源栈关闭客户端;独立 New 客户端也可直接 Close,使用已持有引用完成消费收尾。 Close 拒绝新增注册,排空消费后拒绝新发布与请求,再等待异步发布结果并 drain 连接。 排空期间 handler ctx 保持有效,可以继续发布和完成 ACK;Close 不汇总单条发布错误。 连接意外永久关闭后停止接纳新的 Core 回调,Close 在整体期限内等待在途回调及其结果日志结束, 不依赖此时 SDK 可能缺失的订阅关闭状态通知;未完成的业务仍会触发 ErrCloseTimeout。 已建立连接意外断开后默认持续重连,心跳间隔默认 20 秒,重连发送缓冲默认 16 MiB; 调用方可通过 nats.MaxReconnects、nats.PingInterval、nats.ReconnectBufSize 等官方选项覆盖。 首次连接失败仍直接返回错误;重连成功后由官方客户端恢复原有订阅。 DrainTimeout、CloseTimeout 的零值默认保持 10 秒、20 秒,由调用方通过 Config 按需设置。 DrainTimeout 仅用于底层 NATS 连接 drain;直接 Close 时消费排空、异步确认等待和连接关闭共用 CloseTimeout。 已完成 WaitConsumers 的客户端不会再次排空原消费句柄;该方法的等待由外部服务预算管理。 关闭完成后的连接 LastError 仅对 ErrDrainTimeout、ErrTimeout 记录日志,不作为返回错误。 发起连接 Drain 失败及整体关闭超时仍返回错误。 Config.JetStream 使用 JetStreamConfig,目前仅开放 PublishAsyncTimeout: 零值默认 5 秒,正值覆盖,负值在拨号前报错;仅限制默认 JetStream 上下文的异步发布确认等待。 确认超时通过 future.Err() 和 Pixiu 错误日志报告,不等于消息未写入服务端。 以下为仅发布消息的调用样例:
client, err := natsx.New(natsx.Config{
Name: "orders",
URLs: []string{"nats://127.0.0.1:4222"},
Username: username,
Password: password,
})
if err != nil {
return err
}
defer client.Close()
ctx = logit.WithContextLogID(ctx) // 服务入口生成一次,后续发布直接复用 ctx
return client.Publish(ctx, "orders.created", payload)
上例需导入 github.com/bpcoder16/pixiu/infra/natsx 和 github.com/bpcoder16/pixiu/logit。 Publish、Request、PublishJetStream 的 Header 均可省略或传入一个(可为 nil),多传返回参数错误;data 允许 nil。 PublishJetStream 在 data 后要求非空 messageID,再接收可选 Header,不开放 jetstream.PublishOpt。 例如:ack, err := client.PublishJetStream(ctx, "orders.created", payload, eventID)。 messageID 不自动生成,覆盖消息 Header 副本的 Nats-Msg-Id;同一事件重试时复用,不同事件使用不同 ID。 发布去重仅在同一 Stream 的去重窗口内生效,不代表消费者业务处理只执行一次。 Publish、Request、PublishJetStream 从 meta 读取 logit.LogId,覆盖消息的 X-Log-Id; 缺失或为空时为消息 Header 生成新 ID,不回写调用方 context。 操作日志只使用 ctx 已有的 logID,不额外补写或覆盖;需关联时应在入口初始化。 出入站完全信任已有的非空 ID,不校验长度或字符,合法性由写入方保证。 多次发布需要关联时,应在入口初始化 ID。 Core Publish/Request 调用期间 data 和 header 必须独占,不得被其他 goroutine 并发读取、修改或用于另一次发布。 这两个方法直接使用 data 和 header,不复制;header 为 nil 时内部创建,非 nil 时原地写入追踪 ID,失败也不回滚。 JetStream 同步和异步发布均深拷贝 Header,仅在副本中写入追踪 ID 和消息 ID,不修改调用方 Header。 调用期间 Header 不得并发修改,可被其他发布调用只读共享;同步发布直接使用 data,调用期间 data 须独占。 出站追踪仅覆盖 X-Log-Id,其他大小写名称作为普通 Header 原样保留。 消费端精确读取 X-Log-Id(区分大小写),在独立日志作用域还原 ID, 可通过 logit.LogIDFromContext 读取。 服务器地址只能通过 Config.URLs 提供;选项中的 Url 非空或 Servers 长度非零时在拨号前报错。 URLs 至少包含一个地址,每项必须非空且无首尾空白;不自动裁剪,非法值在拨号前报错。 DisconnectedErrCB、DisconnectedCB、ReconnectedCB、ClosedCB、AsyncErrorCB 由 Pixiu 管理; 选项中任一字段非 nil 时在拨号前报错,不保留或串联用户连接回调。 应用可设置 Config.AsyncErrorHandler(nats.ErrHandler)接收权限拒绝、慢消费者等异步错误; 内部日志后同步调用,日志过滤不影响通知,订阅可能为 nil。回调不得阻塞、panic、调用 Close, 或关闭/排空连接及受管订阅;需要停机时向应用协调协程发信号。 该通知不改变注册返回值,也不自动重试;JetStream 拉取错误仍使用 ConsumeConfig.ErrorHandler。 取得 Conn() 后也不得覆盖这些回调;可通过原生 StatusChanged 观察连接状态。 username、password 由应用读取配置后注入,允许空密码;只有密码而没有用户名时无效。 Config 仅直接提供用户名/密码认证,两个字段均可不填。 nats.UserInfo 及自定义选项设置固定用户名/密码会在连接前报错,应通过 Config 提供。 显式填写认证字段时,不能混用官方认证选项或 URL 内嵌凭据;TLS 选项仍可组合使用。 两个认证字段均为空时,支持 nats.UserInfoHandler 动态获取用户名/密码, 并继续支持 nats.Token、nats.UserCredentials 等其他认证选项 及 URL 认证;所有入口都未提供凭据时才不认证。配置凭据不裁剪空格;原始错误可能包含凭据。
启动阶段的边界由应用负责;模块不提供 Start,也不在运行期自动拒绝注册。 Core 消费统一通过 RegisterCoreConsumers 注册,Queue 为空时广播,非空时同组竞争消费。 Subscribers 仅在 Queue 非空时控制当前 Client 的同组订阅数,零值默认 1,负值无效; Queue 为空时忽略该数量,固定创建一个广播订阅。 单个订阅内串行处理,多个订阅间可并发且不保证处理顺序,handler 须支持并发调用。 全空白队列名无效;handler 返回 error,成功时返回 nil。 集中注册入口只应在启动阶段调用,不能从消息回调中追加注册。 注册返回前可能接收消息,handler 依赖的资源应预先就绪。 New 不接收外部 ctx;注册入口的 ctx 仅约束准备阶段,消费生命周期由 Client.Close 管理。 托管订阅和消费均由 Client.Close 统一排空;消费注册仅返回启动错误。 直接关闭、排空原生连接后,不保证封装层的优雅排空及在途回调等待。 每条消息获得独立日志作用域的 ctx,由 Client 在关闭完成或超时后取消; Close 排空期间 ctx 保持有效,仍允许回调发布和请求;回调内不得调用 Close。 Publish、Request、PublishJetStream 仍接收调用方 ctx,回调内可按需派生 WithTimeout。 RegisterJetStreamConsumers 使用 Messages 迭代器和固定 worker;ConsumeConfig.Workers 零值默认 1,负值无效, MaxMessages 为零时等于有效 Workers 的两倍;不开放完整拉取选项。 拉取期限固定使用 jetstream.DefaultExpires(当前为 30 秒)。注册时校验声明及服务端有效配置: MaxRequestExpires 为零或不低于默认期限时允许,正值低于默认期限时在创建迭代器前报错。 MaxRequestBatch 为零或不低于有效 MaxMessages 时允许,超限时在创建迭代器前报错,不自动缩小预取数量。 调用方须在运行期间保持相关限制不变。 其余拉取参数由 SDK 按默认规则设置。 ErrorHandler 在运行错误日志之后执行;心跳丢失后继续拉取,运行中意外关闭迭代器等终止错误会通知回调,主动停收导致的迭代结束正常收尾。 多 worker 不保证业务完成顺序,确认和重试由组件按 handler 的返回结果管理。
连接失败可用 errors.Is(err, natsx.ErrConnect) 判断,同时保留原始错误链, 可继续使用 errors.Is 和 errors.AsType 判断底层错误;网络超时不转换为 nats.ErrTimeout。
集中注册只在业务依赖就绪后调用,无需额外 Runtime 或 Start:
setupCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
streamCfg := natsx.DefaultStreamConfig("TASKS", 1, "tasks.sms")
streamCfg.Retention = jetstream.WorkQueuePolicy
if err := client.RegisterStreams(setupCtx, streamCfg); err != nil {
return err
}
handler := func(ctx context.Context, msg jetstream.Msg) error {
return sendSMS(ctx, msg.Data())
}
consumer := natsx.DefaultJetStreamConsumer("TASKS", "send-sms", handler, "tasks.sms")
consumer.Consume.Workers = 4
return client.RegisterJetStreamConsumers(setupCtx, consumer)
上例的 client 已初始化且已安排 Close,sendSMS 是业务函数;还需导入 time 与官方 jetstream 包。 DefaultStreamConfig 返回可直接修改的原生配置,replicas 原样写入副本数,复制传入的 subjects;校验由注册入口和 SDK 承担。 默认 LimitsPolicy、FileStorage、MaxBytes=-1(不设 Stream 容量上限,仍受账户及服务端配额限制)、MaxMsgSize=512 KiB、DiscardNew、MaxAge=90 天(约 3 个月)、Duplicates=2 分钟、NoAck=false, 其余字段沿用 SDK 默认。注册前可直接覆盖字段,例如 streamCfg.MaxBytes = 2 << 30。 MaxMsgSize 限制 Header 与正文的总大小,须为组件追加的追踪 ID、消息 ID 等 Header 预留空间。 LimitsPolicy 下 ACK 不释放容量;达到显式配置的容量上限时拒绝新消息,空间释放后可继续发布,MaxAge 到期也会删除未 ACK 的消息。 需要满额淘汰最老消息时,可在注册前设置 streamCfg.Discard = jetstream.DiscardOld。 DefaultJetStreamConsumer 返回可修改的消费声明,默认显式确认、AckWait=60s、MaxDeliver=5(含首次投递), 显式设置 MaxAckPending=1000,限制同一 Durable 下所有实例合计的未确认消息数。 MaxRequestBatch 和 MaxRequestExpires 保留零值,不额外指定拉取批量或期限上限。 BackOff 为空、RetryDelay 为零;可通过 consumer.Config 覆盖 AckWait、MaxDeliver、MaxAckPending 或设置 BackOff。 handler 后可传入多个过滤主题,复制到 FilterSubjects,要求 NATS Server >= 2.10;不传主题时消费整个 Stream。 构造函数不设置 FilterSubject;调用方后续设置该字段时须清空 FilterSubjects,两者不能同时使用。 Workers 默认设为 1;MaxMessages 保留零值,注册时为有效 Workers 的两倍。 默认构造函数不校验参数;手写消费声明仍须显式配置确认超时。 RegisterJetStreamConsumers 仅支持 Pull Consumer,Config.DeliverSubject 非空时在创建本批任何远端 Consumer 前报错。 RegisterStreams/RegisterJetStreamConsumers 使用 SDK 创建语义:同配置复用、冲突返回错误,不更新或删除已有资源。 RegisterStreams 创建资源前整批检查名称、主题元素非空且无首尾空白,以及同批名称唯一。 Subjects 列表允许省略或为空,保留原生默认主题及 Mirror 等用法;其余约束由 SDK/服务端处理。 RegisterJetStreamConsumers 创建资源前整批校验本地参数及 (Stream, Durable) 唯一。 Stream、Durable 必须非空且无首尾空白;过滤条件允许省略,已提供的主题元素须非空且无首尾空白。 RegisterCoreConsumers 建立订阅前整批校验本地参数及 Name 唯一。 Name、Subject 必须非空且无首尾空白;Queue 为空时广播,非空时不得有首尾空白。 已有使用旧默认 AckWait=5s 的 Durable,采用新默认值前须显式更新远端配置。 RegisterStreams、RegisterJetStreamConsumers 和 RegisterCoreConsumers 分别计数,通过入口检查后每个 Client 各只允许调用一次; 须一次传入该类的全部配置,空清单或失败也不可重试,各 Client 互不影响。 消费参数校验和归一化统一在注册入口完成,内部 worker 和订阅函数不重复处理。 三个 Register 入口仅在启动阶段串行调用,不与 Close 并发;入口检查初始状态, ctx 仅传给资源 RPC 和有 deadline 时的 Core Flush,由 SDK 处理取消和连接错误。 不额外检查 ctx.Err();本地消费启动不受启动 ctx 取消限制,全部操作成功即返回 nil。 注册可能在返回前执行 handler;失败返回后须中止启动并 Close,不在同一客户端重试整批注册, 本地已执行工作和远端资源不回滚。 不同 Client 可共享同一 Durable 分摊消息,服务重启可复用其进度。 每个 Consumer 必须显式配置正值 AckWait 或非空 BackOff,至少一项;两者同时配置时 BackOff 优先。 无论 RetryDelay 是否为正,都在准备本批远端 Consumer 前检查确认超时配置。 新注册入口默认一个 worker,handler 返回 nil 时 ACK,错误或 panic 且尚有投递次数时按 RetryDelay 决定重投方式; 失败且达到 MaxDeliver 后记录 exhausted,不 ACK/Term/主动 NAK,不自动删除或转入死信队列; MaxDeliver 包含首次投递,例如 3 表示最多投递 3 次。关闭取消后不再发起确认。 handler 必须在返回前完成本条业务并支持配置的并发度,不得自行 ACK/NAK/Term 或调用 Close。 RetryDelay 为正时发送指定延迟的 NAK;零值不主动确认,等待服务端按 BackOff 重投, 未配置 BackOff 时使用 AckWait;负值无效,非空 BackOff 与正值 RetryDelay 冲突,注册前报错。 AckWait(或覆盖它的 BackOff)从消息投递时开始计时,应覆盖预取等待和业务处理时间, 不自动 InProgress,业务仍须幂等。 注册入口的 handler panic 被恢复并按业务失败处理。 消费错误文本直接调用 err.Error() 获取,调用方须保证 Error 方法可安全调用;日志被过滤后不求值错误。
Core 通过 RegisterCoreConsumers(setupCtx, CoreConsumer{...}) 集中注册: Name 必须非空且无首尾空白,同批名称按原值判重;不同 Name 可使用相同 Subject 和 Queue,不同 Client 可使用相同 Name。 Queue 为空时广播,否则竞争消费;Handler 返回错误只记日志,不重投,使用 Msg.Respond 显式应答。 DefaultCoreConsumer(name, subject, handler) 构建广播声明,Subscribers 显式设为 1。 DefaultCoreQueueConsumer(name, subject, queue, subscribers, handler) 构建同组声明,subscribers 原样写入,注册时零值默认 1。 两者只构建可修改的声明,不建立连接或校验参数;pending 保留零值以沿用 SDK 默认。 以下同时注册广播及四个同组订阅;handleBroadcast 和 handleQueue 是业务提供的 CoreHandler,后者须支持并发调用:
broadcast := natsx.DefaultCoreConsumer("event-listener", "events.created", handleBroadcast)
queue := natsx.DefaultCoreQueueConsumer("task-worker", "tasks.created", "task-workers", 4, handleQueue)
return client.RegisterCoreConsumers(context.Background(), broadcast, queue)
setupCtx 可使用 context.Background(),全部注册后仅 Flush 一次;有 deadline 时使用 FlushWithContext, 无 deadline 时使用 SDK 默认 Flush(当前等待上限 10 秒),此时取消 ctx 不会中断正在执行的 Flush。 不另设整体注册期限;Flush 不保证逐个订阅授权成功。 PendingMessages/PendingBytes 分别限制每个订阅的积压,为零沿用 SDK 默认,正值覆盖; 建立订阅后逐个设置,有默认限额窗口,总缓冲容量随订阅数增加。 两种注册的启动 ctx 均不传入长期 handler,生命周期、日志作用域和关闭顺序复用 Client。
PublishJetStreamAsync 的参数与同步方法相同,要求非空 messageID,返回原生 PubAckFuture。 同一事件重试复用 ID,不同事件使用不同 ID;去重仍受同一 Stream 的服务端窗口限制。 异步方法复制 data/Header,不修改原始输入,调用返回后即可复用;不得修改 future.Msg()。 ctx 只用于提交前取消检查、日志与追踪,不取消已提交消息,也不控制后续确认等待。 先检查方法返回的提交 error,再检查 future.Ok()/Err();异步错误同时记录日志。 async_publish_error 从消息 Header 读取已有的非空 Nats-Msg-Id、X-Log-Id, 分别输出 message_id、logId,缺失时不生成替代 ID,使用 Config.LoggerName 指定的路由。 提交日志及耗时不表示持久化成功,PubAck 也不代表消费者业务完成。 PublishAsyncTimeout 默认 5 秒,与消费者 AckWait 无关;确认超时不保证消息未写入。 Close 排空消费后等待异步结果;全部完成不等于全部成功。 整体关闭超时时,清理默认发布者并以 jetstream.ErrJetStreamPublisherClosed 结束剩余 future; Close 自身仍返回 ErrCloseTimeout,发布者关闭错误不保证消息未写入服务端。
Index ¶
- Constants
- Variables
- func CloseAll() error
- func DefaultStreamConfig(name string, replicas int, subjects ...string) jetstream.StreamConfig
- func MessageContext(parent context.Context, header nats.Header) context.Context
- type Client
- func (c *Client) CancelConsumers()
- func (c *Client) Close() error
- func (c *Client) Conn() *nats.Conn
- func (c *Client) JetStream() jetstream.JetStream
- func (c *Client) Publish(ctx context.Context, subject string, data []byte, headers ...nats.Header) error
- func (c *Client) PublishJetStream(ctx context.Context, subject string, data []byte, messageID string, ...) (*jetstream.PubAck, error)
- func (c *Client) PublishJetStreamAsync(ctx context.Context, subject string, data []byte, messageID string, ...) (jetstream.PubAckFuture, error)
- func (c *Client) RegisterCoreConsumers(ctx context.Context, consumers ...CoreConsumer) error
- func (c *Client) RegisterJetStreamConsumers(ctx context.Context, consumers ...JetStreamConsumer) error
- func (c *Client) RegisterStreams(ctx context.Context, configs ...jetstream.StreamConfig) error
- func (c *Client) Request(ctx context.Context, subject string, data []byte, headers ...nats.Header) (*nats.Msg, error)
- func (c *Client) StopConsumers()
- func (c *Client) WaitConsumers(ctx context.Context) error
- type Config
- type ConsumeConfig
- type CoreConsumer
- type CoreHandler
- type CoreHandlerRegistry
- type JetStreamConfig
- type JetStreamConsumer
- type JetStreamHandler
- type JetStreamHandlerRegistry
Examples ¶
Constants ¶
const TraceHeader = "X-Log-Id"
TraceHeader 是消息使用的日志追踪 Header。
Variables ¶
Functions ¶
func CloseAll ¶
func CloseAll() error
CloseAll 排空并关闭全部默认及命名客户端,每个实例只关闭一次,重复调用返回同一次结果。 调用前须统一停收并完成排空,或显式 CancelConsumers 放弃剩余消费;资源回收阶段不再获取客户端。 多实例关闭顺序不固定,各自使用独立的 CloseTimeout,不支持关闭期跨实例依赖。
func DefaultStreamConfig ¶
func DefaultStreamConfig(name string, replicas int, subjects ...string) jetstream.StreamConfig
DefaultStreamConfig 构建可直接修改的原生 Stream 配置,复制 subjects;校验由注册入口和 SDK 承担。 副本数由 replicas 原样指定;默认 LimitsPolicy、文件存储、不设 Stream 容量上限、最多保留 90 天(约 3 个月)、2 分钟去重,并保留发布确认。 仍受账户及服务端配额限制;显式设置容量上限后满额拒绝新消息。 单条消息的 Header 与正文总大小默认不超过 512 KiB。 LimitsPolicy 下 ACK 不释放容量;过期不等待消费,未 ACK 的旧消息到期也会删除。
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client 持有一个 NATS 连接、默认 JetStream 上下文及启动阶段登记的消费句柄。
func Default ¶
func Default() *Client
Default 返回显式初始化的默认客户端,与 Named(cfg.Name) 是同一实例。 未初始化或 CloseAll 开始后调用会 panic;New 和 NewNamed 不设置默认实例。
func New ¶
New 在应用启动阶段建立连接并创建默认 JetStream 上下文;TLS 和其他认证方式通过官方选项配置。 默认在意外断连后持续重连,心跳间隔为 20 秒,重连发送缓冲为 16 MiB。 可通过 nats.MaxReconnects、nats.PingInterval、nats.ReconnectBufSize 等选项覆盖。 服务器地址只能通过 Config.URLs 设置;Config 的 Name 和超时优先于同名 nats.Option 设置。 固定用户名/密码需使用 Config;未配置时可通过 nats.UserInfoHandler 动态获取。 Config 认证字段非空时,拒绝混用官方认证选项或 URL 凭据;凭据原样传递。 DisconnectedErrCB、DisconnectedCB、ReconnectedCB、ClosedCB、AsyncErrorCB 由 Pixiu 管理; 调用方选项设置上述任一非 nil 回调时,在拨号前返回错误。
Example (Credentials) ¶
package main
import (
"context"
"os"
"github.com/bpcoder16/pixiu/infra/natsx"
"github.com/bpcoder16/pixiu/logit"
"github.com/nats-io/nats.go"
)
func main() {
// 未配置用户名/密码时,可透传官方选项使用其他认证方式。
client, err := natsx.New(natsx.Config{
Name: "orders",
URLs: []string{"nats://127.0.0.1:4222"},
}, nats.UserCredentials(os.Getenv("NATS_CREDS_FILE")))
if err != nil {
logit.Error(context.Background(), "NATS 初始化失败")
return
}
defer client.Close()
}
Output:
Example (UserPassword) ¶
package main
import (
"context"
"os"
"github.com/bpcoder16/pixiu/infra/natsx"
"github.com/bpcoder16/pixiu/logit"
)
func main() {
client, err := natsx.New(natsx.Config{
Name: "orders",
URLs: []string{"nats://127.0.0.1:4222"},
Username: os.Getenv("NATS_USERNAME"),
Password: os.Getenv("NATS_PASSWORD"),
})
if err != nil {
logit.Error(context.Background(), "NATS 初始化失败")
return
}
defer client.Close()
}
Output:
func NewDefault ¶
NewDefault 创建默认客户端,同时按 Config.Name 登记;已有默认实例时返回错误。 创建失败不占用名称或默认引用;初始化与关闭约束与 NewNamed 相同。
func NewNamed ¶
NewNamed 创建并按 Config.Name 登记客户端,保留 New 的连接选项与错误语义。 仅在启动阶段串行创建,全部创建完成后再启动业务;不得与 CloseAll 并发。 注册表先检查关闭及重复状态,连接参数统一由 New 校验。
func (*Client) CancelConsumers ¶
func (c *Client) CancelConsumers()
CancelConsumers 先停收,再通知在途消费取消;不关闭共享连接。 Close 随后可关闭连接,不再等待无限运行的回调。
func (*Client) Close ¶
Close 统一排空启动阶段登记的订阅与消费,期间拒绝新增注册,允许回调继续发布与请求。 消费排空后停止发布,等待异步 PubAck,最后 drain 连接。 所有阶段共用 CloseTimeout 整体期限;DrainTimeout 仅用于底层连接 drain。 整体超时后清理默认异步发布者,未完成的 future 以 ErrJetStreamPublisherClosed 结束。 关闭完成或超时后取消消息处理 ctx;不强制终止未响应取消的业务函数。 调用方应先停生产者,最后关闭日志;不得在消费回调中调用 Close。 重复或并发调用复用同一次关闭结果。 调用方须保持托管订阅固定;自行 Unsubscribe/Drain 后,不保证排空及等待在途回调。
func (*Client) Conn ¶
Conn 返回原生连接;直接操作它不会添加 namespace 前缀,也不会获得封装层的追踪和结果日志。 不得通过原生 setter 或修改 Opts 覆盖 Pixiu 管理的连接回调;可通过 StatusChanged 观察连接状态。 退出时统一调用 Client.Close;自行关闭或排空原生连接后,不保证封装层的优雅关闭语义。
func (*Client) Publish ¶
func (c *Client) Publish(ctx context.Context, subject string, data []byte, headers ...nats.Header) error
Publish 向 Core NATS 发送消息;成功只表示客户端已接受写入。 subject 使用原始主题,由 Client 自动添加 namespace 前缀;空 namespace 保持原样。 headers 可省略或传入一个 Header(可为 nil),多传返回参数错误;data 允许 nil。 data 和提供的 Header 在调用期间须独占;Header 非 nil 时原地写入追踪 ID,已写入的字段不回滚。
func (*Client) PublishJetStream ¶
func (c *Client) PublishJetStream(ctx context.Context, subject string, data []byte, messageID string, headers ...nats.Header) (*jetstream.PubAck, error)
PublishJetStream 同步发布并等待服务端 PubAck;messageID 必须非空,不自动生成。 subject 使用原始主题,由 Client 自动添加 namespace 前缀;空 namespace 保持原样。 同一业务事件重试时复用 messageID,不同事件使用不同 ID;去重仅在同一 Stream 的去重窗口内生效。 headers 可省略或传入一个 Header(可为 nil),多传返回参数错误;data 允许 nil。 data 在调用期间须独占;Header 深拷贝后写入追踪 ID 并覆盖 Nats-Msg-Id,不修改调用方 Header。 调用期间 Header 不得并发修改,可被其他发布调用只读共享。
func (*Client) PublishJetStreamAsync ¶
func (c *Client) PublishJetStreamAsync(ctx context.Context, subject string, data []byte, messageID string, headers ...nats.Header) (jetstream.PubAckFuture, error)
PublishJetStreamAsync 提交消息并返回原生 future;提交成功不表示服务端已持久化。 subject 使用原始主题,由 Client 自动添加 namespace 前缀;空 namespace 保持原样。 messageID 必须非空,Header 至多一个;复制 data 和 Header,不修改调用方输入。 调用期间输入不得并发修改,返回后可复用;future.Msg() 是 SDK 持有的消息,不得修改。 ctx 仅用于提交前取消检查、追踪和耗时,不撤销已提交消息或控制后续 PubAck 等待。 最终结果通过 future.Ok/Err 获取,异步错误同时记录日志;Close 等待已提交的确认。
func (*Client) RegisterCoreConsumers ¶
func (c *Client) RegisterCoreConsumers(ctx context.Context, consumers ...CoreConsumer) error
RegisterCoreConsumers 在启动期建立全部订阅并执行一次 Flush;空清单不 Flush。 只在启动阶段串行调用,不与 Close 并发。 通过入口检查后,每个 Client 只允许调用一次;须一次传入全部声明,空清单或失败也不可重试。 Name、Subject 必须非空且无首尾空白;Queue 允许为空,非空时不得带首尾空白。 Name、Subject 和 Queue 使用原始值,校验后添加当前 Client 的 namespace;空 Queue 保持广播。 同批 Name 不得重复,全部声明校验完成前不建立订阅。 ctx 有 deadline 时用于 Flush,否则沿用 SDK 默认 Flush;不额外限制本地订阅建立。 handler 使用 Client 生命周期,返回前可能开始处理消息。 Flush 不保证逐个订阅授权成功,异步故障通过现有日志报告。 失败后由应用中止启动并 Close,不回滚已执行业务;调用方不可自行停止受管订阅。
func (*Client) RegisterJetStreamConsumers ¶
func (c *Client) RegisterJetStreamConsumers(ctx context.Context, consumers ...JetStreamConsumer) error
RegisterJetStreamConsumers 先准备本批全部远端 Consumer,再启动固定 worker;返回前可能执行 handler。 只在依赖就绪后的启动期串行调用,不与 Close 并发。 通过入口检查后,每个 Client 只允许调用一次;须一次传入全部配置,空清单或失败也不可重试。 本地参数及 (Stream, Durable) 判重在创建本批任何远端 Consumer 前完成。 Stream、Durable 必须非空且无首尾空白;过滤条件允许省略,已提供的主题元素须非空且无首尾空白。 Stream、Durable、非空 Name 和过滤主题使用原始值,校验后添加当前 Client 的 namespace。 ctx 仅传给资源 RPC,不额外限制本地 worker 启动,也不影响长期 handler。 失败中止启动,由 Client.Close 回收已启动消费; 已创建远端资源不删除,已执行业务不回滚,不支持失败后重新登记整批。
Example ¶
package main
import (
"context"
"os"
"os/signal"
"time"
"github.com/bpcoder16/pixiu/infra/natsx"
"github.com/bpcoder16/pixiu/logit"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/jetstream"
)
func main() {
client, err := natsx.New(natsx.Config{
Name: "tasks",
URLs: []string{"nats://127.0.0.1:4222"},
})
if err != nil {
return
}
defer client.Close()
setup, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := client.RegisterStreams(setup, jetstream.StreamConfig{
Name: "TASKS",
Subjects: []string{"tasks.sms"},
Retention: jetstream.WorkQueuePolicy,
Storage: jetstream.FileStorage,
}); err != nil {
return
}
handler := func(ctx context.Context, msg jetstream.Msg) error {
// 执行业务并返回错误,由组件确认或等待服务端超时重投;不要自行 ACK。
logit.Info(ctx, "处理短信任务", logit.Str("subject", msg.Subject()))
return nil
}
consumer := natsx.DefaultJetStreamConsumer("TASKS", "send-sms", handler, "tasks.sms")
consumer.Consume.Workers = 4
if err := client.RegisterJetStreamConsumers(setup, consumer); err != nil {
return
}
if err := client.RegisterCoreConsumers(setup, natsx.CoreConsumer{
Name: "invalidate-cache",
Subject: "cache.invalidate",
Handler: func(ctx context.Context, msg *nats.Msg) error {
logit.Info(ctx, "清理缓存", logit.Str("key", string(msg.Data)))
return nil
},
}); err != nil {
return
}
cancel() // 结束准备阶段,不会取消长期 handler。
stop, cancelStop := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancelStop()
<-stop.Done()
// 若有 HTTP/Cron 等生产者,先停止并等待,再通过 defer 排空 Client。
}
Output:
func (*Client) RegisterStreams ¶
RegisterStreams 在启动期依次创建或复用 Stream,不自动更新、删除已有资源。 只在启动阶段串行调用,不与 Close 并发。 通过入口检查后,每个 Client 只允许调用一次;须一次传入全部配置,空清单或失败也不可重试。 创建资源前整批检查名称、主题元素非空且无首尾空白,以及同批名称唯一,不自动裁剪。 Subjects 列表允许省略或为空;其余约束交给 SDK。失败保留已创建资源,由应用中止启动并 Close。 Name 和 Subjects 使用原始值,由 Client 添加 namespace;其他 SDK 高级字段原样传递。
func (*Client) Request ¶
func (c *Client) Request(ctx context.Context, subject string, data []byte, headers ...nats.Header) (*nats.Msg, error)
Request 向 Core NATS 发送请求并等待响应,由 ctx 控制等待期限。 subject 使用原始主题,由 Client 自动添加 namespace 前缀;空 namespace 保持原样。 headers 可省略或传入一个 Header(可为 nil),多传返回参数错误;data 允许 nil。 data 和提供的 Header 在调用期间须独占;Header 非 nil 时原地写入追踪 ID,已写入的字段不回滚。
func (*Client) StopConsumers ¶
func (c *Client) StopConsumers()
StopConsumers 封闭消费注册,停止 Core 接收与 JetStream 拉取,异步排空已接收的消息。 保留连接、发布和请求能力;可与资源 Close 并发,二者复用同一次消费停收。
type Config ¶
type Config struct {
// Name 是连接名称,同时用于日志标识;不能为空或仅含空白。
Name string
// LoggerName 指定连接状态、异步错误和消费入口的命名 Logger;空值或未注册时使用默认 Logger。
// 消费 Handler 及其下游继承消息 ctx;主动发布和 Request 的日志始终跟随调用方 ctx。
LoggerName string
// Namespace 是当前实例的业务资源前缀;空值不启用,非空仅接受 ASCII 字母、数字、_、-。
// 初始化后固定,封装的发送及注册入口接收原始主题和名称,自动添加前缀。
Namespace string
// URLs 是服务器地址列表;至少提供一个地址,且每项非空、无首尾空白,不自动裁剪。
URLs []string
// Username 与 Password 配对,允许空密码;只有 Password 时无效。
// 两者均为空时可通过官方选项使用动态用户名/密码或其他认证;显式配置时不可与认证选项或 URL 凭据混用。
Username string
// Password 是 Username 对应的密码;凭据原样传递,不裁剪空白。
Password string
// ConnectTimeout 是建立连接的超时;零值默认 5 秒。
ConnectTimeout time.Duration
// DrainTimeout 仅配置底层 NATS 连接的 drain 超时;零值默认 10 秒。
// Client 的消费排空及其他关闭等待统一由 CloseTimeout 限制。
DrainTimeout time.Duration
// CloseTimeout 是整体关闭流程的超时;零值默认 20 秒,超时后强制关闭连接。
CloseTimeout time.Duration
// JetStream 配置基于当前连接创建的默认 JetStream 上下文。
JetStream JetStreamConfig
// AsyncErrorHandler 在内部日志后同步接收连接异步错误;日志过滤不影响通知,nil 时仅记录日志。
// 订阅可能为 nil;回调不得阻塞、panic、调用 Client.Close,或关闭/排空连接及受管订阅。
// JetStream 拉取错误使用 ConsumeConfig.ErrorHandler,异步 PubAck 结果通过 future 观察。
AsyncErrorHandler nats.ErrHandler
}
Config 是实例式 NATS 连接配置;零超时使用模块默认值。
type ConsumeConfig ¶
type ConsumeConfig struct {
// Workers 限制同时执行的 handler 数;零值默认 1,负值无效,handler 须支持并发调用。
Workers int
// MaxMessages 是 SDK 预取上限,不含已经交给 worker 的消息;零值等于 Workers 的两倍,负值无效。
// 有效值不得超过 Consumer 配置的非零 MaxRequestBatch。
// 服务端 MaxAckPending 和 ACK 等待期限仍由业务 ConsumerConfig 决定。
MaxMessages int
// ErrorHandler 在模块记录消费运行错误后同步调用;nil 时仅记录日志。
// 不得阻塞或在这里调用 Client.Close;心跳丢失后继续拉取,其他迭代器错误终止消费。
ErrorHandler jetstream.ConsumeErrHandlerFunc
}
ConsumeConfig 配置启动阶段固定的消费并发和预取数量。
type CoreConsumer ¶
type CoreConsumer struct {
// Name 是当前 Client 内唯一的本地声明标识,必须非空且无首尾空白,不发送给服务端。
Name string
Subject string
Queue string
// Subscribers 仅在 Queue 非空时控制当前 Client 创建的同组订阅数;零值默认 1,负值无效。
// Queue 为空时忽略此数量,始终只创建一个广播订阅。
Subscribers int
Handler CoreHandler
// PendingMessages 和 PendingBytes 为零时沿用 SDK 默认,正值覆盖,负值无效。
PendingMessages int
PendingBytes int
}
CoreConsumer 声明 Core 订阅;Queue 为空时广播,否则为同组竞争消费。 同一订阅内串行调用 handler,多个订阅之间可并发执行且不保证处理顺序,handler 须支持并发调用。 pending 溢出由 SDK 异步错误日志报告,不保证重投。
func DefaultCoreConsumer ¶
func DefaultCoreConsumer(name, subject string, handler CoreHandler) CoreConsumer
DefaultCoreConsumer 构建可直接修改的 Core 广播消费声明,不建立连接或校验参数。 Subscribers 显式设为 1;PendingMessages 和 PendingBytes 保留零值,注册时沿用 SDK 默认限额。
func DefaultCoreQueueConsumer ¶
func DefaultCoreQueueConsumer(name, subject, queue string, subscribers int, handler CoreHandler) CoreConsumer
DefaultCoreQueueConsumer 构建可直接修改的 Core 同组消费声明,不建立连接或校验参数。 subscribers 原样写入,注册时零值默认 1、负值无效;pending 默认值与 DefaultCoreConsumer 相同。 Queue 为空时沿用 CoreConsumer 的广播语义。
type CoreHandler ¶
CoreHandler 返回的错误仅记录日志,不重投;panic 恢复后记录堆栈。 需要响应时显式调用 Msg.Respond;不得在回调中调用 Client.Close。
type CoreHandlerRegistry ¶
type CoreHandlerRegistry struct {
// contains filtered or unexported fields
}
CoreHandlerRegistry 保存名称到 Core Handler 的映射,零值可用。 登记与装配快照可并发;首次使用后不得复制。与 JetStream 的名称空间独立。
func MustNewCoreHandlerRegistry ¶
func MustNewCoreHandlerRegistry(handlers ...CoreHandler) *CoreHandlerRegistry
MustNewCoreHandlerRegistry 以原始函数名批量登记包级具名函数,区分大小写。 nil 或重名会 panic;方法值、闭包和泛型函数须通过 MustRegister 显式命名。
func (*CoreHandlerRegistry) Handlers ¶
func (r *CoreHandlerRegistry) Handlers() map[string]CoreHandler
Handlers 返回独立映射快照;nil 或空注册表返回空清单。 修改快照和后续登记互不影响;函数捕获的业务依赖仍由调用方管理。
func (*CoreHandlerRegistry) MustRegister ¶
func (r *CoreHandlerRegistry) MustRegister(handler CoreHandler, name ...string)
MustRegister 登记 Handler,可选稳定名称最多一个;非法名称、nil 或重名会 panic。 自动名称随函数重命名变化;方法值、闭包和泛型函数必须显式命名。
type JetStreamConfig ¶
type JetStreamConfig struct {
// PublishAsyncTimeout 是异步发布等待服务端 PubAck 的超时;零值默认 5 秒,负值无效。
// 仅影响默认上下文的异步发布,不影响同步发布或 Consumer 的 AckWait。
PublishAsyncTimeout time.Duration
}
JetStreamConfig 是默认 JetStream 上下文的配置;不开放完整的 jetstream.JetStreamOpt。
type JetStreamConsumer ¶
type JetStreamConsumer struct {
Stream string
Config jetstream.ConsumerConfig
// Consume 复用固定 worker 配置;本入口 Workers 零值默认 1,MaxMessages 零值等于 Workers 的两倍。
Consume ConsumeConfig
// RetryDelay 为正时是业务失败后的 NAK 延迟;零值不主动确认,等待服务端按 BackOff 重投,
// 未配置 BackOff 时使用 AckWait;负值无效,BackOff 非空时 RetryDelay 必须为零。
RetryDelay time.Duration
Handler JetStreamHandler
}
JetStreamConsumer 绑定远端 Pull Consumer 配置、本地消费参数与 handler。 Config 必须提供 Durable 并使用 AckExplicitPolicy,且显式配置正值 AckWait 或非空 BackOff; 两者同时配置时 BackOff 优先,Name 非空时必须等于 Durable,DeliverSubject 必须为空。
func DefaultJetStreamConsumer ¶
func DefaultJetStreamConsumer(stream, durable string, handler JetStreamHandler, subjects ...string) JetStreamConsumer
DefaultJetStreamConsumer 构建可直接修改的消费声明,不建立连接或校验参数。 复制 subjects 后写入 FilterSubjects(要求 NATS Server >= 2.10),不传主题时消费整个 Stream。 默认显式确认、AckWait 为 60 秒、最多投递 5 次(含首次),不设置 BackOff 或延迟 NAK。 MaxAckPending 显式设为 1000;MaxRequestBatch 和 MaxRequestExpires 保留零值。 Workers 默认设为 1;MaxMessages 保留零值,由注册入口按最终并发配置归一化。
type JetStreamHandler ¶
JetStreamHandler 返回 nil 时由组件 ACK,错误或 panic 按配置重投。 handler 须支持配置的并发度并在返回前完成本条工作;不得自行 ACK/NAK/Term 或调用 Client.Close。 消息只在回调期间借用,不得修改 Header,跨回调保留数据须自行复制。
type JetStreamHandlerRegistry ¶
type JetStreamHandlerRegistry struct {
// contains filtered or unexported fields
}
JetStreamHandlerRegistry 保存名称到 JetStream Handler 的映射,零值可用。 登记与装配快照可并发;首次使用后不得复制。登记不读配置或执行业务。
func MustNewJetStreamHandlerRegistry ¶
func MustNewJetStreamHandlerRegistry(handlers ...JetStreamHandler) *JetStreamHandlerRegistry
MustNewJetStreamHandlerRegistry 以原始函数名批量登记包级具名函数,区分大小写。 nil 或重名会 panic;方法值、闭包和泛型函数须通过 MustRegister 显式命名。
func (*JetStreamHandlerRegistry) Handlers ¶
func (r *JetStreamHandlerRegistry) Handlers() map[string]JetStreamHandler
Handlers 返回独立映射快照;nil 或空注册表返回空清单。 修改快照和后续登记互不影响;函数捕获的业务依赖仍由调用方管理。
func (*JetStreamHandlerRegistry) MustRegister ¶
func (r *JetStreamHandlerRegistry) MustRegister(handler JetStreamHandler, name ...string)
MustRegister 登记 Handler,可选稳定名称最多一个;非法名称、nil 或重名会 panic。 自动名称随函数重命名变化;方法值、闭包和泛型函数必须显式命名。