建设银行宁夏分行网站,机械制造网站,合肥金融网站开发,响应式网站模板百度云一、业务特点
很多第三方服务#xff0c;都使用访问令牌来做访问验证#xff0c;比如某度、某信的access token#xff0c;主要特征如下#xff1a;
1、令牌由第三方系统发放#xff0c;用于访问第三方特定资源#xff1b;
2、令牌存在有效期限#xff0c;过期自动失…一、业务特点
很多第三方服务都使用访问令牌来做访问验证比如某度、某信的access token主要特征如下
1、令牌由第三方系统发放用于访问第三方特定资源
2、令牌存在有效期限过期自动失效
3、同时只存在一个有效令牌重新获取后之前获取到的令牌将会过期这一点不是每个平台都严格限制我们假设严格限制。
二、整体设计
系统主要逻辑主要设计目标为尽可能让用户一次以尽可能快的速度获得令牌同时也提供前端做自动刷新策略的依据具体设计如下
1、分布式缓存暂不考虑本地缓存场景有兴趣可以讨论最新令牌缓存有效期低于令牌有效期
2、先从缓存中获取缓存中不存在、已过期或要求强制刷新则重新获取令牌。如果需要强制刷新前手动删除缓存
3、获取令牌前先添加分布式锁保障只有一个线程在获取令牌
4、假设未抢到分布式锁则限时等待同时监听广播等待唤醒超时则尝试再次从缓存中获取如果获取不到则返回再次获取标识
5、抢到分布式锁的线程获取到令牌后加入缓存并广播令牌事件唤醒等待中线程
6、前端根据返回状态若返回再次获取标识或已获得令牌但使用时返回失效时则尝试重试再次获取
7、当业务量大需要本地缓存令牌时先尝试从本地获取刷新时需要双删本地令牌并广播删除令牌事件通知其他服务删除过期本地令牌。
三、代码实现以Java为例基于分布式缓存半伪代码
1、主程序设计
// 定义在最前
private static final CountDownLatch latch new CountDownLatch(1);// 以下真正主程序开始
// 强制刷新删除缓存否则尝试先从缓存获取if (isForceRefresh) {delete(CacheKey);} else {accToken getFromCache();}// 未从缓存中获取到或强制刷新时尝试获取最新tokenif (StringUtils.isBlank(accToken)) {Lock lock getLock(LockKey);try {// 尝试获取分布式锁未获取到锁时快速失败获取到锁时锁n秒一般考虑访问到锁需要的时间boolean b lock.tryLock(-1, n, TimeUnit.SECONDS);if (b) {// 从远程获取最新访问令牌accToken newToken();}else {// 未抢到锁尝试等待其他线程获取到后直接获取这里等待两次accToken waitGet(1);}} catch (InterruptedException e) {// just ignore} finally {if (lock.isHeldByCurrentThread()) {if (lock.isLocked()) {lock.unlock();}// 如果当前线程抢到锁则无论是否成功都广播事件唤醒其他等待中线程broadcastWakeupEvent(EvantKey);}} // end: finally} // end: if (StringUtils.isBlank(accToken))return 新令牌
2、waitGet 等待设计
String accToken null;try {// 使用latch等待n毫秒后重新尝试从缓存获取boolean isWakeup latch.await(n, TimeUnit.MILLISECONDS);accToken getFromCache();// 未获取到不是被事件唤醒的且等待次数非0则尝试再次等待if (!isWakeup StringUtils.isBlank(accToken) count 0) {accToken waitGet(--count);}if (StringUtils.isBlank(accToken)) {// 未获取到返回前端重试标识return retrySign();}} catch (InterruptedException e) {// 异常打断返回前端重试标识return retrySign();}return accToken;
3、监听获取到token事件唤醒等待线程
latch.countDown();
本作品的版权所有权归作者所有受法律保护。未经作者书面许可任何个人或组织均不得以任何形式使用、复制、修改、传播、展示或在未获得授权的情况下进行商业利用。