服务熔断| 青训营

148 阅读3分钟

1概述

在微服务的架构中,经常会碰到服务超时或者通讯失败的问题,因为服务之间是层层依赖的,很可能某个服务出现问题,导致了层层传递引发雪崩的现象,而熔断就是解决这个问题的一个重要方式。

回到自己的项目,在项目的架构中Api_router依赖用户、视频、社交三个服务:

image.png 服务增加,带来了灵活的同时,对服务稳定性也带来了新的隐患。比如调用视频服务的时候,可能视频服务会出现问题,可能会出现宕机,出现bug,也可能是数据压垮了服务,但是拿不到响应结果,就会触发重试机制,进一步的压垮视频服务,上游服务也会出现大量的等待线程,出现资源耗尽,导致上游服务也变为不可用,形成雪崩效应。

2 Hystrix熔断器

熔断机制可以看作我们日常生活中保险丝的保护机制,电路超负荷运转的时候,保险丝会自动断开,保证电器不会被损害。在服务治理中,熔断指的是在发起服务调用的时候,如果调用返回的错误率超过一定的阈值,后续的请求直接返回错误,而不是反复的重试。

在服务的调用方,会维护一个状态机,这个状态机有三种状态:

  • 关闭(Close):在这种状态下,可以正常的请求响应。同时需要一个计数器来记录调用失败的次数和总的请求次数,如果在某个时间窗口内,失败的失败率达到预设的阈值,则切换到断开状态
  • 打开(Open):在这种状态下,发起请求会立马返回错误。一般会启动一个超时计时器,当计时器超时后,状态切换到半打开状态。
  • 半打开(Half-Open):在该状态下,允许应用程序一定数量的请求发往被调用服务,如果这些调用正常,那么可以认为被调用服务已经恢复正常,此时熔断器切换到关闭状态,同时需要重置计数。

在golang中,hystrix是比较通用的熔断器库,先看一下核心参数:

type Settings struct {
	Timeout                time.Duration
	MaxConcurrentRequests  int
	RequestVolumeThreshold uint64
	SleepWindow            time.Duration
	ErrorPercentThreshold  int
}
  • Timeout:这是执行请求的超时时间。如果请求在这段时间内没有完成,断路器可能会中断该请求,避免等待太长时间。
  • MaxConcurrentRequests:这个参数规定了能够同时处理的最大请求数量。它可以防止系统被过多的并发请求压垮。
  • RequestVolumeThreshold:这是一个请求阈值,表示在一个时间窗口内收到的请求数量。如果请求数量低于这个阈值,即使出现错误,断路器可能仍然保持闭合状态,不中断对服务的请求。如果请求数量超过了这个阈值,错误可能会触发断路器的打开。
  • SleepWindow:这是断路器从打开状态转换到半开状态(部分接受请求)所需的时间。在这段时间内,断路器允许一部分请求通过以便测试服务是否已经恢复正常。
  • ErrorPercentThreshold:这是一个错误百分比阈值。如果错误率达到或超过这个阈值,断路器将会打开,不再接受请求。这是为了避免继续向故障的服务发送请求。

3 具体实现

每次熔断都会向日志文件中打印日志

func NewWrapper(name string) {
	// 设置 Hystrix 配置
	hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{
		Timeout:                1000, // 超时时间(毫秒)
		MaxConcurrentRequests:  10,   // 最大并发请求数
		RequestVolumeThreshold: 5,    // 触发熔断的最小请求数,大于这个值才开始做熔断检测
		SleepWindow:            5000, // 熔断后休眠时间(毫秒)
		ErrorPercentThreshold:  20,   // 错误率阈值
	})

	// 使用 Hystrix 执行命令
	err := hystrix.Do(name, func() error {
		return errors.New("服务熔断")
	}, nil)
	if err != nil {
		logger.Log.Info("请求过快---" + name + "服务熔断")
		fmt.Println("err", err)
	}
}