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 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() cb.mu.RLock()
@@ -163,6 +172,18 @@ func (cb *CircuitBreaker) RecordSuccess(ctx context.Context) {
if cb.state == StateHalfOpen { if cb.state == StateHalfOpen {
cb.halfOpenSuccess++ 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 { if cb.halfOpenSuccess >= cb.config.HalfOpenSuccess {
oldState := cb.state oldState := cb.state
cb.state = StateClosed cb.state = StateClosed
@@ -232,6 +253,7 @@ func (cb *CircuitBreaker) setRedisState(ctx context.Context) {
stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName) stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName)
failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName) failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName)
lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName) lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName)
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
// 设置熔断状态 // 设置熔断状态
ttl := int64(cb.config.Timeout.Seconds()) ttl := int64(cb.config.Timeout.Seconds())
@@ -258,6 +280,14 @@ func (cb *CircuitBreaker) setRedisState(ctx context.Context) {
glog.Errorf(ctx, "设置最后失败时间到 Redis 失败: %v", err) 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) glog.Infof(ctx, "📡 熔断状态已同步到 Redis - 服务: %s", cb.serviceName)
} }
@@ -266,6 +296,7 @@ func (cb *CircuitBreaker) clearRedisState(ctx context.Context) {
stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName) stateKey := fmt.Sprintf(CircuitBreakerStateKeyPrefix, cb.serviceName)
failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName) failuresKey := fmt.Sprintf(CircuitBreakerFailuresKeyPrefix, cb.serviceName)
lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName) lastFailKey := fmt.Sprintf(CircuitBreakerLastFailKeyPrefix, cb.serviceName)
halfOpenKey := fmt.Sprintf(CircuitBreakerHalfOpenKeyPrefix, cb.serviceName)
// 删除熔断状态 // 删除熔断状态
_, err := redis.RedisClient.Del(ctx, stateKey) _, err := redis.RedisClient.Del(ctx, stateKey)
@@ -285,6 +316,12 @@ func (cb *CircuitBreaker) clearRedisState(ctx context.Context) {
glog.Errorf(ctx, "删除最后失败时间从 Redis 失败: %v", err) 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) glog.Infof(ctx, "📡 熔断状态已从 Redis 清除 - 服务: %s", cb.serviceName)
} }