分享
  1. 首页
  2. 文章

golang 中的定时器(timer),更巧妙的处理timeout

zhangqingping · · 8114 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

今天看到kite项目中的一段代码,发现挺有意思的。

// generateToken returns a JWT token string. Please see the URL for details:
// http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-13#section-4.1
func generateToken(aud, username, issuer, privateKey string) (string, error) {
 tokenCacheMu.Lock()
 defer tokenCacheMu.Unlock()
 uniqKey := aud + username + issuer // neglect privateKey, its always the same
 signed, ok := tokenCache[uniqKey]
 if ok {
 return signed, nil
 }
 tknID, err := uuid.NewV4()
 if err != nil {
 return "", errors.New("Server error: Cannot generate a token")
 }
 // Identifies the expiration time after which the JWT MUST NOT be accepted
 // for processing.
 ttl := TokenTTL
 // Implementers MAY provide for some small leeway, usually no more than
 // a few minutes, to account for clock skew.
 leeway := TokenLeeway
 tkn := jwt.New(jwt.GetSigningMethod("RS256"))
 tkn.Claims["iss"] = issuer // Issuer
 tkn.Claims["sub"] = username // Subject
 tkn.Claims["aud"] = aud // Audience
 tkn.Claims["exp"] = time.Now().UTC().Add(ttl).Add(leeway).Unix() // Expiration Time
 tkn.Claims["nbf"] = time.Now().UTC().Add(-leeway).Unix() // Not Before
 tkn.Claims["iat"] = time.Now().UTC().Unix() // Issued At
 tkn.Claims["jti"] = tknID.String() // JWT ID

 signed, err = tkn.SignedString([]byte(privateKey))
 if err != nil {
 return "", errors.New("Server error: Cannot generate a token")
 }
 // cache our token
 tokenCache[uniqKey] = signed
 // cache invalidation, because we cache the token in tokenCache we need to
 // invalidate it expiration time. This was handled usually within JWT, but
 // now we have to do it manually for our own cache.
 time.AfterFunc(TokenTTL-TokenLeeway, func() {
 tokenCacheMu.Lock()
 defer tokenCacheMu.Unlock()
 delete(tokenCache, uniqKey)
 })
 return signed, nil
}

这里的 time.AfterFunc 来做token的timeout处理,是我之前都不知道的。

我之前的做法,自己启动一个 单独的 goroutine,对所有的token做遍历,判断是否timeout,timout了就进行删除操作。

看到了这段代码,第一个感觉是很妙,第二个是如果用起来,会不会有啥副作用。

翻看源码:https://golang.org/src/time/sleep.go?h=AfterFunc#L116

// AfterFunc waits for the duration to elapse and then calls f
 114 // in its own goroutine. It returns a Timer that can
 115 // be used to cancel the call using its Stop method.
 116 func AfterFunc(d Duration, f func()) *Timer {
 117 t := &Timer{
 118 r: runtimeTimer{
 119 when: when(d),
 120 f: goFunc,
 121 arg: f,
 122 },
 123 }
 124 startTimer(&t.r)
 125 return t
 126 }

这里的startTimer 是用了系统自身的timer实现,只不过是golang在这里做了一层兼容各个平台的封装,应该是没有什么副作用啦。

14 // Interface to timers implemented in package runtime.
 15 // Must be in sync with ../runtime/runtime.h:/^struct.Timer$
 16 type runtimeTimer struct {
 17 i int
 18 when int64
 19 period int64
 20 f func(interface{}, uintptr) // NOTE: must not be closure
 21 arg interface{}
 22 seq uintptr
 23 }
 24 
 25 // when is a helper function for setting the 'when' field of a runtimeTimer.
 26 // It returns what the time will be, in nanoseconds, Duration d in the future.
 27 // If d is negative, it is ignored. If the returned value would be less than
 28 // zero because of an overflow, MaxInt64 is returned.
 29 func when(d Duration) int64 {
 30 if d <= 0 {
 31 return runtimeNano()
 32 }
 33 t := runtimeNano() + int64(d)
 34 if t < 0 {
 35 t = 1<<63 - 1 // math.MaxInt64
 36 }
 37 return t
 38 }
 39 
 40 func startTimer(*runtimeTimer)
 41 func stopTimer(*runtimeTimer) bool

不得不感慨,原生库还是有很多好东东的,需要自己慢慢发觉。


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:zhangqingping

查看原文:golang 中的定时器(timer),更巧妙的处理timeout

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
8114 次点击 ∙ 1 赞
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏