返回顶部
首页 > 资讯 > 后端开发 > GO >go-kit组件使用hystrix中间件的操作
  • 380
分享到

go-kit组件使用hystrix中间件的操作

hystrixGO 2022-06-07 20:06:23 380人浏览 独家记忆
摘要

使用Go-kit中间件时,一般在endpoint中进行中间件的开发。 在endpoint层插入hystrix中间件的插入。 endpoint.go func MakeEndp

使用Go-kit中间件时,一般在endpoint中进行中间件的开发

在endpoint层插入hystrix中间件的插入。

endpoint.go

func MakeEndpoint (svc services.StringService) endpoint.Endpoint {
 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
  req := request.(*StringService.Request)
  rep , err  := svc.Diff(ctx , req)
  return rep , err
 }
}

go-kit使我们更注重对服务逻辑的开发,对中间过程的省略会减少很多的错误发生。

main.go

package main
import (
 "balencegrpc/services"
 "balencegrpc/router"
 "balencegrpc/proto"
 "balencegrpc/discover"
 "balencegrpc/endpoints"
 "GitHub.com/go-kit/kit/circuitbreaker"
 "google.golang.org/grpc"
 "google.golang.org/grpc/health/grpc_health_v1"
 "log"
 "net"
)
func main() {
 //svc := new()
  svc := services.ServiceI{}
 endpoint := circuitbreaker.Hystrix("testname")(endpoints.MakeEndpoint(svc))
 lis , err := net.Listen("tcp" , ":8081")
 if err != nil {
  log.Println(err)
  return
 }
 router := router.NewRouter(svc , endpoint)
 grpcserver := grpc.NewServer()
 c := discover.Service{}
 grpc_health_v1.ReGISterHealthServer(grpcserver , &c)
 StringService.RegisterStringServiceServer(grpcserver , router)
 rs := discover.NewService()
 rs.Register("127.0.0.1" , 8081)
 grpcserver.Serve(lis)
}

我们在main.go中进行添加hystrix对endpoint进行封装,,使用hystrix进行服务熔断的处理。其实使用go-kit封装的。也可以自行封装一个中间件,在创建endpoint时进行封装

补充:go-kit微服务熔断机制的实现

微服务架构中,每一个微服务都是一个独立的业务功能单元,而一个应用一般由多个微服务组成,微服务之间的交互是通过RPC(远程过程调用)完成。

比如,我们的应用是微服务A调用微服务B和微服务C来完成的,而微服务B又需要调用微服务D,微服务D又需要调用微服务E。如果在调用的链路上对微服务E的调用,响应时间过长或者服务不可用,那么对微服务D的调用就会占用越来越多的系统资源,进而引起微服务D的系统崩溃,微服务D的不可用,又会连反应的引起微服务B崩溃,进而微服务A崩溃,最终导致整个应用不可用。这也就是所谓的“雪崩效应”。

介绍

go-kit 提供了三种熔断

1、 gobreaker

2、 handy

3、 hystrix-go

hystrix用的比较多,我们来介绍下go-kit中hystrix的使用方法

go-kit的hystrix

Middleware的实现

1、 Hystrix返回Middleware 此中间件会在原来的endPoint包一层Hystrix的endPoint

2、 hystrix通过传入的commanName获取对应的Hystrix的设置,并设置run失败时运行的fallback函数为nil

3、 我们也可以自己实现middleware包装endPoint


func Hystrix(commandName string) endpoint.Middleware {  
   return func(next endpoint.Endpoint) endpoint.Endpoint {  
      return func(ctx context.Context, request interface{}) (response interface{}, err error) {  
         var resp interface{}  
         if err := hystrix.Do(commandName, func() (err error) {  
            resp, err = next(ctx, request)  
            return err  
         }, nil); err != nil {  
            return nil, err  
         }  
         return resp, nil  
      }  
   }  
}
客户端hystrix配置

1、Timeout 【请求超时的时间】

2、ErrorPercentThreshold【允许出现的错误比例】

3、SleepWindow【熔断开启多久尝试发起一次请求】

4、MaxConcurrentRequests【允许的最大并发请求数】

5、RequestVolumeThreshold 【波动期内的最小请求数,默认波动期10S】


commandName := "my-endpoint"  
hystrix.ConfigureCommand(commandName, hystrix.CommandConfig{  
  Timeout: 1000 * 30,  
  ErrorPercentThreshold: 1,  
  SleepWindow: 10000,  
  MaxConcurrentRequests: 1000,  
  RequestVolumeThreshold: 5,  
})

增加熔断中间件的包装


breakerMw := circuitbreaker.Hystrix(commandName)
//增加熔断中间件  
reqEndPoint = breakerMw(reqEndPoint)
实例 1、protobuf文件及生成对应的go文件

syntax = "proto3"; 
// 请求书详情的参数结构  book_id 32位整形
message BookInfoParams {
    int32 book_id = 1;
} 
// 书详情信息的结构   book_name字符串类型
message BookInfo {
    int32 book_id = 1;
    string  book_name = 2;
}
// 请求书列表的参数结构  page、limit   32位整形
message BookListParams {
    int32 page = 1;
    int32 limit = 2;
} 
// 书列表的结构    BookInfo结构数组
message BookList {
    repeated BookInfo book_list = 1;
}
// 定义 获取书详情  和 书列表服务   入参出参分别为上面所定义的结构
service BookService {
    rpc GetBookInfo (BookInfoParams) returns (BookInfo) {}
    rpc GetBookList (BookListParams) returns (BookList) {}
}

生成对应的go语言代码文件:protoc --go_out=plugins=grpc:. book.proto (其中:protobuf文件名为:book.proto)

注:由于演示熔断机制,也就是Server出现问题的时候进行熔断,因此本文Server端代码可以不用。

2、Client端代码

package main 
import (
"MyKit"
"context"
"fmt"
"github.com/afex/hystrix-go/hystrix"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/etcdv3"
"github.com/go-kit/kit/sd/lb"
"google.golang.org/grpc"
"io"
"time"
)
func main() { 
var (
//注册中心地址
etcdServer = "127.0.0.1:2379"
//监听的服务前缀
prefix = "/services/book/"
ctx    = context.Background()
)
//对hystrix进行配置
commandName:="my_endpoint"
hystrix.ConfigureCommand(commandName,hystrix.CommandConfig{
Timeout:1000*3, //超时
MaxConcurrentRequests:100, //最大并发的请求数
RequestVolumeThreshold:5,//请求量阈值
SleepWindow:10000, //熔断开启多久尝试发起一次请求
ErrorPercentThreshold:1, //误差阈值百分比
})
breakerMw:=circuitbreaker.Hystrix(commandName) //定义熔断器中间件
options := etcdv3.ClientOptions{
DialTimeout:   time.Second * 3,
DialKeepAlive: time.Second * 3,
}
//连接注册中心
client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
if err != nil {
panic(err)
}
logger := log.NewNopLogger()
//创建实例管理器, 此管理器会Watch监听etc中prefix的目录变化更新缓存的服务实例数据
instancer, err := etcdv3.NewInstancer(client, prefix, logger)
if err != nil {
panic(err)
}
//创建端点管理器, 此管理器根据Factory和监听的到实例创建endPoint并订阅instancer的变化动态更新Factory创建的endPoint
endpointer := sd.NewEndpointer(instancer, reqFactory, logger) //reqFactory自定义的函数,主要用于端点层(endpoint)接受并显示数据
//创建负载均衡器
balancer := lb.NewRoundRobin(endpointer)


reqEndPoint := lb.Retry(3, 100*time.Second, balancer) //请求次数为3,时间为10S(时间需要多于服务器限流时间3s)
//增加熔断中间件
reqEndPoint=breakerMw(reqEndPoint)
//现在我们可以通过 endPoint 发起请求了
req := struct{}{}
for i:=0;i<20;i++ {  //发生20次请求
ctx=context.Background()
if _, err = reqEndPoint(ctx, req); err != nil {
//panic(err)
fmt.Println("当前时间: ", time.Now().FORMat("2006-01-02 15:04:05.99"),"\t第",i+1,"次")
fmt.Println(err)
time.Sleep(1*time.Second)
}
}
}
//通过传入的 实例地址  创建对应的请求endPoint
func reqFactory(instanceAddr string) (endpoint.Endpoint, io.Closer, error) {
return func(ctx context.Context, request interface{}) (interface{}, error) {
conn, err := grpc.Dial(instanceAddr, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
panic("connect error")
}
defer conn.Close()
bookClient := book.NewBookServiceClient(conn)
bi, _ := bookClient.GetBookInfo(context.Background(), &book.BookInfoParams{BookId: 1})
fmt.Println("获取书籍详情")
fmt.Println("bookId: 1", " => ", "bookName:", bi.BookName)
fmt.Println("请求服务成功: ", instanceAddr,"当前时间为:",time.Now().Format("2006-01-02 15:04:05.99"))

return nil, nil
}, nil, nil
}
3、运行及分析

直接运行Client端(不用启动etcd、Server),效果如下:

通过上面的输出记录可以验证我们的配置:

1、 前5条波动期内的错误,没有触发circuit开启(RequestVolumeThreshold:5,//请求量阈值)

2、 circuit开启后请求熔断生效(输出内容:hystrix: circuit open)

3、 circuit开启10S后,SleepWindow测试发起请求设置生效(第16次输出的内容;设置:SleepWindow:10000, //熔断开启多久尝试发起一次请求)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。如有错误或未考虑完全的地方,望不吝赐教。


您可能感兴趣的文档:

--结束END--

本文标题: go-kit组件使用hystrix中间件的操作

本文链接: https://lsjlt.com/news/30597.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • go-kit组件使用hystrix中间件的操作
    使用go-kit中间件时,一般在endpoint中进行中间件的开发。 在endpoint层插入hystrix中间件的插入。 endpoint.go func MakeEndp...
    99+
    2022-06-07
    hystrix GO
  • golang使用grpc+go-kit模拟oauth认证的操作
    我们使用grpc对外的接口,进行服务,模拟对外认证的接口 首先我们要了解oauth的基本认证过程 第三方的服务端,在oauth2.0中作为一个客户端的身份,进行请求数据。 用户进行...
    99+
    2024-04-02
  • 利用go-kit组件进行服务注册与发现和健康检查的操作
    在go的微服务架构中 使用go-kit组件进行开发微服务 type Reg struct { Host string Port int Client consul.Clien...
    99+
    2022-06-07
    健康 GO
  • 使用Python中Tkinter模块的Treeview 组件显示ini文件操作
    前言: Tkinter模块的Treeview组件类似于Dev中的treelist控件,但前者还可以当做树控件和表格控件使用,虽然功能可能没有dev和winform控件那么强大,但是在...
    99+
    2024-04-02
  • ASP 中如何使用接口操作数组文件?
    ASP 中使用接口操作数组文件是一个非常常见的需求,尤其是在开发需要大量操作文件的网站时。本文将介绍如何使用接口来操作数组文件,并提供相应的代码演示。 一、什么是接口 在面向对象的编程中,接口是一种规范。它定义了一组方法、属性或事件,供其他...
    99+
    2023-07-19
    接口 数组 文件
  • C#中怎么操作TreeView组件
    C#中怎么操作TreeView组件,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。C#编写操作TreeView组件的例子:下面是C#编写操作TreeView组件的例子,在这个...
    99+
    2023-06-17
  • python元组,文件的操作
    新手刚刚开始学习python,如有写错或者写的不好的地方,请大家多多指导!python元组相加a = (1,2)b = (3,4)a + b元组运用乘法(1,2) * 4  #在这里边,元组不会被当成数字来计算,而是输出4次给字母类型的元组...
    99+
    2023-01-31
    操作 文件 python
  • PHP中如何使用对象数组来操作文件?
    PHP是一门广泛应用于Web开发的编程语言,它具有简单易学、开发效率高的优点。在PHP中,使用对象数组来操作文件是一种非常常见的方式。本文将介绍PHP中如何使用对象数组来操作文件。 一、打开文件 在PHP中,我们可以使用fopen()函数来...
    99+
    2023-08-26
    对象 数组 文件
  • Go语言中JSON文件的读写操作
    目录写 JSON 文件读 JSON 文件JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。它基于 ...
    99+
    2023-05-14
    Go语言JSON读写 Go语言读写JSON
  • Go语言中XML文件的读写操作
    目录写 XML 文件读 XML 文件XML(extensible Markup Language)格式被广泛用作一种数据交换格式,并且自成一种文件格式。与上一节介绍的 JSON 相比...
    99+
    2023-05-14
    Go语言XML文件读写 Go语言XML读写
  • Vue组件中的父子组件使用
    目录Vue组件中的父子组件父组件向子组件传值子组件向父组件传值Vue父子组件的生命周期总结Vue组件中的父子组件 父组件向子组件传值 父组件通过属性绑定(v-bind:)的形式, 把...
    99+
    2023-01-28
    Vue组件 Vue父子组件 Vue父子组件使用
  • Vue3中使用ref标签对组件进行操作方法
    目录Vue3使用ref标签补充:Vue3 中 ref 标记组件使用父组件子组件Vue3使用ref标签 在Vue2中 一般用 this.$ref.xxxx 进行获取组件对象Vue3中就...
    99+
    2023-05-16
    Vue3使用ref标签 Vue3  ref 标记组件
  • Django中间件的使用
    中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应可以通过中间件,也就是说中间件可以处理request和resp...
    99+
    2023-01-30
    中间件 Django
  • C# 中如何使用Delphi控件操作Excel文件
    这篇文章给大家介绍C# 中如何使用Delphi控件操作Excel文件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C# 操作Excel之Delphi控件方法在Form中分别放入ExcelApplication,Exce...
    99+
    2023-06-17
  • Go语言中常见的文件操作分享
    目录常用包os与I/O操作相关包常用文件/目录操作路径拼接创建文件(touch)获取文件信息读取文件内容写入文件内容常用包 文件操作应该是应用程序里非常常见的一种操作,无论是哪种应用...
    99+
    2023-01-30
    Go语言常见文件操作 Go语言文件操作 Go 文件操作
  • 如何在Java中使用Shell脚本操作数组和文件?
    Java是一种非常流行的编程语言,常用于开发Web应用程序和移动应用程序。在Java中,我们可以使用Shell脚本来操作数组和文件,这使得开发者可以更加轻松地管理数据和文件。本文将介绍如何在Java中使用Shell脚本操作数组和文件。 一、...
    99+
    2023-10-31
    shell 数组 文件
  • 使用Python操作PDF文件
    从PDF读取文本内容和从已经有的文档生成新的PDF。 需要用到的模块是PyPDF2. mstamy2/PyPDF2: A utility to read and write PDFs...
    99+
    2024-04-02
  • amazeui如何使用时间组件
    这篇文章给大家分享的是有关amazeui如何使用时间组件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、总结一句话总结:图标是字体样式:input右侧的字体图标是字体样式,所以要引入字体文件,随便找一个项目把里...
    99+
    2023-06-09
  • Go语言中如何使用索引来操作数组?
    Go语言是一门受欢迎的编程语言,它提供了许多方便易用的工具和API,其中包括数组。在Go语言中,数组是一种基本的数据结构,它可以存储一组具有相同数据类型的元素。当我们需要对数组进行操作时,索引是一个非常重要的概念。在本文中,我们将探讨如何使...
    99+
    2023-11-06
    索引 数组 存储
  • QtQFile文件操作的具体使用
    目录QFile文件操作QFile+QTextStreamQFile+QDataStream很多应用程序都需要具备操作文件的能力,包括对文件内容进行读/写、创建和删除文件等,甚至某些应...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作