V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
xpyusrs
V2EX  ›  Go 编程语言

怎么方便全局维护 token, , 有效期二个小时, 快过期的时候主动发请求更新

  •  
  •   xpyusrs · 2022-06-26 18:22:40 +08:00 · 4023 次点击
    这是一个创建于 881 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用什么方案能优雅的实现, 有很多份 token 需要维护, 用定时任务的话, 得设置成千上万个

    29 条回复    2022-06-30 23:50:21 +08:00
    smallthing
        1
    smallthing  
       2022-06-26 18:24:50 +08:00
    什么东西 过期的不是用 refresh token 来申请吗
    吊销的时候删掉 refresh token
    BBCCBB
        2
    BBCCBB  
       2022-06-26 18:27:22 +08:00
    发现过期的时候再去更新行不行?
    xpyusrs
        3
    xpyusrs  
    OP
       2022-06-26 18:28:05 +08:00
    @smallthing 对, 就是快过期的时候用 refresh token 去申请
    xpyusrs
        4
    xpyusrs  
    OP
       2022-06-26 18:28:54 +08:00
    @BBCCBB 这样会有很多无效请求, 想着到期了就更新好
    yangg
        5
    yangg  
       2022-06-26 18:34:51 +08:00 via iPhone
    一个定时任务,每分钟执行,更新这一分钟需要更新的
    BBCCBB
        6
    BBCCBB  
       2022-06-26 18:44:20 +08:00
    但并不是所有的 token 都会使用的吧. 你提前更新无效的请求会更多?
    xpyusrs
        7
    xpyusrs  
    OP
       2022-06-26 18:45:28 +08:00
    @BBCCBB 每个 token 都会用, 用于店铺更新订单
    cpstar
        8
    cpstar  
       2022-06-26 18:50:13 +08:00
    一种方案,独立进程 /线程,独立更新,可以并发或者顺序(主要考虑并行的一致性)
    一种方案,随需随用,过期了则隐含(implicit)更新用例

    either way
    golangLover
        9
    golangLover  
       2022-06-26 18:59:40 +08:00 via Android
    你每次都主动更新,那还用 refresh token 做什么
    AlisaDestiny
        10
    AlisaDestiny  
       2022-06-26 19:06:27 +08:00
    上面说了,时间粗化,精确到分钟,构建一个长度为 120 的循环链表(队列也行),第 i 个节点包含会在 i 分钟过期的 token 列表,每分钟从节点头拿出一个列表更新,然后头指针移动到下一个节点。
    BugCry
        11
    BugCry  
       2022-06-26 19:07:01 +08:00 via Android
    golang 用时间轮就好了
    wangningkai
        12
    wangningkai  
       2022-06-26 20:25:39 +08:00 via iPhone
    可每请求一次更新一次 token 发给客户端更新
    vfs
        13
    vfs  
       2022-06-26 20:44:02 +08:00
    如果是那种过期了也可以很容易刷新的 token , 只需要记录下 token 和对应的 token 过期时间就行。每次使用 token 之前判断一下是否过期,过期了就刷新一下就好。 轮询,按时刷新都太费了,过日子吗,就是要省:-)
    cxytz01
        14
    cxytz01  
       2022-06-26 20:53:33 +08:00
    想到两种解决方法:
    方法一:自己写数据结构 -- 大(小)根堆,优先级队列。
    a.大小根堆存储 token 的时间,每秒扫对顶元素,过期就 pop 出来,继续扫堆顶元素直到再也扫不到过期的,然后进入下一个循环。
    b.优先级队列存储 token 时间,同样每秒扫队顶元素。不过这里貌似都用不着优先级队列,用普通的队列就可以了,毕竟时间都是线性的,顺序的。

    方法二:用工业界的组件 -- 延时消息队列 -- 比如电商领域的订单系统,开单后,N 分钟内不付款,系统就关闭订单。
    haolongsun
        15
    haolongsun  
       2022-06-26 20:53:35 +08:00
    选 lazy 吧,主动轮询检查的是个不明智的选择。全局拦截响应,如果发现 token 过期再用 refresh token 来刷新 token ,再重新请求,就能做到无感刷新 token 。
    cxytz01
        16
    cxytz01  
       2022-06-26 20:56:08 +08:00
    @cxytz01 其中方法一就是定时任务,不过只需要一个定时任务,每 n 秒,或者每 n 分钟扫一次数据结构。你需要自己维护 token 的数据结构。token 应该是存在 DB table 里面的吧,应该都有一个唯一 ID 吧,且有创建时间吧。那么就把这些数据拿出来,搞成大小根堆,或者队列。
    q1angch0u
        17
    q1angch0u  
       2022-06-27 01:41:53 +08:00 via iPhone
    有没有可能中心化呢
    aaniao002
        18
    aaniao002  
       2022-06-27 03:29:56 +08:00 via Android
    数据库+http server+一堆 bash 脚本。bash 脚本运行更新 token ,根据返回 exp 算好到期时间(可提前 10min),sleep 到下个 round 再更新一次。bash 跟新 post 到 http server 然后写入数据库。使用的时候去数据库读取就好。管理能力 3 万起步,用 redis 还能更快。其他群控,docker ,监控,报错提示,管理什么的自由发挥就好。
    SteveWoo
        19
    SteveWoo  
       2022-06-27 03:58:04 +08:00
    生成的 token 就带上时间,每次要用的时候检查是否过期
    SteveWoo
        20
    SteveWoo  
       2022-06-27 04:02:55 +08:00
    哦,上面那条理解错题了。
    我之前遇到同类场景是微信小程序的 authkey 2 小时过期,需要提前更新。解决办法是:

    把生成的 token (或者 wxkey 等及其他可以标记的)放到 redis 的 score set 里,score 就是过期的时间。
    然后启动一个进程每 10 秒扫一下还有 15 分钟就过期的 key ,完成更新操作。
    BeijingBaby
        21
    BeijingBaby  
       2022-06-27 09:51:46 +08:00
    写一套通用维护 token 的工具 /框架

    使用方从这个框架 Get token 。

    框架内部维护有效期,有个 goroutine 来将快过期的 token 续期。
    CodeJr
        22
    CodeJr  
       2022-06-27 10:31:06 +08:00
    就像 steam pc 和手机 认证一样的采用同样的密钥生成算法
    joesonw
        23
    joesonw  
       2022-06-27 10:50:40 +08:00 via iPhone
    用时间轮,全局一个 ticker 就好了。
    hopingtop
        24
    hopingtop  
       2022-06-27 11:04:22 +08:00
    更新这个操作,分摊到客户端, 去检测你下发 token 的过期 时间戳。他检测到 快 过期,在主动触发 服务端。 然后你 服务端,只需要一个 代价很小的 轮询 补偿机制就行了。 不知道这样能够解决你的问题?
    xtinput
        25
    xtinput  
       2022-06-27 15:04:15 +08:00
    用之前判断有效期进行更新,或者后台返回指定错误码,然后收到错误码之后更新再尝试上一个请求
    seth19960929
        26
    seth19960929  
       2022-06-27 17:47:44 +08:00
    怕无效请求就这样子:
    A token 请求 -> 没过期正常使用

    A token 请求 -> 过期了 -> 正常返回数据 -> 在 response header 增加一个 token 字段返回 B token -> 客户端所有请求拦截判断 response header 有 token 就更新到本地 做到无痛更新

    A token 过期了, 有并发请求过来, 上锁存储生成的 token 到 redis, 设置过期时间为 3s(自己决定), 3s 内的请求(包含被锁住的那些)直接返回 redis 存储的 token, 3s 后代表全是失效的请求
    dzdh
        27
    dzdh  
       2022-06-27 19:11:10 +08:00
    go 不是自带锁吗
    zhuweiyou
        28
    zhuweiyou  
       2022-06-28 07:20:50 +08:00
    来请求的时候再判断要不要更新,这种场景为什么要主动去轮.
    abctt
        29
    abctt  
       2022-06-30 23:50:21 +08:00 via iPhone
    搞这么麻烦 session 不会用了吗,舍本求末
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1076 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:50 · PVG 02:50 · LAX 10:50 · JFK 13:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.