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的优化的更多相关文章

  1. golang 项目实战简明指南

    原文地址 开发环境搭建 golang 的开发环境搭建比较简单,由于是编译型语言,写好 golang 源码后,只需要执行 go build 就能将源码编译成对应平台(本文中默认为 linux)上的可执行 ...

  2. flipt 一个基于golang 的特性工具开发类库

    以前介绍过一个Flagr 的基于golang 的特性功能开发类库(技术雷达推荐),今天看到一个类似也很不错的方案flipt 参考架构 包含的特性 快速,使用golang 编写,同时进行了性能优化 运行 ...

  3. golang | Go语言入门教程——结构体初始化与继承

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题第10篇文章,我们继续来看golang当中的面向对象部分. 在上一篇文章当中我们一起学习了怎么创建一个结构体,以及怎么 ...

  4. golang GC 垃圾回收机制

    垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行. Golang中的垃圾回收主要应用三色标记法, ...

  5. Go性能调优

    文章引用自   Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 pr ...

  6. Go语言入门教程系列——函数、循环与分支

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Golang专题的第四篇,这一篇文章将会介绍golang当中的函数.循环以及选择判断的具体用法. 函数 在之前的文章当中其实我们已经接 ...

  7. 内存屏障 WriteBarrier 垃圾回收 屏障技术

    https://baike.baidu.com/item/内存屏障 内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之 ...

  8. GO学习-(21) Go语言基础之Go性能调优

    Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling ...

  9. Go语言系列之性能调优

    在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章 ...

随机推荐

  1. git reset揭秘

    一.命令 首先,让我们来解释几个定义.   HEAD(头)     指向当前branch最顶端的一个commit,该分支上一次commit后的节点   Index(索引)     The index, ...

  2. JavaScripy execCommand函数

    execCommand函数命令 execCommand方法是执行一个对当前文档,当前选择或者给出范围的命令.处理Html数据时常用如下格式:document.execCommand(sCommand[ ...

  3. TensorFlow入门和示例分析

    本文以TensorFlow源码中自带的手写数字识别Example为例,引出TensorFlow中的几个主要概念.并结合Example源码一步步分析该模型的实现过程. 一.什么是TensorFlow 在 ...

  4. (二)ROS系统架构及概念 ROS Architecture and Concepts 以Kinetic为主更新 附课件PPT

    第2章 ROS系统架构及概念 ROS Architecture and Concepts PPT说明: 正文用白色,命令或代码用黄色,右下角为对应中文译著页码. 这一章需要掌握ROS文件系统,运行图级 ...

  5. for循环创建文件夹

    bash里面, for n in a b c; do mkdir $n/dir; done 这个会在a,b,c三个文件夹下创建一个名为dir的文件夹. 之前没有在语句后面加分号,导致在cmd界面提交不 ...

  6. SQL Server 扩展事件(Extented Events)从入门到进阶(3)——通过界面操作Extented Event

    本文属于 SQL Server扩展事件(Extended Events)从入门到进阶 系列 对于接纳扩展事件,其中一个最大的障碍就是要对XML和XQuery有一定的了解以便分析数据.我们可以使用T-S ...

  7. Nginx - 代理、缓存

    Nginx 标签 : nginx 代理 代理服务可简单的分为正向代理和反向代理: 正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送 ...

  8. 游戏引擎cocos2d-android使用大全

    做手机游戏需要三个核心的类,即:SurfaceView,SurfaceHolder,Thread.帧数要在30帧左右是最好的. cocos2d游戏引擎 封装好的框架,可直接使用 cocos2d-and ...

  9. SpriteKit中为何不要在update方法中测试碰撞

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们若要在游戏中做碰撞检测有2种办法,一是利用物理引擎,二是自 ...

  10. 学习Android路上的一些感慨和总结,慢慢来,比较快!

    学习Android路上的一些感慨和总结,慢慢来,比较快! 一直想对自己的学习路程做一个总结,来告别某一个阶段的过去,迎接某一个阶段的来临,一直抽不出时间来,于是零零散散的写了点-,到现在,也已经积攒了 ...