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