Redigo:|Redigo: Envoy代理Redis场景下的错误提示
Redigo issue 579
reply.go sliceHelper does not handle Redis errors within the slice#579
一、问题是什么
在使用了 Envoy 代理 Redis 的场景下,执行MGET
获取数据,其中某台 Redis 服务出现了问题,Envoy返回了如下的错误提示upstream failure
【Redigo:|Redigo: Envoy代理Redis场景下的错误提示】而经过 redigo 返回来的却是
redigo: unexpected element type for ByteSlices, got type redis.Error
显然封装的有问题,导致错误提示不够直接。
二、怎么解决的 详见 pr 580
2.1 ByteSlices 与 MGET 我们看 issue 579 的示例代码,发生问题的调用就在这里:
values, err := redis.ByteSlices(conn.Do("MGET", params...))
那么问题根源出在哪里呢?
这就需要看下
redis.ByteSlices()
都做了什么。我直接总结一下:遍历MGET返回的所有数据,进行类型断言,如果断言失败,返回错误信息。
那么问题就在于如下两点:
- 当 Envoy 代理 Redis 后,在 redis 没有响应或者其它情况下,Envoy 返回自定义的错误信息。(Envoy文档-upstream failure错误)
- Redigo 粗暴的判断,对返回的值进行类型断言
v.([]byte)
, 切片断言失败,返回了自定义的错误提示,且错误提示中,没有带着 Envoy 返回的内容。
if v.([]byte)
类型断言出是否为字节切片改造为
switch v := v.(type)
、 case []byte:
、 case Error:
不再判断单一的字节切片类型,而是断言出是哪种类型。
那
Error
是什么类型呢,其实就是 String
,这种特性,我们管它叫做“类型定义” type Error string
再有 Envoy 代理 Redis 返回错误信息 场景下返回的数据,类型断言就会进入到
case Error
三、复现这个问题 安装 Envoy,代理 Redis,kill掉Redis,就可复现出“no upstream host”(虽不是upstream failure,但同样是String)。
四、扩展 4.1 文中提到的 Envoy 是什么? Service Mesh 架构的实现框架
参考
容器设计模式-sidcar
4.2 Envoy 和 Redis 怎么结合的? 在 Service Mesh 架构下,Envoy 对 多 Redis 集群进行代理。
参考
Envoy Redis 源码分析
4.3 Go 4.3.1 类型别名、与类型定义
文中说到的 Error 其实 就是 String,即类型定义,需要注意的是不要和类型别名的概念混淆。
// 将NewInt定义为int类型
type NewInt int// 将int取一个别名叫IntAlias
type IntAlias = int
参考
Go语言type关键字(类型别名)
了解 Go 1.9 的类型别名
4.3.2 回调函数
redis.ByteSlices() 以及其它fun中都运用了回调函数
参考
cyent.github.io
文章图片
推荐阅读
- AOP详解之三-创建AOP代理后记,创建AOP代理
- iOS开发,代理实现方法
- Nginx|一篇就学会Nginx做代理缓存服务器
- AOP源码解析之二-创建AOP代理前传,获取AOP信息
- 解决SpringAop内部调用时不经过代理类的问题
- 事件代理——减少事件监听函数
- 使用vscode|使用vscode Container开发调试envoy
- Nginx反向代理与负载均衡概念理解及模块使用
- TASKCTL调度服务节点与(主/从代理节点)的启动和停止
- 面试常问的设计模式之代理模式的详细解析!分析说明静态代理模式和动态代理模式