fix: 补充半开状态的分布式同步逻辑
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user