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致命缺点(附学习方法)
简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...
随机推荐
- 混合模式程序集是针对“v2.0.50727”版的运行时生成的
混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集. 由于“system.data.sqlite.dll”不完整造成的. 在 ...
- C++ 类的继承一(访问控制)
//类的继承 #include<iostream> using namespace std; /* 面向对象中的继承类之间的父子关系 1.子类拥有父类所有的成员属性和成员函数(包括私有成员 ...
- 002servlet生命周期以及有关servlet的各种知识
4 Sevlet的生命周期(重点) 有关servlet的类有Servlet,HttpServlet以及GenericServlet. 其实我们要写一个Servlet只要写一个类去实现Servet就可以 ...
- Bufferread有readline()使得字符输入更加方便
原则:保证编解码方式的统一,才能不至于出现错误. Io包的InputStreamread称为从字节流到字符流的桥转换类.这个类可以设定字符转换方式. OutputStreamred:字符到字节 Buf ...
- 10个网页设计师必备的CSS技巧(转)
英文原文:10 Essential CSS Rules for Web Designers CSS是网页设计师的基础,对CSS的了解能使他们能够设计出更加美观别致的网页.使用CSS技巧来巧妙地处理CS ...
- php和js实现文件拖拽上传
Dropzone.js实现文件拖拽上传 http://www.sucaihuo.com/php/1399.html demo http://www.sucaihuo.com/jquery/13/139 ...
- PPT如何一页多张打印且铺满整个页面
最近由于工作需要,有些ppt材料想打印出来学习,但是ppt页数较多,ppt单页打印有些浪费纸张,而且也不能拿到外面打印店去打印,所以只能自己动手设置一页多张打印,并且最后双面打印,这样就做够节省纸张了 ...
- zoj 1081:Points Within(计算几何,判断点是否在多边形内,经典题)
Points Within Time Limit: 2 Seconds Memory Limit: 65536 KB Statement of the Problem Several dra ...
- 一次清除SQL SERVER错误日志的体会!
之前在UAT环境搭建的SQL SERVER 2008 R2数据库一直用得比较正常,但最近发现在Sharepoint中不能进行任何操作了,开始以为是什么配置出了问题(因为一直在研究一些新的应用和集成,需 ...
- iOS 8出色的跨应用通信效果:解读Action扩展
本文转载至 http://mobile.51cto.com/iphone-464809.htm 用程序扩展最初于WWDC 2014大会上正式亮相,这是一种将iOS应用程序功能扩展至系统其它组成部分的途 ...