下面由golang教程栏目给大家介绍关于golang封装一个bash函数,用于执行bash命令析,希望对需要的朋友有所帮助!

开篇

这周在看内部一个熔断限流包时,发现它是基于一个开源项目 hystrix-go 实现了,因此有了这篇文章。

Hystrix

Hystrix 是由 Netflex 开发的一款开源组件,提供了基础的熔断功能。 Hystrix 将降级的策略封装在 Command 中,提供了 run 和 fallback 两个方法,前者表示正常的逻辑,比如微服务之间的调用……,如果发生了故障,再执行 fallback方法返回结果,我们可以把它理解成保底操作。如果正常逻辑在短时间内频繁发生故障,那么可能会触发短路,也就是之后的请求不再执行 run,而是直接执行 fallback。更多关于 Hystrix 的信息可以查看 https://github.com/Netflix/Hystrix,而

hystrix-go 则是用 go 实现的 hystrix 版,更确切的说,是简化版。只是上一次更新还是 2018年 的一次 pr,也就毕业了?

为什么需要这些工具?

比如一个微服务化的产品线上,每一个服务都专注于自己的业务,并对外提供相应的服务接口,或者依赖于外部服务的某个逻辑接口,就像下面这样。

假设我们当前是 服务A,有部分逻辑依赖于 服务C,服务C 又依赖于 服务E,当前微服务之间进行 rpc或者 http通信,假设此时 服务C 调用 服务E 失败,比如由于网络波动导致超时或者服务E由于过载,系统E 已经down掉了。

调用失败,一般会有失败重试等机制。但是再想想,假设服务E已然不可用的情况下,此时新的调用不断产生,同时伴随着调用等待和失败重试,会导致 服务C对服务E的调用而产生大量的积压,慢慢会耗尽服务C的资源,进而导致服务C也down掉,这样恶性循环下,会影响到整个微服务体系,产生雪崩效应。

虽然导致雪崩的发生不仅仅这一种,但是我们需要采取一定的措施,来保证不让这个噩梦发生。而 hystrix-go就很好的提供了 熔断和降级的措施。它的主要思想在于,设置一些阀值,比如最大并发数(当并发数大于设置的并发数,拦截),错误率百分比(请求数量大于等于设置 的阀值,并且错误率达到设置的百分比时,触发熔断)以及熔断尝试恢复时间等 。

使用

hystrix-go 的使用非常简单,你可以调用它的 Go 或者 Do方法,只是 Go 方法是异步的方式。而 Do 方法是同步方式。我们从一个简单的例子开启。_ = hystrix.Do("wuqq", func() error {

// talk to other services

_, err := http.Get("https://www.baidu.com/")

if err != nil {

fmt.Println("get error:%v",err)

return err }

return nil

}, func(err error) error {

fmt.Printf("handle error:%v\n", err)

return nil

})

Do 函数需要三个参数,第一个参数 commmand 名称,你可以把每个名称当成一个独立当服务,第二个参数是处理正常的逻辑,比如 http 调用服务,返回参数是 err。如果处理|调用失败,那么就执行第三个参数逻辑, 我们称为保底操作。由于服务错误率过高导致熔断器开启,那么之后的请求也直接回调此函数。

既然熔断器是按照配置的规则而进行是否开启的操作,那么我们当然可以设置我们想要的值。hystrix.ConfigureCommand("wuqq", hystrix.CommandConfig{

Timeout: int(3 * time.Second),

MaxConcurrentRequests: 10,

SleepWindow: 5000,

RequestVolumeThreshold: 10,

ErrorPercentThreshold: 30,

})

_ = hystrix.Do("wuqq", func() error {

// talk to other services

_, err := http.Get("https://www.baidu.com/")

if err != nil {

fmt.Println("get error:%v",err)

return err }

return nil

}, func(err error) error {

fmt.Printf("handle error:%v\n", err)

return nil

})

稍微解释一下上面配置的值含义:Timeout: 执行 command 的超时时间。

MaxConcurrentRequests:command 的最大并发量 。

SleepWindow:当熔断器被打开后,SleepWindow 的时间就是控制过多久后去尝试服务是否可用了。

RequestVolumeThreshold: 一个统计窗口10秒内请求数量。达到这个请求数量后才去判断是否要开启熔断

ErrorPercentThreshold:错误百分比,请求数量大于等于RequestVolumeThreshold并且错误率到达这个百分比后就会启动熔断

当然你不设置的话,那么自动走的默认值。

我们再来看一个简单的例子:package mainimport (

"fmt"

"github.com/afex/hystrix-go/hystrix" "net/http" "time")type Handle struct{}func (h *Handle) ServeHTTP(r http.ResponseWriter, request *http.Request) {

h.Common(r, request)}func (h *Handle) Common(r http.ResponseWriter, request *http.Request) {

hystrix.ConfigureCommand("mycommand", hystrix.CommandConfig{

Timeout: int(3 * time.Second),

MaxConcurrentRequests: 10,

SleepWindow: 5000,

RequestVolumeThreshold: 20,

ErrorPercentThreshold: 30,

})

msg := "success"

_ = hystrix.Do("mycommand", func() error {

_, err := http.Get("https://www.baidu.com")

if err != nil {

fmt.Printf("请求失败:%v", err)

return err }

return nil

}, func(err error) error {

fmt.Printf("handle error:%v\n", err)

msg = "error"

return nil

})

r.Write([]byte(msg))}func main() {

http.ListenAndServe(":8090", &Handle{})}

我们开启了一个 http 服务,监听端口号 8090,所有请求的处理逻辑都在 Common 方法中,在这个方法中,我们主要是发起一次 http请求,请求成功响应success,如果失败,响应失败原因。

我们再写另一个简单程序,并发 11 次的请求 8090 端口。package mainimport (

"fmt"

"io/ioutil"

"net/http"

"sync"

"time")var client *http.Clientfunc init() {

tr := &http.Transport{

MaxIdleConns: 100,

IdleConnTimeout: 1 * time.Second,

}

client = &http.Client{Transport: tr}}type info struct {

Data interface{} `json:"data"`}func main() {

var wg sync.WaitGroup for i := 0; i < 11; i++ {

wg.Add(1)

go func(int2 int) {

defer wg.Done()

req, err := http.NewRequest("GET", "http://localhost:8090", nil)

if err != nil {

fmt.Printf("初始化http客户端处错误:%v", err)

return

}

resp, err := client.Do(req)

if err != nil {

fmt.Printf("初始化http客户端处错误:%v", err)

return

}

defer resp.Body.Close()

nByte, err := ioutil.ReadAll(resp.Body)

if err != nil {

fmt.Printf("读取http数据失败:%v", err)

return

}

fmt.Printf("接收到到值:%v\n", string(nByte))

}(i)

}

wg.Wait()

fmt.Printf("请求完毕\n")}

由于我们配置 MaxConcurrentRequests 为10,那么意味着还有个 g 请求会失败:

和我们想的一样。

接着我们把网络断开,并发请求改成10次。再次运行程序并发请求 8090 端口,此时由于网络已关闭,导致请求百度失败:

接着继续请求:

熔断器已开启,上面我们配置的RequestVolumeThreshold 和 ErrorPercentThreshold 生效。

然后我们把网连上,五秒后 (SleepWindow的值)继续并发调用,当前熔断器处于半开的状态,此时请求允许调用依赖,如果成功则关闭,失败则继续开启熔断器。

可以看到,有一个成功了,那么此时熔断器已关闭,接下来继续运行函数并发调用:

可以看到,10个都已经是正常成功的状态了。

那么问题来了,为什么最上面的图只有一个是成功的?5秒已经过了,并且当前网络正常,应该是10个请求都成功,但是我们看到的只有一个是成功状态。通过源码我们可以找到答案:

具体逻辑在判断当前请求是否可以调用依赖if !cmd.circuit.AllowRequest() {

......

return

}func (circuit *CircuitBreaker) AllowRequest() bool {

return !circuit.IsOpen() || circuit.allowSingleTest()}func (circuit *CircuitBreaker) allowSingleTest() bool {

circuit.mutex.RLock()

defer circuit.mutex.RUnlock()

now := time.Now().UnixNano()

openedOrLastTestedTime := atomic.LoadInt64(&circuit.openedOrLastTestedTime)

if circuit.open && now > openedOrLastTestedTime+getSettings(circuit.Name).SleepWindow.Nanoseconds() {

/

swapped := atomic.CompareAndSwapInt64(&circuit.openedOrLastTestedTime, openedOrLastTestedTime, now) //这一句才是关键

if swapped {

log.Printf("hystrix-go: allowing single test to possibly close circuit %v", circuit.Name)

}

return swapped }

return false}

这段代码首先判断了熔断器是否开启,并且当前时间大于 上一次开启熔断器的时间+ SleepWindow 的时间,如果条件都符合的话,更新此熔断器最新的 openedOrLastTestedTime ,是通过 CompareAndSwapInt64 原子操作完成的,意外着必然只会有一个成功。

此时熔断器还是半开的状态,接着如果能拿到令牌,执行run 函数(也就是Do传入的第二个简单封装后的函数),发起 http 请求,如果成功,上报成功状态,关闭熔断器。如果失败,那么熔断器依旧开启。

以上就是大体的流程讲解,下一篇文章将解读核心源码以及进一步当思考。

更多相关技术文章,请访问go语言教程栏目!

Hystrix php,详解 hystrix-go 使用与原理相关推荐

  1. 详解变频器、逆变器工作原理

    我现在知道直流怎么变为交流,通过PWM波,我感觉无人机的电调就是个逆变器,就是把直流变为交流,莫非就是飞控输出PWM,电调就是专为交流电?不讲道理是PWM遇到电机线圈就自动变为交流电了么. 摘自:ht ...

  2. 详解非局部均值滤波原理以及用MATLAB源码实现

    详解非局部均值滤波原理以及用MATLAB源码实现 序言 均值滤波.中值滤波.高斯滤波在滤除噪声的过程中,无可避免的使图像的边缘细节和纹理信息所被滤除.针对此问题,Buades[1]等人提出了非局部均值 ...

  3. 详解JSP 中Spring工作原理及其作用

    详解JSP 中Spring工作原理及其作用 1.springmvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作. 2.Dispat ...

  4. 计算机网络知识详解之:TCP连接原理详解

    网络知识详解之:TCP连接原理详解 计算机网络相关知识体系详解 网络知识详解之:TCP连接原理详解 网络知识详解之:HTTP协议基础 网络知识详解之:HTTPS通信原理剖析(对称.非对称加密.数字签名 ...

  5. 详解音频编解码的原理、演进和应用选型等

    本文来自网易云音乐音视频实验室负责人刘华平在LiveVideoStackCon 2017大会上的分享,并由LiveVideoStack根据演讲内容整理而成(本次演讲PPT文稿,请从文末附件下载). 1 ...

  6. 深入浅出多线程编程实战(五)ThreadLocal详解(介绍、使用、原理、应用场景)

    深入浅出多线程编程实战(五)ThreadLocal详解(介绍.使用.原理.应用场景) 文章目录 一.ThreadLocal简介 二.ThreadLocal与Synchronized区别 三.Threa ...

  7. java源码系列:HashMap底层存储原理详解——4、技术本质-原理过程-算法-取模具体解决什么问题

    目录 简介 取模具体解决什么问题? 通过数组特性,推导ascii码计算出来的下标值,创建数组非常占用空间 取模,可保证下标,在HashMap默认创建下标之内 简介 上一篇文章,我们讲到 哈希算法.哈希 ...

  8. 即时通讯音视频开发(十八):详解音频编解码的原理、演进和应用选型

    1.引言 大家好,我是刘华平,从毕业到现在我一直在从事音视频领域相关工作,也有一些自己的创业项目,曾为早期Google Android SDK多媒体架构的构建作出贡献. 就音频而言,无论是算法多样性, ...

  9. 网络知识详解之:HTTPS通信原理剖析(对称、非对称加密、数字签名、数字证书)

    网络知识详解之:HTTPS通信原理剖析(对称.非对称加密.数字签名.数字证书) 计算机网络相关知识体系详解 网络知识详解之:TCP连接原理详解 网络知识详解之:HTTP协议基础 网络知识详解之:HTT ...

  10. SpringCloudSpringBootmybatis分布式微服务云架构-hystrix参数详解

    简介 上节我们讨论了hystrix+feign+ribbon,但是可能很多人都知道hystrix还有线程隔离,信号量隔离,等等各种参数配置,在这几就记录下hystrix的参数, 一.hystrix参数 ...

最新文章

  1. Linux(Centos)下jdbc连接oracle速度超慢的问题
  2. dubbo服务使用spring-data-mongodb进行时间查询的bug记录
  3. 在Visual Studio中调试samples中可能出现的错误
  4. 示例介绍:JavaFX 8打印
  5. java 线程池 wait,Java 多线程 之 wait等待 线程实例
  6. centos 环境变量配置
  7. Ubuntu 实现点击菜单栏图标最小化程序
  8. 十进制转二进制 / 八进制 / 十六进制的手算方法,及其数学原理的通俗解释
  9. larveral 直接拷贝安装_2020年mac系统下制作win10引导安装盘,亲测可用
  10. VMware Cloud Director 10.3.1 - 云计算调配和管理平台
  11. tomcat下面的starup.bat的作用
  12. i350在linux系统刷MAC,MAC 10.14 安装教程10-基于黑果小兵大神EFI文件的修改过程
  13. 基于uniapp开发的一款Android、iOS上使用的小说阅读app
  14. 计算机运行速度靠什么,怎么让电脑运行速度变快?一招搞定
  15. NoteExpress免费版只7个引文样式#NoteExpress免费版新增引文样式
  16. IOS开发之制作静态库
  17. 飞浆AI studio人工智能课程学习(2)-Prompt优化思路|十个技巧高效优化Prompt|迭代法|Trick法|通用法|工具辅助
  18. 会计做什么副业好?分享几个适合会计的副业
  19. 赛事解读|中国工程机器人大赛暨国际公开赛——飞思实验室空中机器人项目-仿真与自主任务赛项
  20. opengl绘制金字塔

热门文章

  1. 48本实体书包邮免费送!
  2. 微软捕获中国黑客刘蝶雨的故事
  3. 3DM:phase wrapping
  4. Javascript深入浅出之this
  5. Cannot serialize; nested exception is org.springframework.core.serializer
  6. 抓包精灵app使用教程
  7. 分享三个前端学习方法和十项前端面试笔记:为想去的公司努力一把
  8. 上位机程序,上位机界面开发,ATECLOUD中国人自己的LabVIEW
  9. 《信息物理融合系统(CPS)设计、建模与仿真——基于 Ptolemy II 平台》——1.4 角色模型...
  10. hello.s:15: 错误: junk at end of line, first unrecognized character valued 0x8 的解决方法