golang:使用timingwheel进行大量ticker的优化
Ticker
最近的项目用go实现的服务器需要挂载大量的socket连接。如何判断连接是否还存活就是我们需要考虑的一个问题了。
通常情况下面,socket如果被客户端正常close,服务器是能检测到的,但是如果客户端突然拔掉网线,或者是断电,那么socket的状态在服务器看来可能仍然是established。而实际上该socket已经不可用了。
为了判断连接是否可用,通常我们会用timer机制来定时检测,在go里面,这非常容易实现,如下:
ticker := time.NewTicker(60 * time.Second)
for {
select {
case <-ticker.C:
if err := ping(); err != nil {
close()
}
}
}
上面我们使用一个60s的ticker,定时去ping,如果ping失败了,证明连接已经断开了,这时候就需要close了。
这套机制比较简单,也运行的很好,直到我们的服务器连上了10w+的连接。因为每一个连接都有一个ticker,所以同时会有大量的ticker运行,cpu一直在30%左右徘徊,性能不能让人接受。
其实,我们只需要的是一套高效的超时通知机制。
Close channel to broadcast
在go里面,channel是一个很不错的东西,我们可以通过close channel来进行broadcast。如下:
ch := make(bool)
for i := 0; i < 10; i++ {
go func() {
println("begin")
<-ch
println("end")
}
}
time.Sleep(10 * time.Second)
close(ch)
上面,我们启动了10个goroutine,它们都会因为等待ch的数据而block,10s之后close这个channel,那么所有等待该channel的goroutine就会继续往下执行。
TimingWheel
通过channel这种close broadcast机制,我们可以非常方便的实现一个timer,timer有一个channel ch,所有需要在某一个时间 “T” 收到通知的goroutine都可以尝试读该ch,当T到达时候,close该ch,那么所有的goroutine都能收到该事件了。
timingwheel的使用很简单,首先我们创建一个wheel
//这里我们创建了一个timingwheel,精度是1s,最大的超时等待时间为3600s
w := timingwheel.NewTimingWheel(1 * time.Second, 3600)
//等待10s
<-w.After(10 * time.Second)
因为timingwheel只有一个1s的ticker,并且只创建了3600个channel,系统开销很小。当我们程序换上timingwheel之后,10w+连接cpu开销在10%以下,达到了优化效果。
timingwheel的代码在这里。
golang:使用timingwheel进行大量ticker的优化的更多相关文章
- golang 项目实战简明指南
原文地址 开发环境搭建 golang 的开发环境搭建比较简单,由于是编译型语言,写好 golang 源码后,只需要执行 go build 就能将源码编译成对应平台(本文中默认为 linux)上的可执行 ...
- flipt 一个基于golang 的特性工具开发类库
以前介绍过一个Flagr 的基于golang 的特性功能开发类库(技术雷达推荐),今天看到一个类似也很不错的方案flipt 参考架构 包含的特性 快速,使用golang 编写,同时进行了性能优化 运行 ...
- golang | Go语言入门教程——结构体初始化与继承
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题第10篇文章,我们继续来看golang当中的面向对象部分. 在上一篇文章当中我们一起学习了怎么创建一个结构体,以及怎么 ...
- golang GC 垃圾回收机制
垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行. Golang中的垃圾回收主要应用三色标记法, ...
- Go性能调优
文章引用自 Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 pr ...
- Go语言入门教程系列——函数、循环与分支
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Golang专题的第四篇,这一篇文章将会介绍golang当中的函数.循环以及选择判断的具体用法. 函数 在之前的文章当中其实我们已经接 ...
- 内存屏障 WriteBarrier 垃圾回收 屏障技术
https://baike.baidu.com/item/内存屏障 内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之 ...
- GO学习-(21) Go语言基础之Go性能调优
Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling ...
- Go语言系列之性能调优
在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章 ...
随机推荐
- git reset揭秘
一.命令 首先,让我们来解释几个定义. HEAD(头) 指向当前branch最顶端的一个commit,该分支上一次commit后的节点 Index(索引) The index, ...
- JavaScripy execCommand函数
execCommand函数命令 execCommand方法是执行一个对当前文档,当前选择或者给出范围的命令.处理Html数据时常用如下格式:document.execCommand(sCommand[ ...
- TensorFlow入门和示例分析
本文以TensorFlow源码中自带的手写数字识别Example为例,引出TensorFlow中的几个主要概念.并结合Example源码一步步分析该模型的实现过程. 一.什么是TensorFlow 在 ...
- (二)ROS系统架构及概念 ROS Architecture and Concepts 以Kinetic为主更新 附课件PPT
第2章 ROS系统架构及概念 ROS Architecture and Concepts PPT说明: 正文用白色,命令或代码用黄色,右下角为对应中文译著页码. 这一章需要掌握ROS文件系统,运行图级 ...
- for循环创建文件夹
bash里面, for n in a b c; do mkdir $n/dir; done 这个会在a,b,c三个文件夹下创建一个名为dir的文件夹. 之前没有在语句后面加分号,导致在cmd界面提交不 ...
- SQL Server 扩展事件(Extented Events)从入门到进阶(3)——通过界面操作Extented Event
本文属于 SQL Server扩展事件(Extended Events)从入门到进阶 系列 对于接纳扩展事件,其中一个最大的障碍就是要对XML和XQuery有一定的了解以便分析数据.我们可以使用T-S ...
- Nginx - 代理、缓存
Nginx 标签 : nginx 代理 代理服务可简单的分为正向代理和反向代理: 正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送 ...
- 游戏引擎cocos2d-android使用大全
做手机游戏需要三个核心的类,即:SurfaceView,SurfaceHolder,Thread.帧数要在30帧左右是最好的. cocos2d游戏引擎 封装好的框架,可直接使用 cocos2d-and ...
- SpriteKit中为何不要在update方法中测试碰撞
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们若要在游戏中做碰撞检测有2种办法,一是利用物理引擎,二是自 ...
- 学习Android路上的一些感慨和总结,慢慢来,比较快!
学习Android路上的一些感慨和总结,慢慢来,比较快! 一直想对自己的学习路程做一个总结,来告别某一个阶段的过去,迎接某一个阶段的来临,一直抽不出时间来,于是零零散散的写了点-,到现在,也已经积攒了 ...