Wireshark网络分析之追踪Redisearch-go官方Bug
问题描述
我所在公司某业务需要redis-json
存储数据,然后通过redis-search
对存储的json
数据进行索引,利用索引进行快速的增删改查。
redis-json
/redis-search
都是redis
官方提供的“武器库”。
如果读者对redis-json
感兴趣,可参照官方或者本人拙作:小谈Redis JSON 系列一
那么说回来我们在使用时遇到的问题,对于redis-search
的使用,我们的client
采用了官方包github redisearch-go。
在我们实验时,对某字段值分别进行闭区间和开区间查找时,发现了致命的错误。
// 我想要对uid字段查找区间(1,49],结果遇到了问题
query := redisearch.NewQuery("*").AddFilter(
redisearch.Filter{
Field: "uid",
Options: redisearch.NumericFilterOptions{
Min: 1,
ExclusiveMin: true,
Max: 49,
ExclusiveMax: false,
},
},
)
运行之后,报错如下
total: 0, err:Unknown argument 49 at position 5 for
这是为什么呢?
(通过对该问题的解决,也达成了我人生的第一个PR
)
问题分析
实际上,当时遇到这个报错,我毫无思绪。再次将代码粘贴在此处
// 我想要对uid字段查找区间(1,49],结果遇到了问题
query := redisearch.NewQuery("*").AddFilter(
redisearch.Filter{
Field: "uid",
Options: redisearch.NumericFilterOptions{
Min: 1,
ExclusiveMin: true,
Max: 49,
ExclusiveMax: false,
},
},
)
我认为对redis-search
库的使用貌似没问题,上述代码就是基本使用嘛。
怎么办,死马当活马医。
我将搜索区间确定为[1, 49]
,发现不会报错。
此时我想,难道redis-search
本身不支持开区间搜索?
那么如何验证这个猜想呢?
那就是使用原生的redis
命令,发送开区间查找请求
ft.search tags * filter uid (1 49
运行之后,发现成功的返回了结果。诶嘿,说明redis-search
是支持开区间查找(这本来也是应该提供的功能嘛)
那么难道是这个官方提供的包有问题?
如何验证包的问题。如同上一篇查询TiDB
的bug
那样,有两个方法。
Wireshark实战之追踪TiDB官方Bug
1、仔细查看代码库的实现,毕竟代码之下,全无秘密。但是缺点是需要仔细debug
,层层嵌套,不一定好理解
2、直接抓包,进行分析。看看通过官方包发送出去的请求到底是什么样子的?
我选择进行wireshark
抓包
wireshark抓包
我们抓包的目的就是查看,发送的redis
请求到底是什么样子的。
抓包的步骤很简单,我们不再进行说明。我们直接进入分析包的环节。
首先浏览下,抓到的包
看到这些包,是不是有些疑惑。Protocol
一列显示的都是TCP
协议,Redis
不应该和MySQL
一样,作为应用软件应该有应用层的协议啊。
为什么没有显示呢?
答案很简单,wireshark
作为一款抓包软件,它并不能提供所有网络协议的解析,尤其是应用层协议。
应用层协议是应用程序自己设计的通信协议,并不是互联网的底层基石。确实有一些应用层协议非常有名,比如HTTP
协议、MySQL
协议、DNS
协议、FTP
协议等等,wireshark
对这些协议理所应当的提供了支持。
我们可以向追踪TiDB
官方bug
那篇文章一样,选择Decode As
,结果里面并没有“Redis协议”
,如下图所示。
那么我们就无法分析了吗?
不,首先让我们了解一下Redis
为自己准备的应用层协议。根据官网提供的信息,我们可知
Redis clients use a protocol called RESP (REdis Serialization Protocol) to communicate with the Redis server.
看来专属于Redis
应用层的协议名为“RESP”
。并且用官网的话来说RESP
具有Human readable
的特性,换句话来说,RESP
是文本协议,是可以直接看的。
由此,我们可以在wireshark
中简单的follow
一下TCP Stream
即可。
我们可以看到,真实的信息交互
首先,的确是报错了
其次我们解析一下RESP
:将RESP
中的请求翻译成redis
命令,即为
ft.search tags * filter uid ( 1 49
嗯哼,这个和上面那个没有报错的redis
开区间搜索命令有何不同?我们将两个语句放在一起比较,立马就会发现两者的不同
ft.search tags * filter uid (1 49 // 未报错
ft.search tags * filter uid ( 1 49 // 报错
没错,真相大白:官方包“翻译”之后的redis
命令,在开区间搜索时,多加了一个空格,导致了报错。
那还等什么,赶紧提了一个PR
,也是人生中第一个有重要意义的PR
。
总结
包括上一篇关于TiDB官方bug
的文章以及本文,不论应用如何花里胡哨的变换,网络协议的分析是同样的。就像代码之下毫无秘密,网络协议包被抓取,我们可以拿着放大镜分析。因为底层TCP/IP
都是共通的,分析方法是可以复用的。随着分析次数的增加,我们能够快速找到出问题的地方。
参考
-
《Wireshark数据分析实战》
转载自:https://juejin.cn/post/7171389808110108685