关系经济人类预测化学自然
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

Go语言定时器time。Tick,你也可能踩过的坑

1月9日 心碎巷投稿
  遇到问题
  最近在处理日志上报kafka时,为防止上报过程中因kafka异常而导致主业务协程阻塞,为此建立了如下日志上报模型:日志主协程负责将消息发给生产者,再由生产者异步写入到broker集群,日志work协程则将收集的日志项通过带缓冲的channel将其传递给日志主协程,从而达到解耦。因日志模型是一对多的关系,为防止work协程长时间等待,为此为每次传递过程设置超时机制,于是在work协程中很容易写出如下代码:
  函数Log2Kafka在每次写日志时调用,为防止单条日志过长同时对超长日志进行切分,切分后再将日志写入到channel中异步传递,同时设定每次传递日志最长时间不能超过500ms,否则认为系统处理不过来直接丢弃本次写操作,这样避免因写channel阻塞而引起协程阻塞。用golang自带的gotest对该模型进行压测,每次4KB数据下QPS能达到百万级别,最低也有1万【kafka异常情况下】。感觉性能ok,应用到业务服务上并先发布到测试环境进行灰度和进一步压测。在测试环境灰度期间,发现服务器CPU曲线图如下所示。
  引进新日志组件时CPU曲线
  未引进新日志组件时CPU曲线问题排查
  从发布后开始压测CPU曲线逐渐增大,压测结束后一直维持在40左右,且中间有极短间歇性的波谷,这和存在定时任务的曲线很类似,不过压测后即使服务空转CPU消耗也维持在40的水平极为不寻常。但通过排查代码没有发现怀疑点,能确定的是肯定是新引进的日志组件导致的。于是在本地对服务进行重新压测,同时开启pprof监控gotoolpprofhttp0。0。0。0:3001seconds60http:localhost:6000debugpprofprofile,抓取一分钟CPU火焰图。
  上图左侧是压测中代码业务逻辑函数的CPU占用情况,中间红色框内的是系统调用,图中可以看出系统调用占用CPU时间较长,且从函数名如parkm、schedule、findrunnable可以猜测出应该是与协程调度相关,这说明程序空转的时候系统在不断进行协程上下文切换,另外其中与时间相关的函数也占用了较长CPU时间。因此从火焰图所展示的调用层次不难推出是如下场景导致的CPU高:程序的某个定时器不断的被触发,从而唤起对应的协程被调度执行。
  好了,根据如上的现象及分析结论我们再去看新引入的日志组件的代码,重点关注有定时器逻辑的,开头提到Log2Kafka函数有段代码如下图所示。
  按照写代码时的理解这里每次写日志才会开启一个定时器,且定时器的作用域在该函数内,按理来说没有继续写日志应该不会有定时器在运行才对。那为什么程序空转的时候还存在定时器不断触发的情况呢?难道是定时器一直存在而没有随着函数调用结束被回收?带着这个疑问我们看下golangtime包的几个定时器函数:time。NewTimer:创建定时器,调用startTimer开启定时器并将其加入到当前P的定时器堆中【startTimer内部调用了addtimer实现https:go。devsrcruntimetime。go】,到时间后向channel写入当前时间,只执行一次。time。NewTicker:创建过程和NewTimer类似,每次间隔固定时间向channel写入当前时间。time。Tick:创建隐式定时器,其实际是调用了NewTicker,只不过返回的是定时器的只读channel而不是定时器本身,属于NewTicker的间接访问方式。time。AfterFunc:创建隐式定时器,固定时间后触发某个函数执行,只执行一次。
  所以实际上无论调用哪个函数创建定时器都不会自动回收,需要开发人员手动调用stop函数终止才能释放资源,这样也就能解释得通为何在压测后即使程序空转也一直在不断的触发定时器并导致协程调度了。因为每次调用Log2Kafka函数时都会执行time。Tick,从而在压测时不断的创建出一个每500毫秒触发一次的定时器且又没有释放。解决问题
  为避免上述问题,我们需要避免重复创建且在日志写完后主动将定时器关闭。基于此优化后的代码如下:在写之前先显示创建定时器【由于只需要定时器触发一次,故调用NewTimer】,同时通过defer机制保障一定会被关闭。
  修改后再次压测结果如下:压测瞬间CPU不断飚高,压测结束后CPU消耗曲线立马下降到正常水平,不会再出现之前的无法恢复的现象。
  修复后压测前后CPU曲线
  修复后空转时COU曲线
  另一种修复方式:
  除了使用定时器外,我们还可以用golang自带的上下文来解决上述问题,代码可改为如下形式,其实际内部实现也是通过调用time。AfterFunc函数生成定时器来实现,只不过不需要开发自己去手动关闭。
  写在最后go编程中如使用定时器时尽量显示创建且需手动关闭,否则容易出现协程和channel泄露。使用gotest压测时除了注意QPS外还应该多关注CPU消耗。select在执行时会判断每个case是否就绪,然后再随机执行就绪的case,并不是只遇到已就绪的case后续的case就不判断了。这样若在case中有执行语句会被执行。go自带的pprof是个好东西,在性能分析上应该经常使用。
投诉 评论 转载

利川组图宛若仙境齐岳云海美爆了利川市齐岳山的云海到底有多美?跟随摄影师的镜头去领略一下吧!早上七八点钟,金黄的太阳光洒在众山之巅,仿佛给群山穿上了一件金光灿灿的外衣。薄薄的云雾围绕着群山,平铺万……心肌梗塞的黄金救治时间心血管疾病已经成为我国城市和农村人群第一位的死亡原因,其中急性心肌梗死导致的死亡率增长更显著。需要对其心肌梗塞的黄金救治时间等进行了解,本站小编给大家介绍一下。急性心肌梗……核桃是血管清道夫还是催命符?早上吃好,还是晚上吃好?答案来了这核桃可不是什么好东西,少吃点吧!许大娘气势汹汹地将桌面装着核桃的果盘端走,絮絮叨叨地跟老伴反复强调,核桃吃多了不仅伤肝,还堵血管。老伴刘大叔患有慢性肝炎多年,一直……小儿肠系膜淋巴结结核早期症状有哪些小儿肠系膜淋巴结结核早期症状有哪些呢?主要症状为一般结核中毒症状及局部症状。慢性中毒症状为长期不规则低热、食欲减退、消瘦、容易疲劳、睡眠不安、情绪不稳等。局部胃肠道症状有恶心、……上阳赋王儇因母亲的死黑化了吗王儇母亲长公主被逼死王儇一生可谓是跌宕起伏,这也迫使王儇必须坚强起来,她要为自己以及王家寻求一条正道。王蔺的野心朝中上下皆知,导致王儇和萧綦都被皇帝猜忌,甚至要将他们消除。王儇不可能坐以待毙,一边……黑蜂蜂蜜和普通蜂蜜的区别蜂蜜是蜜蜂采集植物的花蜜酿制而成的,因蜂种和蜜源等不同可以分成很多蜜种,虽然这些蜜种在成分上基本都大同小异,但在深层次上它们之间也是有区别的,下面我们就一起来看一看黑蜂蜂蜜和普……勇士输了森林狼!!整场比赛看下来在后段,总感觉有些怪怪的,抒发一下自己的观点。勇士队与森林狼队在加时赛战斗许久才分出胜负,比赛的某些片段是十分激烈的。其实前三节的勇士队表现是不错的,球星,有个人……月似当时二星期天是个艳阳天,天空湛蓝湛蓝的,不带半点杂质。一大早,榕榕就驾车来到林舒欣家门口。汽车喇叭声肆无忌惮的在天空中回荡,林舒欣穿得像个修女似的,背个小包,戴着墨镜出来了。榕榕走出……Go语言定时器time。Tick,你也可能踩过的坑遇到问题最近在处理日志上报kafka时,为防止上报过程中因kafka异常而导致主业务协程阻塞,为此建立了如下日志上报模型:日志主协程负责将消息发给生产者,再由生产者异步写……西兰花的做法大全家常这八种做法了解下西兰花的做法大全家常西兰花炒桃仁材料:西兰花,核桃仁,蒜,盐,鸡精。做法:1。锅中水开后,放入少许盐和植物油,再放入西兰花,水开后再焯几秒钟。……头上长出一棵树姐姐,你的头上有一棵树诶!好好玩,我也想要一棵!茜茜眨巴着宝石般的眼睛,直勾勾地盯着面前这个女孩头上的树,树已经结果了。你真的想要吗?小妹妹?望着女孩的笑容,茜茜坚定地点……王者荣耀凯背后的英雄故事你知道王者荣耀铠皮肤曙光守护者的背景故事吗?凯出生在一个繁华兴盛的城市,传说这座城市曾被天使所庇佑,天使的纪念雕像至今矗立城市中心。修建于城市最辉煌时期的天使纪念碑高大圣……
环境污染致人损害由谁承担赔偿责任我们那雷人的老师此恨绵绵缘来无期第卅一回意难忘情难续国有集团公司负责人履职情况述责述廉报告幼儿园3年,父母让孩子做好2件事,孩子学习成绩比同龄人更优秀晨起第一杯水,该如何喝?提醒这3种水,医生可不建议你多喝新生儿睡眠新生儿睡眠要注意什么永历皇帝为何不去海南偏要到缅甸去有那么一个人日本中小学为何与我们不一样停课也停学了消息称美团优选大幅裁员陈年黑茶和新黑茶有什么区别
喝的造句用喝的造句大全时间来来来,咱看看,那么多限制老赖的措施中,哪个最狠?推进随班就读,须做好四类人员的思想工作自考本科文凭怎么样张掞龙图挽词三首其三纪念碑造句用纪念碑造句大全发朋友圈早安的句子为什么会越来越欣赏杨超越?她最触人心弦的可能是孤独派出所报案后多久立案蜂王浆有丰胸的效果吗蜂王浆怎么吃丰胸如何让U盘不传播病毒

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州