基于go-micro微服务的实战-Gateway网关层的限流降级(八)
创始人
2024-03-14 00:56:32
0

基于go-micro微服务的实战-Gateway网关层的限流降级(八)


文章最后附带完整代码

这一节主要是在Gateway网关层,基于go-micro的装饰器引入限流和降级。限流降级用的是开源库hystrix,类似java的hystrix,这里不做具体介绍和使用,可自行查看文档。

设计流程是这样

  1. 请求到达网关层,超过一定并发数则限制请求,直接返回默认结果
  2. 请求到达网关层,转发到服务,服务返回错误信息个数达到一定数量,接口熔断,一定时间内请求直接返回默认结果

第一步:网关层新增装饰器

grpc_gateway中新增wrapper目录和client_wrapper.go客户端请求装饰器

import "github.com/asim/go-micro/v3/client"
...
type CliWrapper struct {client.Client
}func (c *CliWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error{log.Println("client wrapper!!!")//限流唯一名commandName := req.Service() + "." + req.Endpoint()//行为主体action := func() error {return c.Client.Call(ctx, req, rsp, opts...)}//限流和降级if HystrixLimit(commandName, req.Endpoint(), action) == nil {return nil}else{//限流降级默认返回结果处理HystrixFallback(rsp)return nil}
}func NewCliWrapper(c client.Client) client.Client{return &CliWrapper{c}
}
第二步:通过hystrix库实现限流和降级

wrapper目录下新增client_limit.go限流处理器。
*注意,这里的限流的并发指的是同时并发,如果串行,单进程一个for循环1w次也是只有一个并发。

几个参数介绍

限流的两个参数:
Timeout:时间毫秒,指定时间内为一个窗口
MaxConcurrentRequests:在窗口时间内,并发最大数的限制下面三个参数是熔断参数,也就是有RequestVolumeThreshold个请求,就判断超过ErrorPercentThreshold比例则熔断,熔断时间SleepWindow
ErrorPercentThreshold:错误率,百分比,超过设定值则打开熔断器,默认50(50%)
RequestVolumeThreshold:请求阈值  熔断器是否打开首先要满足这个条件;这里的设置表示至少有2个请求才进行ErrorPercentThreshold错误百分比计算,默认20
SleepWindow:过多长时间,熔断器再次检测是否开启(是否启动服务运行)。单位毫秒,默认5秒

具体的限流处理器代码

import "github.com/afex/hystrix-go/hystrix"//限流处理
func HystrixLimit(commandName, endpoint string, action func() error) error{var config hystrix.CommandConfigswitch endpoint {case "UserService.UserLogin":			  //登录接口,限制3秒内只能有2个并发config = hystrix.CommandConfig{Timeout: 3000,MaxConcurrentRequests: 2,//下面三个参数是熔断配置,也就是有RequestVolumeThreshold个请求,就判断超过ErrorPercentThreshold比例则熔断,熔断时间SleepWindowErrorPercentThreshold: 25,        //错误率,百分比,超过设定值则打开熔断器,默认50(50%)RequestVolumeThreshold:2,         //请求阈值  熔断器是否打开首先要满足这个条件;这里的设置表示至少有2个请求才进行ErrorPercentThreshold错误百分比计算,默认20SleepWindow: 5000,                //过多长时间,熔断器再次检测是否开启(是否启动服务运行)。单位毫秒,默认5秒}case "UserService.UserReg":               //主从接口,限制5秒内只能有10个并发config = hystrix.CommandConfig{Timeout: 5000,MaxConcurrentRequests: 10,ErrorPercentThreshold: 25,RequestVolumeThreshold:10,SleepWindow: 2000,}default:                                 //默认其它非指定接口的处理config = hystrix.CommandConfig{Timeout: 5000,MaxConcurrentRequests: 10000,ErrorPercentThreshold: 25,RequestVolumeThreshold:100,SleepWindow: 5000,}}hystrix.ConfigureCommand(commandName, config)return hystrix.Do(commandName, func() error{return action()}, func(err error) error{return err})
}
第三步:限流降级中请求默认结果的处理

主要就是针对返回结果,对返回结果做一个默认内容的处理,友好提示等等,根据实际场景做相应处理。

func HystrixFallback(resp interface{}) {switch t:= resp.(type) {case *pb.RegResp:t.Status = 2t.Msg = "please wait to try"case *pb.LoginResp:t.Status = 2t.Msg = "please wait to try"case *pb.TestResp:t.Msg = "is limit"default:}
}
第四步:测试验证

限流测试:
模拟发起登录请求测试,发送6个

	body := "{\"phone\":\"15222222222\",\"pwd\":\"123789\"}"//post 方法参数,第一个参数为请求url,第二个参数 是contentType, 第三个参数为请求体[]byte格式w := sync.WaitGroup{}for i := 1; i <= 6; i++{w.Add(1)go func() {responce, err := http.Post("http://localhost:55001/user/login", "application/json", bytes.NewBuffer([]byte(body)))if err != nil {fmt.Println("net http post method err,", err)}defer responce.Body.Close()w.Done()}()}w.Wait()

按上面第2步的配置,登录接口3秒内限制2个,实际结果6个请求,只有2个可以通过,4个直接返回,符合预期!如图。

限流

降级测试:

修改用户服务的登录接口,直接弄个暴力报错

func (u *UserHandler) UserLogin(ctx context.Context, req *pb.LoginReq, resp *pb.LoginResp) error{var i int = 0log.Println(10/i)

模拟发起登录请求测试,每次发送4个,睡眠3秒

	w := sync.WaitGroup{}for i := 0; i <= 3; i++{w.Add(1)go func() {responce, err := http.Post("http://localhost:55001/user/login", "application/json", bytes.NewBuffer([]byte(body)))if err != nil {fmt.Println("net http post method err,", err)}defer responce.Body.Close()w.Done()}()}time.Sleep(3 *time.Second)for i := 0; i <= 3; i++{w.Add(1)go func() {responce, err := http.Post("http://localhost:55001/user/login", "application/json", bytes.NewBuffer([]byte(body)))if err != nil {fmt.Println("net http post method err,", err)}defer responce.Body.Close()w.Done()}()}w.Wait()

如下图,3秒内只有2个请求可以通过,但是后续的6个请求,接口熔断,不发起请求,直接走默认返回结果
降级

gitee完整代码链接

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...