当前位置: 首页 > 后端技术 > Java

网上一个奇怪的问题让我排查了一天

时间:2023-04-02 10:34:54 Java

昨天网上又出了一个问题,找了一天找原因。理由其实很坑爹。事情是这样的,最近我们上线了一个刷新用户令牌的功能,在APP中经常可以看到。只要您经常操作,就可以让您一直在线,无需重新登录。需求就是这么简单。需求也即将推出。但是上线后发现有用户15天一定时间没有调用接口刷新token,一直停留在登录状态(默认token过期7天),非常奇怪的。由于我不是主要开发者,所以我负责协助调查原因。根据开发的口述,我得到的信息如下:根据数据库日志,该用户在八月份只登录了两次,两次之间的时间间隔长达15天。另外排除了日志丢失的问题,同步保存了日志。并且在一次交易中,没有损失的可能性。根据ELK网关日志,用户在这15天内基本每天都使用该APP,仍然需要登录界面。根据ELK用户服务日志,用户在此期间没有刷新token,本应在7天后过期,却持续了15天。以上情况我基本都见过,也都一一验证过了。确实如此。那么,我们调查的方向就确定了。是否有任何其他错误导致用户的令牌被更新?按说如果是这样的话,那么这个问题应该早就存在了。等到这个需求上线是不可能的,也从来没有看到过这个问题的反馈。于是,我筛选了一些用户的日志,发现登录其实还是挺有规律的。在大多数情况下,将在<=7天内登录一次。如果日志超过7天,发现没有接口调用。这可能意味着这个问题以前从未发生过。是这次上线造成的BUG吗?于是查阅了QA相关的测试情况和开发提供的最新在线调用的log和情况,都没有问题。于是,我特意把代码翻了一遍,担心有什么BUG导致token被更新,但是检查了一下,有没有发现什么问题。至此,调查似乎陷入僵局,只能从其他方面寻找思路。我询问了整个业务的呼叫链接。简单的说就是用户在登录的时候请求token,然后保存起来。以后每次请求都会带上token,然后由认证服务来验证token的合法性。性别。所以,不禁想问,是不是认证服务有问题???于是又把认证服务的代码翻了一遍,发现代码很垃圾,到处都写了token存储,调用的地方有10多个。通过CAT查看这些接口后,发现大部分接口近一个月都没有被调用过。我也随着开发确认,这些接口基本都是老接口,没什么用。存在调用的地方只有一个,就是我们现在使用的鉴权。这个地方简单来说就是判断token在redis中是否存在。也在本地和测试环境中验证,没有发现问题。OK,至此,时间到了下午,包括我在内的几个调查员都快炸了。这个问题找了快一天了,也没有发现问题,整个事情就此陷入停顿。我默默点了根烟,别告诉我,小苏抽烟的本事真高(友情提示,抽烟有害健康)。不禁想到之前领导说他以前不抽烟,然后团里的其他人每次找不到问题的原因就跑出去抽。但是他们回来后说他们发现了问题,所以我也只好抽烟了。..那么怎么说呢,吸烟可以给人带来思想。不禁想到一个问题,他们说的就是他们说的,虽然我看了他们给我的demo,但是除了看到用户的登录日志,还有他们给我看的网关日志和服务调用日志此外,我实际上并没有亲自去验证他们的说法。于是,我首先从数据库中查看了登录日志,发现这确实是没有问题的。代码已经过验证,确实在登录交易中。虽然代码很垃圾,框架了整个登录逻辑,但是这个交易这个时候少不了他。有什么额外保证这个日志的存在是必要的!然后查看网关日志,发现没有问题。用户的认证接口基本一直调用,不过7天后就通过了,也没有提示token失效。所以我继续查看服务本身的调用日志。之前他们给我看的时候,就是这个结果。根据日志信息和用户ID,没有找到日志,排除用户调用了refreshtoken接口的情况。感觉这里不对劲,所以我把搜索方式改为搜索用户的设备信息,而不是用户ID!!!结果,尼玛出现了!!!查到结果,用户中间调用了一次refreshtoken,查看时间,8月8日第一次登录,8月23日再次登录,15日刷新一次,时间刚好吻合,7天!至此,真相基本大白。这并不是说有任何错误。只是我相信了他们的调查结果,没有求证!我在错误的调查道路上越走越远!真是尼玛炸裂!OK,到这里我不禁想到,为什么我用用户ID查不到任何结果呢?当我把结果告诉开发者时,他也惊呆了。他说我可以通过搜索其他用户ID找到它,然后他给我演示了。我测试了一下,发现确实可以。我进一步测试了几个用户ID,发现有的可以搜索到,有的不能搜索到。这有点奇怪。我仔细查看了我们的token,发现token.123.456bdf(中间那个是用户ID)这样搜是搜不到的,但是token.456.bde123这样搜是可以找到的。这应该是一个分词问题。连在一起的数字看成是一串分词,所以有的可以查,有的查不到。经过测试,发现确实是这样。我们可以自己测试ELK的分词效果,进入首页,然后选择ESAPI交互。验证我们的猜测是否是分词造成的。默认应该是标准分词。Analyzer选择standard,可以看到输出结果确实OK。换一个字符串,在tokentest前加一个数字,分词结果果然和我们猜的一样。有两种解决方法。第一个只能由分词器代替。比如我们使用一个patternregulartokenizer,我们可以达到我们想要的效果,但是我们不关心分词。第二种方法其实可以改成搜索的方式,比如message:"*token*"和message:*123456*,也可以搜索到,不过大家平时是怎么这么用的,对吧?综上所述,在排查问题的过程中,一定要自己动手,不要轻易相信别人说的话,要大胆假设,认真求证,才能得到好的结果。