我是靠谱客的博主 慈祥小虾米,最近开发中收集的这篇文章主要介绍GOLANG实现超时对象检测的最好理解的方式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原文: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

最后

以上就是慈祥小虾米为你收集整理的GOLANG实现超时对象检测的最好理解的方式的全部内容,希望文章能够帮你解决GOLANG实现超时对象检测的最好理解的方式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部