feat(bus): JetStream 流/KV 副本数可配(NATS_STREAM_REPLICAS,默认1)
三机/单机多节点集群部署需 Replicas=3,durable 流才有 Raft quorum 容错(计费/状态/ 用量/评测/审批/入库回写不因单节点挂掉而丢)。此前 6 处 CreateOrUpdateStream + 1 处 KV 桶都未设 Replicas(默认1),集群等于白搭。加 streamReplicas() 读 env(合法值 1/3/5), 7 处统一带上。默认 1 保证单机/CI 不变。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -113,6 +113,7 @@ func (b *Bus) EnsureTaskStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamTasks,
|
Name: contract.StreamTasks,
|
||||||
Subjects: []string{contract.SubjectTasksAll},
|
Subjects: []string{contract.SubjectTasksAll},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -341,6 +342,7 @@ func (b *Bus) EnsureStatusStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamStatus,
|
Name: contract.StreamStatus,
|
||||||
Subjects: []string{contract.SubjectTaskStatus},
|
Subjects: []string{contract.SubjectTaskStatus},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
MaxAge: 24 * time.Hour, // 状态一天内必被消费,过期回收防无限增长
|
MaxAge: 24 * time.Hour, // 状态一天内必被消费,过期回收防无限增长
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -399,6 +401,7 @@ func (b *Bus) EnsureEvalStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamEval,
|
Name: contract.StreamEval,
|
||||||
Subjects: []string{contract.SubjectEval},
|
Subjects: []string{contract.SubjectEval},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
MaxAge: 24 * time.Hour, // 评测一天内必被消费,过期回收防无限增长
|
MaxAge: 24 * time.Hour, // 评测一天内必被消费,过期回收防无限增长
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -453,6 +456,7 @@ func (b *Bus) EnsureUsageStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamUsage,
|
Name: contract.StreamUsage,
|
||||||
Subjects: []string{contract.SubjectUsage},
|
Subjects: []string{contract.SubjectUsage},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
MaxAge: 72 * time.Hour, // 计费留足追赶窗口(网关长时间离线后仍能补齐)
|
MaxAge: 72 * time.Hour, // 计费留足追赶窗口(网关长时间离线后仍能补齐)
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -520,6 +524,7 @@ func (b *Bus) EnsureApprovalStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamApprovals,
|
Name: contract.StreamApprovals,
|
||||||
Subjects: []string{contract.SubjectApprovalAll},
|
Subjects: []string{contract.SubjectApprovalAll},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
MaxAge: 24 * time.Hour,
|
MaxAge: 24 * time.Hour,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -774,6 +779,18 @@ func DrainTimeout() time.Duration {
|
|||||||
return 30 * time.Second
|
return 30 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// streamReplicas 是 JetStream 流/KV 桶的副本数,经 NATS_STREAM_REPLICAS 配置,缺省 1。
|
||||||
|
// 单机(单节点 NATS)保持 1;三机/单机多节点集群部署设 3,durable 流才有 Raft quorum 容错
|
||||||
|
// (计费/状态/用量/评测/审批/入库回写不会因单节点挂掉而丢)。合法值 1/3/5(Raft 需奇数)。
|
||||||
|
func streamReplicas() int {
|
||||||
|
if v := os.Getenv("NATS_STREAM_REPLICAS"); v != "" {
|
||||||
|
if n, err := strconv.Atoi(v); err == nil && (n == 1 || n == 3 || n == 5) {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
// drainWait 停止接新活后,等待在途 WaitGroup 跑完,或 dctx 到期放弃。
|
// drainWait 停止接新活后,等待在途 WaitGroup 跑完,或 dctx 到期放弃。
|
||||||
func drainWait(wg *sync.WaitGroup, dctx context.Context) {
|
func drainWait(wg *sync.WaitGroup, dctx context.Context) {
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@@ -890,6 +907,7 @@ func (b *Bus) EnsureIngestStream(ctx context.Context) error {
|
|||||||
Name: contract.StreamIngest,
|
Name: contract.StreamIngest,
|
||||||
Subjects: []string{contract.SubjectIngestAll},
|
Subjects: []string{contract.SubjectIngestAll},
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
MaxAge: ingestStreamMaxAge,
|
MaxAge: ingestStreamMaxAge,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -1004,6 +1022,7 @@ func (b *Bus) Checkpoints(ctx context.Context, bucket string, ttl time.Duration)
|
|||||||
kv, err := b.js.CreateOrUpdateKeyValue(ctx, jetstream.KeyValueConfig{
|
kv, err := b.js.CreateOrUpdateKeyValue(ctx, jetstream.KeyValueConfig{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Storage: jetstream.FileStorage,
|
Storage: jetstream.FileStorage,
|
||||||
|
Replicas: streamReplicas(),
|
||||||
TTL: ttl,
|
TTL: ttl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user