分享
  1. 首页
  2. 文章

为什么Netty的FastThreadLocal速度快

aside section ._1OhGeD · · 1435 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一个监控项目有个需求,会对一批域名全国的边缘节点进行探测,这里包括,丢包率,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 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() {
 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) // debug == true will fmt debug log
 bp.SetCount(100)
 bp.Run()
}

启动上面的进程,会连续ping 3g.qq.com,同时,再启动一个进程ping www.baidu.com , 日志会显示,收到了220.181.38.150 的icmp 包。

image

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() {
 ipSlice := []string{}
 // ip list should not more than 65535
 ipSlice = append(ipSlice, "2400:da00:2::29") //support ipv6
 ipSlice = append(ipSlice, "baidu.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) // debug == true will fmt debug log
 bp.SetSource("") // 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 %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,时间间隔非常小,发送机器非常多的时候,会出现非常严重丢包,内核参数需要优化。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:aside section ._1OhGeD

查看原文:为什么Netty的FastThreadLocal速度快

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1435 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏