3.1 惊呆了!服务熔断降级竟然这么简单?
在构建高可用的分布式系统时,服务熔断和降级是两个至关重要的概念。它们能够帮助系统在面对故障和异常情况时保持稳定运行,避免故障的级联传播。本节将深入探讨服务熔断和降级的原理,并通过实际的Go代码示例展示如何实现这些机制。
服务熔断与降级概述
什么是服务熔断?
服务熔断是一种保护机制,当某个服务出现故障或响应时间过长时,系统会暂时切断对该服务的调用,避免故障扩散到整个系统。熔断器就像电路中的保险丝,当电流过大时自动断开,保护电路安全。
什么是服务降级?
服务降级是指在系统面临压力或部分服务不可用时,通过关闭非核心功能或提供简化的服务来保证核心功能的正常运行。降级是一种有损但可用的策略。
熔断器模式实现
熔断器状态
熔断器通常有三种状态:
- 关闭状态(Closed):正常状态下,允许请求通过
- 打开状态(Open):故障状态下,拒绝所有请求
- 半开状态(Half-Open):尝试恢复状态下,允许有限的请求通过
// CircuitBreakerState 熔断器状态typeCircuitBreakerStateintconst(// StateClosed 关闭状态StateClosed CircuitBreakerState=iota// StateOpen 打开状态StateOpen// StateHalfOpen 半开状态StateHalfOpen)// String 状态字符串表示func(s CircuitBreakerState)String()string{switchs{caseStateClosed:return"Closed"caseStateOpen:return"Open"caseStateHalfOpen:return"Half-Open"default:return"Unknown"}}熔断器核心实现
// CircuitBreaker 熔断器typeCircuitBreakerstruct{// 配置config*CircuitBreakerConfig// 当前状态state CircuitBreakerState// 最后失败时间lastFailureTime time.Time// 连续失败次数failureCountint64// 半开状态下的请求数halfOpenRequestsint64// 互斥锁mutex sync.RWMutex}// CircuitBreakerConfig 熔断器配置typeCircuitBreakerConfigstruct{// 失败阈值FailureThresholdint64// 超时时间Timeout time.Duration// 半开状态下的请求数阈值HalfOpenMaxRequestsint64// 熔断器打开后的休眠时间OpenTimeout time.Duration}// NewCircuitBreaker 创建熔断器funcNewCircuitBreaker(config*CircuitBreakerConfig)*CircuitBreaker{return&CircuitBreaker{config:config,state:StateClosed,}}// Execute 执行受保护的函数func(cb*CircuitBreaker)Execute(fnfunc()error)error{cb.mutex.Lock()// 检查当前状态switchcb.state{caseStateOpen:// 检查是否可以转换到半开状态iftime.Since(cb.lastFailureTime)>=cb.config.OpenTimeout{cb.state=StateHalfOpen cb.halfOpenRequests=0}else{cb.mutex.Unlock()returnfmt.Errorf("circuit breaker is open")}caseStateHalfOpen:// 检查半开状态下的请求数是否超过阈值ifcb.halfOpenRequests>=cb.config.HalfOpenMaxRequests{cb.mutex.Unlock()returnfmt.Errorf("circuit breaker is half-open, max requests reached")}cb.halfOpenRequests++}cb.mutex.Unlock()// 执行函数err:=fn()// 更新状态cb.updateState(err==nil)returnerr}// updateState 更新熔断器状态func(cb*CircuitBreaker)updateState(successbool){cb.mutex.Lock()defercb.mutex.Unlock()switchcb.state{caseStateClosed:ifsuccess{// 成功,重置失败计数cb.failureCount=0}else{// 失败,增加失败计数cb.failureCount++cb.lastFailureTime=time.Now()// 检查是否达到失败阈值ifcb.failureCount>=cb.config.FailureThreshold{cb.state=StateOpen}}caseStateOpen:// 在打开状态下不应该调用此方法// 状态转换在Execute方法中处理caseStateHalfOpen:ifsuccess{// 成功,转换到关闭状态cb.state=StateClosed cb.failureCount=0}else{// 失败,转换到打开状态cb.state=StateOpen cb.lastFailureTime=time.Now()}}}// State 获取当前状态func(cb*CircuitBreaker)State()CircuitBreakerState{cb.mutex.RLock()defercb.mutex.RUnlock()returncb.state}// Metrics 获取熔断器指标func(cb*CircuitBreaker)Metrics()map[string]interface{}{