diff --git a/middleware/circuit_breaker.go b/middleware/circuit_breaker.go index 7678220..73d67ba 100644 --- a/middleware/circuit_breaker.go +++ b/middleware/circuit_breaker.go @@ -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) }