golang 中的定时器(timer),更巧妙的处理timeout
今天看到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的更多相关文章
- python中实现定时器Timer
实现定时器最简单的办法是就是循环中间嵌time.sleep(seconds), 这里我就不赘述了 # encoding: UTF-8 import threading #Timer(定时器)是Thre ...
- Python--day41--threading中的定时器Timer
定时器Timer:定时开启线程 代码示例: #定时开启线程 import time from threading import Timer def func(): print('时间同步') #1-3 ...
- [ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!
作为入门者来说.了解JavaScript中timer的工作方式是非常重要的.通常它们的表现行为并非那么地直观,而这是由于它们都处在一个单一线程中.让我们先来看一看三个用来创建以及操作timer的函数. ...
- golang中的定时器
1. timer 定时器,时间到了执行,只执行一次 package main import ( "fmt" "time" ) func main() { // ...
- Java中的定时器Timer
java.util.Timer是一个实用工具类,该类用来调度一个线程,使线程可以在将来某一时刻开始执行. Java的Timer类可以调度一个线程运行一次,或定期运行. java.util.TimerT ...
- 线程中的定时器Timer类
Timer 定时器 几分钟之后执行一个任务. 创建了一个定时器相当于开启了一条线程,TimerTask相当于一个线程的任务.内部使用wait/notify机制来实现的. 用法非常的简单 就足以里面的 ...
- Swoole 中毫秒定时器(Timer)的使用
间隔定时器, tick 定时器会持续触发,直到调用 clear() 清除为止. $timer = Swoole\Timer::tick(3000, function (int $timer_id, $ ...
- 解决windows 服务中定时器timer 定时偶尔失效 问题
最近做个windows 服务,功能是:定时执行一个任务:自动登录到一个网站后,点击相关网面上的按钮button. 在处理的过程中发现定时器老是不定时的失效,失效时间没有规律. 由于刚开始处于测试阶段, ...
- Java中定时器Timer致命缺点(附学习方法)
简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...
随机推荐
- 纯css3实现的win8加载动画
今天给大家分享一款纯css3实现的win8加载动画.在这款实例中动画效果完全由css3实现.一起看下效果图: 在线预览 源码下载 实现的代码. html代码: <div class=&quo ...
- 跟着百度学习php之ThinkPHP的运行流程-2
Thinkphp为了提高编译的效率,第一次运行的时候thinkphp会把文件全部编译到temp目录下的~runtime.php文件,在第二次运行的时候会直接读取这个文件.所以我们在线下自己写代码测试的 ...
- telnet 登陆的方法
第一种方式:通过inetd启动telnetd服务 必须这样设置busybox配置 Networking Utilities ---> 去掉 [ ] Support sta ...
- git chekout分支遇到问题:need merge
解决步骤: 在master上, 1.git add . 2.git commit 3.新建分支,并且checkout到此分支,重新提交
- MFC中给控件添加变量,DoDataExchange中
DoDataExchange函数其实是一项数据动态绑定技术.比如你在写动态按钮过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的.你要添加新的变量就要用到DoDataExchan ...
- [转]这五种方法前四种方法只支持IE浏览器,最后一个方法支持当前主流的浏览器(火狐,IE,Chrome,Opera,Safari)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 编程之美 set 9 字符串移位包含问题
题目 给定字符串 s1 和 s2, 要求判定 s2能否能够被通过 s1 做循环移位得到的字符包含. s1 = AABCD, s2 = CDAA 返回 true. 给定 s1 = ABCD 和 s2 = ...
- 主线程不能执行耗时的操作,子线程不能更新Ui
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 在看方法之前看一下Android中消息机制: 引用 Message:消息 ...
- vue2.0中子组件通过v-modal改变父组件中的值
父组件代码: <template lang="pug"> div p this is father child(v-model="data") &l ...
- instance method '*****' not found (return type defaults to 'id')
博文转载至 http://blog.csdn.net/cerastes/article/details/38025801 return type defaultsnot foundiOSwarning ...