偶现外部接口调用token失效

背景

手里接到一个项目,项目存在大量外部页面接口调用(就是嵌入页面)。在获取对方页面链接前,我们需要获取token换取ticket拼接到网关的链接上。然后网关校验ticket是否在他们服务器的缓存中存在,如果存在这通过链接上的页面表示符参数,返回响应的页面给我们。大致如下图: 看了上图,你不是觉得很完美,没有问题了,还直喷没有技术含量。

问题

然后问题来了,有部分网速比较慢的用户反馈访问带三方页面的服务页面经常出现401或者400。这里400和401是对方封装的权限异常,也就是ticket、token这些有问题。

过程

一开始没有头绪,我们坚持认为我们获取token是成功的,tikect也是成功的,传递过去的参数为什么你们会说权限无效?对!肯定是他们问题,他们有毒! 就在这样的怀疑下,安心的有过了一个星期,晚上谁的挺香。 但是运营扛不住了,隔三差五反馈用户有反馈了,你们技术行不行啊。 领导直接对我发话,这个问题你不要让开发自己去看,你作为技术经理你要参与分析。 呵呵,我分析了我就觉得是那帮吊炸天的人有问题。 领导来一句你考虑了时间差了吗?

分析

领导不亏是领导,就是牛皮plus,他这一说画了个草图,我才知道自己的见识有多浅薄。 不说了上图: 上图中的'产生ticket2,并存入ticket1'是笔误,应该是'产生ticket2,并存入ticket2'

原因

远程调用我们忽略两个因素:

复制代码
   用户多次点击,无论是用户手贱还是网络问题,这是客观存在的,我们没有考虑到;
   更没有考虑到的是多次请求的时延性,特别在调用外部系统的情况下;

解决

问题找到了,原因也分析清楚了,方案就好做了。

  1. 作为请求方,我们token请求太频繁,因此增加token缓存过期时间设置为30分钟。在每次请求进来时检查token过期时间,如果不到两分钟的时候,再次去网关获取token。

  2. 上一步只能解决不频繁去获取token的问题,关键解决这个问题是,需要在同一个用户获取网关token时需要在redis缓存中增加分布式锁,防止在第一次获取token或者在更新的时候出现之前时序问题。

  3. 前端优化,增加每一次请求后增加loading遮罩层,特别是容易出现时序问题的这些业务上,也为了防止其他类似因为网络慢而发起的多次请求。也能一定层度上降低正常用户的幂等性相关问题,特别是后端比较懒或者没有考虑幂等性问题的时候。

    解决后大致如下图:

回顾

以上问题真的就解决了吗?不一定还有个问题要考虑。 使用相同的token获取的ticket是否每次都一样,如果不一样,还会出现同样的问题。 解决方法,改为缓存ticket,并加锁?但是页面访问是一次性的,基本不会用第二次。那对获取token和获取ticket整个作为一个整体事务是否可以?我觉得可以。

总结

干了11年的IT,遇到生产上的20%问题多和网络有关,特别是现在分布式微服务。网络问题会导致主从节点频繁切换,还会导致出现服务孤岛,还会出现因分布式事务导致数据不一致,也有可能出现想本文一样因为时延而产生的幂等性问题。

如果本文有什么错误或纰漏欢迎指出一起讨论。

相关推荐
Loo国昌40 分钟前
【LangChain1.0】第八阶段:文档处理工程(LangChain篇)
人工智能·后端·算法·语言模型·架构·langchain
vx_bisheyuange44 分钟前
基于SpringBoot的海鲜市场系统
java·spring boot·后端·毕业设计
李慕婉学姐1 小时前
【开题答辩过程】以《基于Spring Boot和大数据的医院挂号系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
大数据·spring boot·后端
源代码•宸2 小时前
Leetcode—3. 无重复字符的最长子串【中等】
经验分享·后端·算法·leetcode·面试·golang·string
0和1的舞者3 小时前
基于Spring的论坛系统-前置知识
java·后端·spring·系统·开发·知识
invicinble4 小时前
对于springboot
java·spring boot·后端
码界奇点4 小时前
基于Spring Boot与Vue的校园后台管理系统设计与实现
vue.js·spring boot·后端·毕业设计·源代码管理
爱编程的小庄4 小时前
Rust 发行版本及工具介绍
开发语言·后端·rust
Apifox.6 小时前
测试用例越堆越多?用 Apifox 测试套件让自动化回归更易维护
运维·前端·后端·测试工具·单元测试·自动化·测试用例
sunnyday04266 小时前
Nginx与Spring Cloud Gateway QPS统计全攻略
java·spring boot·后端·nginx