偶现外部接口调用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%问题多和网络有关,特别是现在分布式微服务。网络问题会导致主从节点频繁切换,还会导致出现服务孤岛,还会出现因分布式事务导致数据不一致,也有可能出现想本文一样因为时延而产生的幂等性问题。

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

相关推荐
摸鱼仙人~1 小时前
Flask-SocketIO 连接超时问题排查与解决(WSL / 虚拟机场景)
后端·python·flask
Lisonseekpan1 小时前
@Autowired 与 @Resource区别解析
java·开发语言·后端
chenyuhao20242 小时前
Linux系统编程:线程概念与控制
linux·服务器·开发语言·c++·后端
IT_陈寒2 小时前
Redis 性能优化实战:5个被低估的配置项让我节省了40%内存成本
前端·人工智能·后端
qq_12498707532 小时前
基于springboot的智能医院挂号系统(源码+论文+部署+安装)
java·人工智能·spring boot·后端·毕业设计
木木一直在哭泣2 小时前
ThreadLocal 讲清楚:它是什么、为什么会“内存泄漏”、线程池复用为什么会串号
后端
艺杯羹2 小时前
Thymeleaf模板引擎:让Spring Boot页面开发更简单高效
java·spring boot·后端·thymeleadf
逸风尊者3 小时前
开发可掌握的知识:推荐系统
java·后端·算法
Violet_YSWY3 小时前
阿里巴巴状态码
后端