golang 微服务容错处理是如何做的?

随着微服务的规模越来越大,各个微服务之间可能会存在错综复杂的调用关系

在我们实际工作中,确实慢慢的也出现了很多问题,整个系统的弊端的慢慢的展现出来

例如就会有这样的情况:

  • 服务 A 去请求服务B,服务 B 还需要去请求 服务 C,由于服务 C 的问题,导致整条链路都出现了问题,甚至整个系统都坏掉

工作中,我们一般为了提高服务的健壮性,会去设置失败后重试机制,用来避免一些因为网络抖动,暂时性的故障

可是,如果是一个长期性的故障,那么这个重试机制,只会加重我们服务的负担,一直在消耗连接和性能

这个时候,就需要服务熔断机制

服务熔断机制

服务的熔断机制是什么呢?

其实熔断,是我们以前学习物理知识的时候听到过的词,例如家里的电路,在总开关的位置,都会有一个保险丝来保障我们电路的安全,若是出现了短路,或者是电流异常过大的情况下,保险丝就会因为过热而被熔断,进而断电,最终达到保护电表和电路的作用

在如今的微服务架构中,也需要有这一根保险丝

如上图,是一个很常见的微服务之间的调用关系

请求 :客户端 – 网关 – 服务A – 服务B

响应:服务B – 服务A – 网关 – 客户端

整条链路中,只要有一个点出现问题,客户端都无法得到期望的结果

在微服务架构中,服务之间的调用一般分为

  • 服务调用方
  • 服务提供方

为什么需要熔断?

当下游的服务因为过载或故障,无法提供服务,我们需要及时的让上游服务知悉,且暂时 熔断 调用方和提供方的调用链,这是为了避免服务雪崩现象的发生

服务雪崩

服务雪崩就是指调用链中的某个环节不可用了,此处特别指的是服务的提供方,导致上游服务不可用,并最终影响像雪崩一样扩散到整个系统,最终导致整个系统都不可用

简单故障场景

还是上面的一个熟悉场景,正常的 客户端 – 网关 – 服务A – 服务B 请求过程中,上面展示了三个阶段,这也是服务雪崩一般的 3 个阶段

  • 服务提供者不可用

系统运行之处,一切运转良好。每个服务正常请求和响应,当某一个刻,服务 B 由于 自身异常,或者网络故障导致自身不可用,无法及时的响应打过来的各种请求

  • 服务调用者不可用

在 服务B 作为服务提供者不可用的时候,客户端可能会因为错误提示,或者长时间的阻塞而不断的发送相同的请求到网关去,请求再次发送到网关,发送到 服务 A,最终又到 服务 B 知道超时也没有正常响应

重复多次,因为服务 A发起了过多的请求给到服务 B 而产生的等待线程,耗尽了线程池中的资源,那么 服务 A 自身也无法及时响应外部的请求,最终导致 服务 A 也不可用

  • 整个系统不可用

经过上述的流程,服务 A同样也阻塞了转发请求的网关,网关因为大量的等待请求响应也会产生大量的阻塞线程,同样的道理,网关最后没有足够的资源去处理其他请求,这样就导致整个系统无法对外提供服务

加上服务融到保障系统的可用性

如上图,服务 A 访问 服务 B 的过程中,中间加了一个保险丝,也就是一个断路器,

  • 当服务 A 访问 服务 B 的时候,服务 B 这时出现了轻微故障,导致超时返回
  • 服务 A 又 继续访问 服务 B 的时候,服务 B 已经不可用了,导致相应失败
  • 此时断路器检测到异常,则打开保险丝,设置异常返回
  • 服务 A 再次访问服务 B,保险丝自身就立即返回 错误消息给到 服务 A,这样避免服务 A 资源耗尽而不可用,进而保护了服务调用者

断路器

如上图,断路器有 3 中状态互相切换,我们可以这样来理解:

1 关闭状态 – 打开状态

  • 周期内函数执行失败超出阈值,就会从关闭状态到打开状态

2 打开状态 – 半开状态

  • 一定时候后,断路器会尝试执行请求函数,就会转到半开状态

3 半开 – 关闭

  • 尝试执行请求成功次数超过设定的阈值,就会转到关闭状态

4 半开状态 – 打开状态

  • 尝试执行请求函数成功次数没有超过设定的阈值,就会转到打开状态

今天就到这里,学习所得,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

本作品采用《CC 协议》,转载必须注明作者和本文链接
关注微信公众号:阿兵云原生
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!