本篇文章参考【Micro In Action(七):熔断与限流】

@dche423写的太好了,这里仅做部分摘录介绍

熔断

go micro 封装了hystrix-go,gobreaker,都在plugins下

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

他的默认值超时时间是1000毫秒,最大并发数是10

    // 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

如果需要修改其他参数,可以在服务service.init()后设置

import (
    ...
    hystrixGo "github.com/afex/hystrix-go/hystrix"
    "github.com/micro/go-plugins/wrapper/breaker/hystrix/v2"
    ...
)
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
    ...
}

DefaultMaxConcurrent限制的是hystrix 中的 command

看看插件中是怎么定义的Call

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)
}

都是return的hystrix.Do(), 他的参数没有包含节点信息,这意味着对于同一个服务,部署单个还是多个节点对于熔断来说是没有区别的,所有节点都共享一组限制

现实项目中,不同服务的负载能力是不同的,go micro可以为不同的服务设置不同的熔断限制

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

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

限流

在服务端生效,它的作用是保护服务器:避免服务器因为客户端的疯狂调用而整体垮掉。

go micro 封装了2个限流包ratelimiter/uber,ratelimiter/ratelimit,都在plugins下

package main

import (
    ...
    limiter "github.com/micro/go-plugins/wrapper/ratelimiter/uber/v2"
    ...
)

func main() {
    const QPS = 100
    // New Service
    service := micro.NewService(
        micro.Name("com.foo.srv.hello"),
        micro.Version("latest"),
        micro.WrapHandler(limiter.NewHandlerWrapper(QPS)),
    )

    ...
}

默认QPS上限为100。这个限制由此服务的所有handler所有method 共享。换句话说,此限制的作用域是服务级别的。

其他设置和熔断的设置类似,具体使用请见官方的文档。

总结:

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

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

go micro 分析系列文章
go micro server 启动分析
go micro client
go micro broker
go micro cmd
go micro config
go micro store
go micro registry
go micro router
go micro runtime
go micro transport
go micro web
go micro registry 插件consul
go micro plugin
go micro jwt 网关鉴权
go micro 链路追踪
go micro 熔断与限流
go micro wrapper 中间件
go micro metrics 接入Prometheus、Grafana