今天看到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
// in its own goroutine. It returns a Timer that can
// be used to cancel the call using its Stop method.
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
when: when(d),
f: goFunc,
arg: f,
},
}
startTimer(&t.r)
return t
}

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

    // Interface to timers implemented in package runtime.
// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
type runtimeTimer struct {
i int
when int64
period int64
f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{}
seq uintptr
} // when is a helper function for setting the 'when' field of a runtimeTimer.
// It returns what the time will be, in nanoseconds, Duration d in the future.
// If d is negative, it is ignored. If the returned value would be less than
// zero because of an overflow, MaxInt64 is returned.
func when(d Duration) int64 {
if d <= {
return runtimeNano()
}
t := runtimeNano() + int64(d)
if t < {
t = << - // math.MaxInt64
}
return t
} 40 func startTimer(*runtimeTimer)
41 func stopTimer(*runtimeTimer) bool

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

golang 中的定时器(timer),更巧妙的处理timeout的更多相关文章

  1. python中实现定时器Timer

    实现定时器最简单的办法是就是循环中间嵌time.sleep(seconds), 这里我就不赘述了 # encoding: UTF-8 import threading #Timer(定时器)是Thre ...

  2. Python--day41--threading中的定时器Timer

    定时器Timer:定时开启线程 代码示例: #定时开启线程 import time from threading import Timer def func(): print('时间同步') #1-3 ...

  3. [ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!

    作为入门者来说.了解JavaScript中timer的工作方式是非常重要的.通常它们的表现行为并非那么地直观,而这是由于它们都处在一个单一线程中.让我们先来看一看三个用来创建以及操作timer的函数. ...

  4. golang中的定时器

    1.  timer 定时器,时间到了执行,只执行一次 package main import ( "fmt" "time" ) func main() { // ...

  5. Java中的定时器Timer

    java.util.Timer是一个实用工具类,该类用来调度一个线程,使线程可以在将来某一时刻开始执行. Java的Timer类可以调度一个线程运行一次,或定期运行. java.util.TimerT ...

  6. 线程中的定时器Timer类

    Timer 定时器 几分钟之后执行一个任务. 创建了一个定时器相当于开启了一条线程,TimerTask相当于一个线程的任务.内部使用wait/notify机制来实现的. 用法非常的简单  就足以里面的 ...

  7. Swoole 中毫秒定时器(Timer)的使用

    间隔定时器, tick 定时器会持续触发,直到调用 clear() 清除为止. $timer = Swoole\Timer::tick(3000, function (int $timer_id, $ ...

  8. 解决windows 服务中定时器timer 定时偶尔失效 问题

    最近做个windows 服务,功能是:定时执行一个任务:自动登录到一个网站后,点击相关网面上的按钮button. 在处理的过程中发现定时器老是不定时的失效,失效时间没有规律. 由于刚开始处于测试阶段, ...

  9. Java中定时器Timer致命缺点(附学习方法)

    简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...

随机推荐

  1. dp之多重背包poj1276

    题意:有现今cash,和n种钱币,每种钱币有ni个,价值为di,求各种钱币组成的不超过cash的最大钱数....... 思路:二进制拆分转化为01背包,或者转化为完全背包都是可以的. 反思:这个题目我 ...

  2. springJDBC实现查询

    其实在Spring这个框架中,提供了一些对JDBC访问数据库的封装,其中JdbcTemplate就是一个很好用的类,下面来 演示一下这个类的一些用法.首先需要导入commons-logging.jar ...

  3. Setup Factory 读取安装包的配置文件

    result = INIFile.GetValue(SessionVar.Expand("%SourceFolder%\\set.ini"), "set", & ...

  4. Flume Channel Selectors + kafka

    http://flume.apache.org/FlumeUserGuide.html#custom-channel-selector 官方文档上channel selectors 有两种类型: Re ...

  5. 实现itoa()

    上代码之前先讲个笑话:曾经有位面试官问:“你实现过 唉踢哦诶(音) 吗”? 我第一个想到的是各种OA系统,心想那玩意不多是Java实现的吗...过一会想明白了,瞬间石化... #include < ...

  6. haproxy+keepalived实现高可用负载均衡(转)

      软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现.LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载. ...

  7. [system]c/c++调用cat命令

    因为cat并不是一个带返回的命令,而是输出到标准输出.所以使用system("cat /sys/class/gpio/...."); 得不到我们想要的结果. 下面的/bin/ls同 ...

  8. svn提示out of date

    你需要先update一下,应该会有一个冲突标志,你查看一下历史日志,找到是谁在你之前进行了提交,和他商议一下如何合并你们两个人的修改,然后在你本地处理后,标记“冲突已解决”,最后再次commit

  9. plsql programming 01 plsql概述

    授权 从 oracle 8i 开始, oracle 用通过提供 authid 子句为 pl/sql 的执行授权模型, 这样我们可以选择使用 authid current_user(调用者权限)来执行这 ...

  10. EasyUI Tree checkbox node

    tree插件允许你创建checkbox tree,如果你点击节点的checkbox,被点击的节点信息得到下和上的继承.例如,点击tomato节点的checkbox,你可以看到vegetables节点现 ...