GOLANG实现超时对象检测的最好理解的方式
来源:互联网 发布:只有我知1 编辑:程序博客网 时间:2024/06/05 17:20
原文:https://gocn.io/article/328
依赖于心跳的系统,都需要超时检测。比如P2P系统中客户端每隔120秒向数据服务器发送一次数据汇总,服务器就需要维护一个超时时间。比如一个UDP服务器,在和客户端之间创建Session之后,如果没有数据包,一般会有Ping包,说明这个Session是存活的,服务器在发现Session超时后也需要清理。
首先,服务器一般需要维护一个列表,以Peer为例:
type Peer struct { id uint64 heartbeat time.Time}type Server struct { peers map[uint64]*Peer lock sync.Mutex}
创建Peer,同时在收到Ping消息后,更新Peer的心跳时间:
func (v *Server) Create(id uint64) *Peer { v.lock.Lock() defer v.lock.UnLock() p = &Peer { id:id, heartbeat: time.Now(), } v.peers[id] = p return p}func (v *Server) OnPing(id uint64) { v.lock.Lock() defer v.lock.UnLock() if p,ok := v.peers[id]; ok { p.heatbeat = time.Now() }}
当然,需要起一个goroutine定期扫描这个列表, 假设300秒超时:
go func(v *Server) { for { func(){ v.lock.Lock() defer v.lock.UnLock() now := time.Now() for id,p := range v.peers { if p.heartbeat.Add(300 * time.Second).Before(now) { delete(v.peers, id) } } }() time.Sleep(30 * time.Second) }}(server)
如果Peers的数目非常多,那么扫描时每次都需要锁定v.peers
,会导致其他的业务都无法进行。特别是清理Peer这个过程如果比较复杂,譬如需要发起io请求,是一个费时的操作时,就会造成系统的等待。
一般来说,超时的Peer不会很多,因此可以用chan放一个超时的peer,每个peer专门起一个goroutine来看什么时候超时,这样就可以在检测超时时避免用锁了:
timeout := make(chan *Peer)func (v *Server) Create(id uint64) *Peer { v.lock.Lock() defer v.lock.UnLock() p = &Peer { id:id, heartbeat: time.Now(), } v.peers[id] = p return p go func(p *Peer) { for { tm := p.heartbeat <- time.After(300 * time.Second) if tm.Equal(p.heartbeat) { timeout <- p break } } }(p)}go func(v *Server){ for gw := range timeout { func(){ lgateways.Lock() defer lgateways.Unlock() delete(gateways, gw.port) }() // Do something cleanup about the gateway. }}(server)
这样就只有在有Peer超时时,才真正锁住Server.peers
。
阅读全文
0 0
- GOLANG实现超时对象检测的最好理解的方式
- golang定时器和超时的使用
- 最好理解的卷积
- Golang的面向对象
- 超时的理解:
- 最好的方式?
- 读书最好的方式
- 检测数组最好的办法
- 网络超时检测的方法
- 检测对象属性的几种方式
- Golang以OO的方式实现二叉查找树
- Golang 获得文件名最快的代码实现方式比较
- Golang以OO的方式实现二叉查找树
- golang 的 import理解实验
- Golang 闭包的理解
- GOLANG 实现的 fastcgi
- Golang实现的红黑树
- GOLANG实现类似C++模板,返回符合类型的对象
- 连接查询
- iOS开发 ☞ Runloop使用
- golang如何下载go get不下来(被墙)的第三方包
- android基本功
- [leetcode: Python]434. Number of Segments in a String
- GOLANG实现超时对象检测的最好理解的方式
- Go1.8实现watchdog功能,实现依赖启动服务程序
- Leap Motion(JS)控制(提高事件判定精准度)
- 使用FreeMarker替换JSP的10个理由
- scrapy安装和简单使用
- Android酷炫的25种动画开源框架
- 移动app测试中出现bug漏测的原因分析
- 接口
- dvwa-command injection