窝游网:值得大家信赖的游戏下载站!
发布时间:2021-06-30 09:26:54来源:窝游网作者:窝游网
在没有引入zipkin(或者阿里的鹰眼,百度的华佗)这种trace系统的时候,排查问题的一般思路都是按照请求链路来寻找问题源。因此如果能在请求链路中有一个唯一的标识就最好了,而在nginx/openresty做接入层的架构中,可以通过lua脚本生成一个随机traceid。
随机数的生成原理,都是先初始化一个随机数种子,由于伪随机数的特性,种子的随机性就显得格外重要,而一般种子的生成都是通过时间的倒序来选取
lua 随机数生成方法
首先我们看下通常lua的随机数生成方法
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1,6))) math.random(m,n)
通过时间字符串的逆序初始化随机种子,这里注意到有个sub函数做了截断,是因为
math.randomseed will call the underlying C function srand which takes an unsigned integer valueLua will cast the value of the seed to this format. In case of an overflow the seed will actually become a bad seed, without warning
所以需要避免出现高类型向低类型转换的溢出问题
common 方法的问题
但上面的方法有个问题,就是os.time()函数返回的是秒(10位整数), 所以在做web请求的traceid时很容易就出现重复,影响问题追踪的效率,而lua如果要以毫秒为单位的时间来初始化随机种子,需要引入socket等外部模块,对于openresty来说一般都是封装好的,不方便去做这种定制
利用openresty 与lua生成traceid
幸运的是,nginx-lua中有个函数ngx.now会返回一个浮点数(当然在lua中统一为number类型),3位小数即为毫秒位,所以问题就变得简单了
access_by_lua_block { math.randomseed(tonumber(tostring(ngx.now()*1000):reverse():sub(1,9))) local randvar = string.format(“%.0f”,math.random(1000000000000000000,9223372036854775807)) ngx.req.set_header(“traceid”, randvar) }
通过ngx.now()*1000拿到毫秒数据转换为字符串取反,这样毫秒数据的变化才能显出效果; unsigned int(64bit机器下为4byte) 最大值为10位数,我们取前9位避免数据溢出带来的转换问题; lua在显示大于64bit的数据时会自动用科学技术法表示,所以我们需要通过string.format函数来将其转换为19位数字,然后通过ngx.req.set_header添加到请求头中去。
上一篇:Redis 官网集群步骤
月圆之夜小红帽日记事件独眼巨人怎么选择
王牌战士幽灵实战技巧讲解
王牌战争文明重启各种资源刷新地点与详细位置大全
崩坏3精英工坊新加入了什么武器圣痕 精英工坊新武器圣痕一览
和平精英通讯塔是什么 和平精英通讯塔玩法详细解析
跑跑卡丁车手游制霸赛场挑战任务全攻略
玄元剑仙神魂悟道秘术有什么用
王牌战士团战如何切入详细讲解
王者荣耀王者模拟战即将上线 王者模拟战玩法介绍
炽姬无双
角色扮演
坠落星界
其它游戏
梦三国
角色扮演
邪恶疯人院
休闲益智
斗罗大陆手游
角色扮演
一刀传世
角色扮演
九州天空城3D
角色扮演
九州战国策
战争策略
穿越火线-枪战王者
枪战射击