fix: 补充半开状态的分布式同步逻辑

This commit is contained in:
2026-01-01 00:04:43 +08:00
parent bf235c709d
commit 75d9348896

View File

@@ -129,6 +129,15 @@ func (cb *CircuitBreaker) AllowRequest(ctx context.Context) bool {
return false
}
}
// 从 Redis 同步半开成功计数
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
halfOpenValue, err := redis.RedisClient.Get(ctx, halfOpenKey)
if err == nil && !halfOpenValue.IsEmpty() {
cb.mu.Lock()
cb.halfOpenSuccess = gconv.Int(halfOpenValue.Val())
cb.mu.Unlock()
}
}
cb.mu.RLock()
@@ -163,6 +172,18 @@ func (cb *CircuitBreaker) RecordSuccess(ctx context.Context) {
if cb.state == StateHalfOpen {
cb.halfOpenSuccess++
// 分布式模式:同步半开成功计数到 Redis
if cb.config.EnableDistributed {
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
ttl := int64(cb.config.Timeout.Seconds())
_, err := redis.RedisClient.Set(ctx, halfOpenKey, cb.halfOpenSuccess, gredis.SetOption{
TTLOption: gredis.TTLOption{EX: &ttl},
})
if err != nil {
glog.Errorf(ctx, "同步半开成功计数到 Redis 失败: %v", err)
}
}
if cb.halfOpenSuccess >= cb.config.HalfOpenSuccess {
oldState := cb.state
cb.state = StateClosed
@@ -232,6 +253,7 @@ func (cb *CircuitBreaker) setRedisState(ctx context.Context) {
stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName)
failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName)
lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName)
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
// 设置熔断状态
ttl := int64(cb.config.Timeout.Seconds())
@@ -258,6 +280,14 @@ func (cb *CircuitBreaker) setRedisState(ctx context.Context) {
glog.Errorf(ctx, "设置最后失败时间到 Redis 失败: %v", err)
}
// 重置半开成功计数
_, err = redis.RedisClient.Set(ctx, halfOpenKey, 0, gredis.SetOption{
TTLOption: gredis.TTLOption{EX: &ttl},
})
if err != nil {
glog.Errorf(ctx, "设置半开成功计数到 Redis 失败: %v", err)
}
glog.Infof(ctx, "📡 熔断状态已同步到 Redis - 服务: %s", cb.serviceName)
}
@@ -266,6 +296,7 @@ func (cb *CircuitBreaker) clearRedisState(ctx context.Context) {
stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName)
failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName)
lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName)
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
// 删除熔断状态
_, err := redis.RedisClient.Del(ctx, stateKey)
@@ -285,6 +316,12 @@ func (cb *CircuitBreaker) clearRedisState(ctx context.Context) {
glog.Errorf(ctx, "删除最后失败时间从 Redis 失败: %v", err)
}
// 删除半开成功计数
_, err = redis.RedisClient.Del(ctx, halfOpenKey)
if err != nil {
glog.Errorf(ctx, "删除半开成功计数从 Redis 失败: %v", err)
}
glog.Infof(ctx, "📡 熔断状态已从 Redis 清除 - 服务: %s", cb.serviceName)
}