聊聊dubbo-go的HystrixFilter
时间:2022-07-22
本文章向大家介绍聊聊dubbo-go的HystrixFilter,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
序
本文主要研究一下dubbo-go的HystrixFilter
HystrixFilter
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
// HystrixFilter ...
type HystrixFilter struct {
COrP bool //true for consumer
res map[string][]*regexp.Regexp
ifNewMap sync.Map
}
- HystrixFilter定义了COrP、res、ifNewMap属性
Invoke
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
// Invoke ...
func (hf *HystrixFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
cmdName := fmt.Sprintf("%s&method=%s", invoker.GetUrl().Key(), invocation.MethodName())
// Do the configuration if the circuit breaker is created for the first time
if _, load := hf.ifNewMap.LoadOrStore(cmdName, true); !load {
configLoadMutex.Lock()
filterConf := getConfig(invoker.GetUrl().Service(), invocation.MethodName(), hf.COrP)
for _, ptn := range filterConf.Error {
reg, err := regexp.Compile(ptn)
if err != nil {
logger.Warnf("[Hystrix Filter]Errors occurred parsing error omit regexp: %s, %v", ptn, err)
} else {
if hf.res == nil {
hf.res = make(map[string][]*regexp.Regexp)
}
hf.res[invocation.MethodName()] = append(hf.res[invocation.MethodName()], reg)
}
}
hystrix.ConfigureCommand(cmdName, hystrix.CommandConfig{
Timeout: filterConf.Timeout,
MaxConcurrentRequests: filterConf.MaxConcurrentRequests,
SleepWindow: filterConf.SleepWindow,
ErrorPercentThreshold: filterConf.ErrorPercentThreshold,
RequestVolumeThreshold: filterConf.RequestVolumeThreshold,
})
configLoadMutex.Unlock()
}
configLoadMutex.RLock()
_, _, err := hystrix.GetCircuit(cmdName)
configLoadMutex.RUnlock()
if err != nil {
logger.Errorf("[Hystrix Filter]Errors occurred getting circuit for %s , will invoke without hystrix, error is: ", cmdName, err)
return invoker.Invoke(ctx, invocation)
}
logger.Infof("[Hystrix Filter]Using hystrix filter: %s", cmdName)
var result protocol.Result
_ = hystrix.Do(cmdName, func() error {
result = invoker.Invoke(ctx, invocation)
err := result.Error()
if err != nil {
result.SetError(NewHystrixFilterError(err, false))
for _, reg := range hf.res[invocation.MethodName()] {
if reg.MatchString(err.Error()) {
logger.Debugf("[Hystrix Filter]Error in invocation but omitted in circuit breaker: %v; %s", err, cmdName)
return nil
}
}
}
return err
}, func(err error) error {
//Return error and if it is caused by hystrix logic, so that it can be handled by previous filters.
_, ok := err.(hystrix.CircuitError)
logger.Debugf("[Hystrix Filter]Hystrix health check counted, error is: %v, failed by hystrix: %v; %s", err, ok, cmdName)
result = &protocol.RPCResult{}
result.SetResult(nil)
result.SetError(NewHystrixFilterError(err, ok))
return err
})
return result
}
- Invoke方法首先通过hf.ifNewMap.LoadOrStore判断该cmdName的circuit breaker是否已经创建,还没有创建的话,会通过getConfig获取filterConf,给指定的invocation.MethodName()创建reg,之后通过hystrix.ConfigureCommand进行配置;之后通过hystrix.GetCircuit(cmdName)获取circuit,然后执行hystrix.Do,在该func里头执行invoker.Invoke(ctx, invocation)
OnResponse
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
// OnResponse ...
func (hf *HystrixFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
return result
}
- OnResponse方法目前直接返回result
GetHystrixFilterConsumer
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
// GetHystrixFilterConsumer ...
func GetHystrixFilterConsumer() filter.Filter {
//When first called, load the config in
consumerConfigOnce.Do(func() {
if err := initHystrixConfigConsumer(); err != nil {
logger.Warnf("[Hystrix Filter]Config load failed for consumer, error is: %v , will use default", err)
}
})
return &HystrixFilter{COrP: true}
}
- GetHystrixFilterConsumer创建的HystrixFilter的COrP属性为true
GetHystrixFilterProvider
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
// GetHystrixFilterProvider ...
func GetHystrixFilterProvider() filter.Filter {
providerConfigOnce.Do(func() {
if err := initHystrixConfigProvider(); err != nil {
logger.Warnf("[Hystrix Filter]Config load failed for provider, error is: %v , will use default", err)
}
})
return &HystrixFilter{COrP: false}
}
- GetHystrixFilterProvider创建的HystrixFilter的COrP属性为false
initHystrixConfigConsumer
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
func initHystrixConfigConsumer() error {
if config.GetConsumerConfig().FilterConf == nil {
return perrors.Errorf("no config for hystrix")
}
filterConfig := config.GetConsumerConfig().FilterConf.(map[interface{}]interface{})[HYSTRIX]
if filterConfig == nil {
return perrors.Errorf("no config for hystrix")
}
hystrixConfByte, err := yaml.Marshal(filterConfig)
if err != nil {
return err
}
err = yaml.Unmarshal(hystrixConfByte, confConsumer)
if err != nil {
return err
}
return nil
}
- initHystrixConfigConsumer会根据config.GetConsumerConfig().FilterConf的filterConfig来创建confConsumer
initHystrixConfigProvider
dubbo-go-v1.4.2/filter/filter_impl/hystrix_filter.go
func initHystrixConfigProvider() error {
if config.GetProviderConfig().FilterConf == nil {
return perrors.Errorf("no config for hystrix")
}
filterConfig := config.GetConsumerConfig().FilterConf.(map[interface{}]interface{})[HYSTRIX]
if filterConfig == nil {
return perrors.Errorf("no config for hystrix")
}
hystrixConfByte, err := yaml.Marshal(filterConfig)
if err != nil {
return err
}
err = yaml.Unmarshal(hystrixConfByte, confProvider)
if err != nil {
return err
}
return nil
}
- initHystrixConfigProvider方法根据filterConfig来创建confProvider
小结
HystrixFilter的Invoke方法首先通过hf.ifNewMap.LoadOrStore判断该cmdName的circuit breaker是否已经创建,还没有创建的话,会通过getConfig获取filterConf,给指定的invocation.MethodName()创建reg,之后通过hystrix.ConfigureCommand进行配置;之后通过hystrix.GetCircuit(cmdName)获取circuit,然后执行hystrix.Do,在该func里头执行invoker.Invoke(ctx, invocation)
doc
- hystrix_filter
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python干货 | 遥感影像拼接
- SAP Spartacus 自定义指令的实现以及通过@HostBinding实现属性绑定
- Python气象绘图教程—(十九)剖面图
- Angular DefaultDomRenderer2.setProperty
- 在pandas中利用hdf5高效存储数据
- AMS机器学习课程:Keras深度学习 - 卷积神经网络
- python教程 | 最标准的地图调用方式(国家测绘局提供数据)
- 「万物生长」一个APK从诞生到活跃在Android手机上
- webpack实战——生产环境配置【下】
- R语言作图——Violin plot with dot
- AkShare-中国宏观-全社会用电分类情况表
- Angular应用从Component到Html的数据绑定是如何实现的
- 3分钟短文:Laravel Form,让你不再写 HTML 的好“库”
- Angular应用input和div标签页的动态创建场景
- 在Angular的index.html里插入script,拦截所有动态创建标签页的场景