(给Go开发大全加星标)

来源:Che Dan

https://medium.com/@dche423/micro-in-action-7-cn-ce75d5847ef4

【导读】熔断和限流机制对于大流量高并发服务来说不可或缺,尤其在微服务架构下更需要在服务中配置熔断限流机制。对可用性要求高的系统,熔断和限流是非常必要的保障可用性手段,本文介绍了Golang熔断和限流的实现。

今天来谈谈熔断与限流。

熔断与限流一直大型系统架构的重要话题。当我们开始把系统拆分成由很多微服务组成分布式系统时, 这些话题变得比以往更加重要。没有熔断与限流, 系统很容易因为单个组件的故障(这在分布式系统中不可避免)而形成“雪崩”效应, 进而导致整个系统的瘫痪。

在Micro的可插拔架构之下,可以非常容易地引入以上机制。我们知道Micro支持用中间件实现请求的拦截与控制。而这些中间件中最关键的两类是:

  1. micro.WrapClient ,用于包装对外发出的请求,即客户端包装

  2. micro.WrapHandler ,用于包装外界发来的请求,即服务端包装

这两类中间件刚好分别适用于熔断和限流两个场景。下面我们以实例来说明如何利用这类两中间件来提高系统的鲁棒性。

熔断

你可能已经猜到了, 如此常见的工具一般情况下不需要我们自己开发。社区中已经有一些非常优秀的开源熔断组件,例如 hystrix-go,gobreaker 。不仅如此, Micro 也提供了对上述组件进行简单封装的插件, 如 hystrix 插件, gobreaker 插件。

有了这些插件的帮助, 在Micro中实现熔断就变得非常简单了。以hystrix为例:

import (...  "github.com/micro/go-plugins/wrapper/breaker/hystrix"...)func main(){...  // New Service  service := micro.NewService(     micro.Name("com.foo.breaker.example"),     micro.WrapClient(hystrix.NewClientWrapper()),  )  // Initialise service  service.Init()...}

只需要在创建service实例的时候指定hystrix插件,系统便具备了自动熔断能力。

所有从此节点发出的Micro服务调用都会受到熔断插件的限制和保护。当请求超时或并发数超限,调用方会立即接收到熔断错误。那么默认的并发限制和时间限制是多少呢?答案在hystrix-go 的源码中。查看github.com/afex/hystrix-go/hystrix/settings.go 将看到几个包级变量:

...   // DefaultTimeout is how long to wait for command to complete, in milliseconds   DefaultTimeout = 1000   // DefaultMaxConcurrent is how many commands of the same type can run at the same time   DefaultMaxConcurrent = 10...
可见默认的超时时间是1000毫秒, 默认最大并发数是10。

注:可调整的熔断设置不只这两项, 但对他们每一项的详细讨论超过了本文范围, 因此不作更多说明。如果有兴趣,可以到hystrix-go官网查看详细文档。

如果默认设置不能满足我们的要求, 则可以通过如下方式修改:

import (...  hystrixGo "github.com/afex/hystrix-go/hystrix"  "github.com/micro/go-plugins/wrapper/breaker/hystrix"...)func main(){...  // New Service  service := micro.NewService(     micro.Name("com.foo.breaker.example"),     micro.WrapClient(hystrix.NewClientWrapper()),  )  // Initialise service  service.Init()  hystrix.DefaultMaxConcurrent = 3//change concurrrent to 3  hystrix.DefaultTimeout = 200 //change timeout to 200 milliseconds...}
如代码所示,默认限制被调整成了3个并发及200毫秒。

你可能会对 DefaultMaxConcurrent 有疑问:这个并发限制的作用域是什么呢?假设我们需要同时调用3个服务,每个服务有3个不同方法。那么是不是说我们必须把DefaultMaxConcurrent设置为成大于33的数字才可以彻底并发呢? *要回答这个问题, 需要搞清楚两点:

首先, DefaultMaxConcurrent 的限制的目标是什么。从hystrix 文档可以看到, 它的目标是hystrix 中的 command:

DefaultMaxConcurrent is how many commands of the same type can run at the same time

接下来就需要看看hystrix插件如何处理不同方法与command的关系。查看 github.com/micro/go-plugins/wrapper/breaker/hystrix/hystrix.go 相关代码如下:

import(  "github.com/afex/hystrix-go/hystrix"  ...)...func (c *clientWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {   return hystrix.Do(req.Service()+"."+req.Endpoint(), func() error {      return c.Client.Call(ctx, req, rsp, opts...)   }, nil)}...

可以看到每一个方法调用都被 hystrix.Do 包装起来。注意其中的req.Service()+”.”+req.Endpoint(),它就是hystrix的command。由于这个字符串中没有包含节点信息, 这意味着对于同一个服务,部署单个还是多个节点对于熔断来说是没有区别的,所有节点都共享一组限制。

至此便可以明确:每一个服务的每一个方法会独立进行并发限制计数,彼此并不影响。DefaultMaxConcurrent 的作用域是方法级的,与节点数无关。因此, 当某个服务的节点数被扩容一倍, 那么也有必要修改相应hystrix 限制,否则此扩容可能无法发挥全部效果。

实践中, 不同方法可能需要不同的熔断指标。如果我们想要更细粒度地进行控制,应该怎么办呢?从上面的源码分析可以看出, 服务方法被映射成了 hystrix command,而hystrix是支持对不同command分别设限的, 具体方法如下:

...hystrix.ConfigureCommand("com.serviceA.methodFoo",   hystrix.CommandConfig{      MaxConcurrentRequests: 50,      Timeout:               10,   })hystrix.ConfigureCommand("com.serviceB.methodBar",   hystrix.CommandConfig{      Timeout: 60,   })...

通过上述代码,我们为两个方法设置了不同的限制。如果某一项没有特别说明, 便会使用系统默认值。

小结: 熔断功能作用于客户端,设置恰当阈值以后, 它可以保障客户端资源不会被耗尽 —— 哪怕是它所依赖的服务处于不健康的状态,也会快速返回错误,而不是让调用方长时间等待。

限流

与熔断类似, 限流也是分布式系统中常用的功能。不同的是, 限流在服务端生效,它的作用是保护服务器:在请求处理速度达到设定的限制以后, 便不再接收和处理更多新请求,直到原有请求处理完成, 腾出空闲。避免服务器因为客户端的疯狂调用而整体垮掉。

打个比方, 假设我们运营一间能容纳10位客人的餐馆。如果同时来了100位客人想要用餐,最好的处理方式是选取前10位进行服务,同时告诉另外90位客人:我们目前无法服务,请改天再来。虽然这90位客人会不开心, 但我们至少保证了前10位可以开心地用餐。

若没有限流措施, 结果是100位客人全进入餐厅, 厨房忙不过来, 客人无处落座。任何人都得不到服务,又不甘心离开。最终的结果是整个餐厅人满为患并最终瘫痪。

在Micro中使用限流功能非常简单,只需增加一行代码就可以实现基于QPS的限流。目前有两个的现成的限流插件可供使用, 本文以 uber rate limiter 插件为例进行说明(当然如果现有插件不满足需求, 完全可以自行开发更适用的插件)。修改hello-srv/main.go:

package mainimport (...   limiter "github.com/micro/go-plugins/wrapper/ratelimiter/uber"...)func main() {   const QPS = 100   // New Service   service := micro.NewService(      micro.Name("com.foo.srv.hello"),      micro.Version("latest"),      micro.WrapHandler(limiter.NewHandlerWrapper(QPS)),   )...}

以上代码便为hello-srv增加了服务器限流能力, QPS上限为100。这个限制由此服务的所有handler所有method 共享。换句话说,此限制的作用域是服务级别的。

总结

熔断和限流很重要。得益于Micro的可插拨架构, 我们可以非常方便地应用这两个重要的功能。

熔断的出发点是保护客户端, 不被外部服务的问题所拖累, 永远快速响应(哪怕得到一个错误,也好于长时间等待)。永远避免资源的过度消耗。

限流的出发点是保护服务器。只处理自己能力之内的流量,实现过载保护。当流量超过设定限制时立即返回错误。

二者结合体现了一个哲学:永远首先为自己负责, 无论外部依赖状态如何, 一个服务应保证自身的稳健。

当这种哲学应用到分布系统的每一个组件以后, 这个系统将变得非常健壮,不会被突发流量高峰击垮。

因此, 我们在分布式系统开发中应该遵循这样一个最佳实践:为每一个服务增加熔断和限流能力。起步时可以是粗粒度的限制, 随着业务的演进, 可以逐步细化控制, 为每一个(每一类)服务设置与其业务相匹配的限制策略。

- EOF -

推荐阅读(点击标题可打开)

1、Golang 垃圾回收原理与优化

2、Go 性能分析工具 pprof 入门

3、RedHat容器术语实用导论

如果觉得本文不错,欢迎转发推荐给更多人。

分享、点赞和在看

支持我们分享更多好文章,谢谢!

golang bufio.newscanner如何超时跳出_Golang微服务的熔断与限流相关推荐

  1. 微服务之熔断、限流、降级 三板斧

    系列服务器开发 文章目录 系列服务器开发 前言 一.背景 二.熔断 三. 限流 四. 降级 五.三种措施的差异 总结 前言 Spring Cloud全家桶是提供的一整套微服务开源解决方案,包括服务注册 ...

  2. SpringCloud微服务组件:Sentinel限流熔断

    点击关注公众号,实用技术文章及时了解 前言 什么是雪崩问题? 微服务之间相互调用,因为调用链中的一个服务故障,引起整个链路都无法访问的情况. 解决雪崩问题的常见方式有四种: 超时处理:设定超时时间,请 ...

  3. 深度好文 — 微服务和API网关限流熔断实现关键逻辑思路

    来源:https://www.toutiao.com/i6853970319745483275/?group_id=6853970319745483275 今天准备谈下微服务架构和API网关中的限流熔 ...

  4. 微服务架构 - Gateway网关限流

    作者:pu20065226 cnblogs.com/pu20065226/p/11426279.html 1.算法 在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户 ...

  5. 微服务中常用的限流算法(一)

    一个业务系统在指定配置的服务器上,可以承载的容量是一定的,当请求流量超过系统的容量后,系统就会变得不稳定,可用性下降,为了保证系统的可用性,需要将系统能够承载容量之外的流量进行丢弃,这样虽然会导致部分 ...

  6. Service Mesh微服务熔断、限流的骚操作

    在微服务架构中,随着服务调用链路变长,为了防止出现级联雪崩,在微服务治理体系中,熔断.限流作为服务自我保护的重要机制,是确保微服务架构稳定运行的关键手段之一. 那么什么是熔断.限流?在传统Spring ...

  7. 玩转Service Mesh微服务熔断、限流骚操作

    在微服务架构中,随着服务调用链路变长,为了防止出现级联雪崩,在微服务治理体系中,熔断.限流作为服务自我保护的重要机制,是确保微服务架构稳定运行的关键手段之一. 那么什么是熔断.限流?在传统Spring ...

  8. 微服务(八)——Hystrix服务降级、熔断、限流(上)

    目录 Hystrix服务降级.熔断.限流 Hystrix是什么 Hystrix停更进维 Hystrix的服务降级熔断限流相关概念 Hystrix支付微服务构建 JMeter高并发压测后卡顿 订单微服务 ...

  9. SpringCloud微服务的熔断机制和熔断的意义?

    什么是微服务的熔断机制 在2017年2月1日,GitLab公司的运维人员就出现过这样的事故.当时运维人员在进行数据库维护时,通过执行rm -rf命令,删除了约300GB生产环境数据.由于数据备份失效, ...

最新文章

  1. 【Network Security!】Web安全学习及异或解密示例
  2. GlusterFS下如何修复裂脑文件?
  3. visio篇章--1
  4. node --- 实践中理解跨域
  5. C++ STL 学习笔记 3. 文本文件操作
  6. java dataset redis,利用Spring-Data-Redis和Jedis操作Redis缓存
  7. linux 中的gzip命令
  8. TCP协议之三次握手与四次挥手
  9. 2004-11-28+ 认识Duwamish 7.0(3)错误处理
  10. unity镜头边缘羽化_【JTRP】屏幕空间深度边缘光 Screen Space Depth Rimlight
  11. Element 入门教程
  12. JDBC个人学习总结
  13. 在worldpress中使用php代码抓取图书馆书籍信息
  14. 2022年HGAME中REVERSE的Flag Checker
  15. 星浩资本快速发展引擎:IT就是生产力
  16. 论 致命错误c0000005
  17. Lucene6.6.0 案例与学习路线
  18. X-Files 目录及剧情简介
  19. keepass2android插件,Keepass2Android
  20. 你知道的APP中,有哪些比较好用有特色的用户互动功能(指用户可以参与进来的功能,比较常见的如评论、关注、投票、聊天室等)?你觉得一个功能具有什么特征,才会让用户愿意互动进来?

热门文章

  1. 解决360浏览器偶发性会闪屏一下黑色的背景
  2. C语言的单链表求交点
  3. ubuntu18.04.1内核升级至5.0.0-25版本
  4. 新手C#string类常用函数的学习2018.08.04
  5. 转载 iOS js oc相互调用(JavaScriptCore) --iOS调用js
  6. 史上最浅显易懂的Git教程!
  7. 翻页导航条页码计算方法
  8. 全球UML模型共享设计下载中心--www.euml.org上线
  9. 全球15个顶级技术类博客
  10. valgrind——Cachegrind分析CPU的cache命中率、丢失率,用于进行代码优化。