加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

高性能异步批量ping的golang实现

发布时间:2020-12-16 09:20:51 所属栏目:大数据 来源:网络整理
导读:一个监控项目有个需求,会对一批域名全国的边缘节点进行探测,这里包括,丢包率,http 响应时间,探测频率大概时间是2min 一个周期。这里的域名大概有几百个甚至上千。由于是golang 写的调度和agent, 所以,这里探测丢包率是一个有意思的问题。由于目前git

  一个监控项目有个需求,会对一批域名全国的边缘节点进行探测,这里包括,丢包率,http 响应时间,探测频率大概时间是2min 一个周期。这里的域名大概有几百个甚至上千。由于是golang 写的调度和agent, 所以,这里探测丢包率是一个有意思的问题。由于目前git 上没有一个好用的支持multi-ping 的库包,或者多ping 有bug,我自己实现了一个    1,icmp 协议介绍    icmp 的报文头部一共是2+2+4+4+4 个字节。    type ICMP struct {    Type uint8    Code uint8    CheckSum uint16    Identifier uint16    SequenceNum uint16    这里 type 是icmp 类型,常见有发送报文头 Echo,回收报文头 Echo Reply 等,更多类型 见 https://tools.ietf.org/html/rfc792 。 Code 进一步划分ICMP的类型,该字段用来查找产生错误的原因;CheckSum 校验码部分,这个字段包含有从ICMP报头和数据部分计算得来的,用于检查错误的数据;而Identifier 通常为进程id,标识具体是哪个进程发送的icmp 包;SequenceNum 标识发送包的顺序id。    icmp 有个特点,listen 能收到其他进程ping 的结果,看下面例子:    package main    import (    "log"    "github.com/caucy/batch_ping"    )    func main(xingtuylgw.com) {    ipSlice := []string{}    // ip list should not more than 65535    ipSlice = append(ipSlice,"3g.qq.com")    bp,err := ping.NewBatchPinger(ipSlice,false) // true will need to be root    if err != nil {    log.Fatalf("new batch ping err %v",err)    }    bp.SetDebug(true) www.sangyuLpt.com// debug == true will fmt debug log    bp.SetCount(100)    bp.Run()    }    启动上面的进程,会连续ping 3g.qq.com,同时,再启动一个进程ping www.baidu.com,日志会显示,收到了220.181.38.150 的icmp 包。    2, 如何支持同时支持ping 多个addr    第一种是最简单的,也是大多数探针采用的方式:subprocess 。这个方式有个缺点,就是每个任务会fork 一个进程,非常耗费耗费资源。    第二种方式,我是这样想的,golang 有icmp 包,能够支持send and recive,我直接起协程 去 收发,每个协程和subprocess 一样,先发后等,这样不就行了?然后起一组协程池,这样并发也能控制。然而,上面例子已经提到了,listen 后的conn 能收到其他进程 ping 的结果,这样实现挺麻烦。    第三种方式,一个协程收,一个协程发。最后选择的是这种方式。    一个协程收,一个协程发,有什么比较麻烦地方?因为icmp 层只能标识seq,所以会出现icmp 包头相同的情况,同时,批量收发,非常容易出现丢包的情况。    3,batch-ping 特性    支持原地址控制    支持ipv6 (操作系统本身支持“ip6:ipv6-icmp”,“udp6” dial )    支持时间间隔控制    支持发送方式控制    支持多addr 控制    支持 mac,linux    使用示例:    package main    import (    "log"    "github.com/caucy/batch_ping"    )    func main( www.baichuangyule.cn) {    ipSlice := []string{}    // ip list should not more than 65535    ipSlice = append(ipSlice,www.jintianxuesha.com "2400:da00:2::29") //support ipv6    ipSlice = append(ipSlice,www.qjljdgt.cn "baidu.com")    bp,false)www.yacuangyl.com // true will need to be root    if err != nil {    log.Fatalf("new batch ping err %v",err)    }    bp.SetDebug(true) jujinyulee.com // debug == true will fmt debug log    bp.SetSource("www.xinhuihpw.com") // if hava multi source ip,can use one isp    bp.OnFinish = func(stMap map[string]*ping.Statistics) {    for ip,st := range stMap {    log.Printf("n--- %s ping statistics ---n",st.Addr)    log.Printf("ip www.rhyl158.com %s,%d packets transmitted,%d packets received,%v%% packet lossn",ip,    st.PacketsSent,st.PacketsRecv,st.PacketLoss)    log.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%vn",    st.MinRtt,st.AvgRtt,st.MaxRtt,st.StdDevRtt)    log.Printf("rtts is %v n",st.Rtts)    }    }    err = bp.Run()    if err != nil {    log.Printf("run err %v n",err)    }    bp.OnFinish(bp.Statistics())    }    4,可能问题    因为icmp 基于udp,时间间隔非常小,发送机器非常多的时候,会出现非常严重丢包,内核参数需要优化。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读