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

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

相关推荐
计算机学姐24 分钟前
基于Python的高校成绩分析管理系统
开发语言·vue.js·后端·python·mysql·pycharm·django
wclass-zhengge1 小时前
SpringCloud篇(服务拆分 / 远程调用 - 入门案例)
后端·spring·spring cloud
A_cot1 小时前
一篇Spring Boot 笔记
java·spring boot·笔记·后端·mysql·spring·maven
tryCbest2 小时前
java8之Stream流
java·后端
白总Server2 小时前
JVM 处理多线程并发执行
jvm·后端·spring cloud·微服务·ribbon·架构·数据库架构
@sinner2 小时前
【Spring Boot 入门五】Spring Boot中的测试 - 确保应用质量
spring boot·后端·log4j
江梦寻3 小时前
解决SLF4J: Class path contains multiple SLF4J bindings问题
java·开发语言·spring boot·后端·spring·intellij-idea·idea
LightOfNight3 小时前
Redis设计与实现第9章 -- 数据库 总结(键空间 过期策略 过期键的影响)
数据库·redis·后端·缓存·中间件·架构
每天写点bug3 小时前
golang 常用的占位符 %w, %v, %s
开发语言·后端·golang
鸡鸭扣3 小时前
springboot苍穹外卖实战:五、公共字段自动填充(aop切面实现)+新增菜品功能+oss
java·spring boot·后端