一个监控项目有个需求,会对一批域名全国的边缘节点进行探测,这里包括,丢包率,http 响应时间,探测频率大概时间是2min 一个周期。这里的域名大概有几百个甚至上千。由于是golang 写的调度和agent, 所以,这里探测丢包率是一个有意思的问题。由于目前git 上没有一个好用的支持multi-ping 的库包,或者多ping 有bug,我自己实现了一个。

git 地址:https://github.com/caucy/batch_ping

1,icmp 协议介绍

icmp 的报文头部一共是2+2+4+4+4 个字节。

type ICMP struct {Type        uint8Code        uint8CheckSum    uint16Identifier  uint16SequenceNum 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 mainimport ("log""github.com/caucy/batch_ping"
)func main() {ipSlice := []string{}// ip list should not more than 65535ipSlice = append(ipSlice, "3g.qq.com")bp, err := ping.NewBatchPinger(ipSlice, false) // true will need to be rootif err != nil {log.Fatalf("new batch ping err %v", err)}bp.SetDebug(true) // debug == true will fmt debug logbp.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 mainimport ("log""github.com/caucy/batch_ping"
)func main() {ipSlice := []string{}// ip list should not more than 65535ipSlice = append(ipSlice, "2400:da00:2::29") //support ipv6ipSlice = append(ipSlice, "baidu.com")bp, err := ping.NewBatchPinger(ipSlice, false) // true will need to be rootif err != nil {log.Fatalf("new batch ping err %v", err)}bp.SetDebug(true) // debug == true will fmt debug logbp.SetSource("") // if hava multi source ip, can use one ispbp.OnFinish = func(stMap map[string]*ping.Statistics) {for ip, st := range stMap {log.Printf("\n--- %s ping statistics ---\n", st.Addr)log.Printf("ip %s, %d packets transmitted, %d packets received, %v%% packet loss\n", ip,st.PacketsSent, st.PacketsRecv, st.PacketLoss)log.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",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,时间间隔非常小,发送机器非常多的时候,会出现非常严重丢包,内核参数需要优化。

最后,文章不易,希望大家点个star,试用。 https://github.com/caucy/batch_ping

高性能异步批量ping的golang实现相关推荐

  1. 高性能异步IO机制:IO_URING

    高性能异步IO机制:IO_URING 一.前言 1.1 异步IO机制 Linux内核提供的IO机制大都是同步实现的,如常规的read/write/send/recv等系统调用.同步IO机制存在着一定的 ...

  2. 批量ping工具fping

    批量ping工具fping ping是各个系统自带的基于ICMP协议的主机探测工具.但该工具一次只能检测一个主机,不满足渗透测试批量探测的需要.Kali Linux提供一款批量探测工具fping.用户 ...

  3. python批量ping50台服务器_Python小技巧—批量ping的方法

    在日常的工作中,我们通常会有去探测目标主机是否存活的应用场景,单个的服务器主机可以通过计算机自带的DOS命令来执行,但是业务的存在往往不是单个存在的,通常都是需要去探测C段的主机(同一个网段下的存活主 ...

  4. linux中间隔10ping一次脚本,linux批量ping脚本shell

    linux批量ping脚本shell *ping失败后的返回字符串 5 packets transmitted, 0 received, 100% packet loss, time 3999ms* ...

  5. 多线程批量ping服务器

    最近由于工作的需要写了个多线程批量ping服务器的脚本,如果服务器down了,自动发报警邮件(可以添加多收件人) 提示:程序网页显示可以能有缩进问题. multithreading_ping_host ...

  6. python批量ping50台服务器_使用python编写批量ping主机脚本

    通过使用python,编写脚本批量ping主机,验证主机是否处于活动状态 #!/usr/bin/python #auther: Jacky #date: 2016-08-01 #filename: p ...

  7. 【python】openstack管理小工具(增删查改,批量ping)

    工具介绍: 创建虚拟机会使用多线程队列的方式去控制同时创建的虚拟机数量 如果在创建的虚拟机比较多,会2次创建.第一次会在各个宿主机上创建一台,其余的会再第一次创建成功后创建. 因为第一次创建需要传输镜 ...

  8. ping不通自己的ip地址_如何批量Ping N个IP地址,掌握一个命令让你节省N小时,让老板给你加鸡腿!...

    这是一个信息爆炸的时代,过多无用的信息.公众号只会让我们视觉疲劳.基于这个原因,本公众号致力于为广大网工分享知识.分享招聘信息.传播有价值的信息,运行4年多以来,已慢慢成为网工圈最受信赖的公众号.了解 ...

  9. akka mysql_Spray + Akka高性能异步IO并发

    Spray + Akka高性能异步IO并发 如何使用Java建立像Node.js那样非堵塞异步事件并发IO服务器呢?Spray是基于NIO2高并发框架,虽然Tomcat 8也是基于NIO2,但是Spa ...

最新文章

  1. 大厂面试录取通过率不到3%,我真是太太太难了......
  2. 2021年春季学期-信号与系统-第七次作业参考答案
  3. AngularJS:如何使用自定义指令来取代ng-repeat
  4. 【图文详解】IDEA控制台运行时出现乱码:淇℃伅...
  5. 简单易懂的破解脱壳从0开始
  6. Sql Server发布订阅如何添加新表如何不初始化整个快照
  7. matlab编译器安装在哪里,MATLAB的m文件编辑器在哪里?
  8. 德国人认真起来,自己都怕!
  9. 手机编程环境初尝试-用AIDE开发Android应用
  10. 【渝粤教育】国家开放大学2018年秋季 0689-22T老年心理健康 参考试题
  11. 音符符号html代码,五线谱符号|五线谱符号图案大全_好特教程
  12. 什么样的人适合学编程?
  13. Long-tailed Recognition (长尾问题)
  14. 对于谷歌搜索的一些基本语法整理
  15. 03-STM32+Air724UG远程升级篇OTA(阿里云物联网平台)-STM32+Air724UG使用阿里云物联网平台OTA远程更新STM32程序
  16. 月薪40K+银行测试经理,自动化测试实践经验分享
  17. jenkins-github上提交代码后构建job(十二)
  18. flinkSql的union all然后group by写入mysql
  19. 经历两个月茫然期后粪发图强,四面美团定级3-1,拿到35*16offer
  20. 网上跳蚤市场网站系统HTML5+Vue+nodejs

热门文章

  1. CakePHP你必须知道的21条技巧
  2. H5CS3酷炫登录注册静态页面
  3. Shell——变量详解及注意点
  4. C/C++——打开文件存储数据的各种方式
  5. HTML——初识html,元素 属性 段落 文本格式化 链接 头部入门
  6. 【今日CV 计算机视觉论文速览 第106期】Fri, 26 Apr 2019
  7. Docker-基本概念(镜像和容器)
  8. 图片盒子控件 winform 114868210
  9. 引入媒体播放器media player 并调试它的选择模式 0130
  10. python-描述符基本