Golang 中的断路器模式

2023-12-25 08:01:39 浏览数 (1)

断路器模式的工作原理是引入一个“断路器”组件,该组件充当调用服务与其调用的服务之间的代理。断路器会跟踪它所调用的服务的运行状况,如果它检测到服务出现故障,它将打开电路并停止向失败的服务发送请求。这样可以防止调用服务因失败的请求而陷入困境,并允许其继续运行。

断路器实现

下面是如何在 Golang 中实现 Circuit Breaker 模式的示例:

代码语言:go复制
type CircuitBreaker struct {
    requests chan struct{}
    timeout  time.Duration
}
代码语言:go复制
func NewCircuitBreaker(timeout time.Duration) *CircuitBreaker {
    return &CircuitBreaker{
        requests: make(chan struct{}, 1),
        timeout:  timeout,
    }
}
func (cb *CircuitBreaker) Call(fn func() error) error {
    select {
    case cb.requests <- struct{}{}:
    default:
        return fmt.Errorf("circuit breaker is open")
    }
    defer func() { <-cb.requests }()
    done := make(chan error, 1)
    go func() { done <- fn() }()
    select {
    case err := <-done:
        return err
    case <-time.After(cb.timeout):
        return fmt.Errorf("request timed out")
    }
}

可以这样使用

代码语言:go复制
cb := NewCircuitBreaker(time.Second)
err := cb.Call(func() error {
    // call the service you want to protect
    return nil
})
if err != nil {
    // handle error
}

有几个开源库在 Golang 中实现了 Circuit Breaker 模式。以下是一些流行的:

Hystrix:这是 Netflix 的一个库,提供了广泛的容错功能,包括断路器。它广泛用于微服务架构,如果您需要全面的容错解决方案,它是一个不错的选择。以下是如何在 Golang 中使用 Hystrix 的示例:

代码语言:go复制
func main() {
    hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{
        Timeout:               1000,
        MaxConcurrentRequests: 100,
        ErrorPercentThreshold: 25,
    })
    hystrix.Go("my_command", myCommand)
}
func myCommand() error {
    // call the service you want to protect
    return nil
}

Go-Hystrix:这是 Hystrix 库的 Go 移植。它提供了与 Hystrix 类似的功能,但用纯 Golang 编写,不需要任何额外的依赖项。下面是如何使用 Go-Hystrix 的示例:

代码语言:go复制
func main() {
    hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{
        Timeout:               1000,
        MaxConcurrentRequests: 100,
        ErrorPercentThreshold: 25,
    })
    hystrix.Go("my_command", myCommand)
}

Go-Circuit:这是一个轻量级的 Circuit Breaker 库,它提供了一个简单易用的 API。如果您只需要基本的断路器功能,并且不需要更全面的库的所有花里胡哨的功能,那么这是一个不错的选择。下面是如何使用 Go-Circuit 的示例:

代码语言:go复制
cb := circuit.NewThresholdBreaker(10)
err := cb.Call(func() error {
    // call the service you want to protect
    return nil
})
if err != nil {
    // handle error
}

断路器模式也可以在 Istio 服务网格中实现,这是一种在微服务架构中管理和路由流量的方法。Istio 具有内置的断路器功能,可用于根据服务的运行状况自动打开和关闭电路。

以下是如何在 Istio 中配置断路器的示例:

代码语言:yaml复制
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myservice
spec:
  hosts:
  - myservice.com
  http:
  - route:
    - destination:
        host: myservice
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: gateway-error,connect-failure,refused-stream
    circuitBreaker:
      maxConnections: 10
      httpMaxRequests: 5
      httpConsecutiveErrors: 3
      httpDetectionInterval: 5s

此配置为“myservice”服务设置一个断路器,如果连接超过 10 个、间隔为 5 秒的 HTTP 请求超过 5 个或连续 3 个 HTTP 错误,该中断器将打开电路。

断路器模式是一种强大的工具,用于管理分布式系统的复杂性,并确保其在发生故障时保持弹性。它是构建健壮、容错系统的技术工具箱的一个很好的补充。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

0 人点赞