英文:
Determine Request Latency
问题
我正在努力使用Go原生创建Pastry的版本。根据设计 [PDF]:
假设应用程序提供了一个函数,允许每个Pastry节点确定与给定IP地址的节点之间的“距离”。较低距离值的节点被认为更可取。应用程序预计根据其选择的接近度度量标准来实现此函数,使用像traceroute或Internet子网映射这样的网络服务,并使用适当的缓存和近似技术来最小化开销。
我正在尝试找出从Go中以编程方式确定两个EC2实例之间的“接近度”(即网络延迟)的最佳方法。不幸的是,我对低级网络不够熟悉,无法区分我可以使用的不同类型的请求。在谷歌上搜索没有提供任何关于从Go中测量延迟的建议,而一般的延迟技术似乎总是Linux二进制文件,我希望能够避免使用更少的依赖。有什么帮助吗?
此外,我注意到在两个EC2实例之间的延迟应该在1毫秒的范围内。虽然我计划在EC2上使用该实现,但它理论上可以在任何地方使用。延迟通常是否如此糟糕,以至于我应该花费精力确保两个节点的网络接近度?请记住,大多数Pastry请求可以在集群中的服务器数量的对数基数16内完成(因此对于10,000个服务器,平均而言,大约需要3个请求来找到正在搜索的键)。例如,从EC2的亚太地区到EC2的美国东部地区的延迟足以证明增加复杂性和引入延迟检查时的开销吗?
英文:
I'm working on creating a version of Pastry natively in Go. From the design [PDF]:
> It is assumed that the application
provides a function that allows each Pastry node to determine the “distance” of a node
with a given IP address to itself. A node with a lower distance value is assumed to be
more desirable. An application is expected to implements this function depending on its
choice of a proximity metric, using network services like traceroute or Internet subnet
maps, and appropriate caching and approximation techniques to minimize overhead.
I'm trying to figure out what the best way to determine the "proximity" (i.e., network latency) between two EC2 instances programmatically from Go. Unfortunately, I'm not familiar enough with low-level networking to be able to differentiate between the different types of requests I could use. Googling did not turn up any suggestions for measuring latency from Go, and general latency techniques always seem to be Linux binaries, which I'm hoping to avoid in the name of fewer dependencies. Any help?
Also, I note that the latency should be on the scale of 1ms between two EC2 instances. While I plan to use the implementation on EC2, it could hypothetically be used anywhere. Is latency generally so bad that I should expend the effort to ensure the network proximity of two nodes? Keep in mind that most Pastry requests can be served in log base 16 of the number of servers in the cluster (so for 10,000 servers, it would take approximately 3 requests, on average, to find the key being searched for). Is the latency from, for example, EC2's Asia-Pacific region to EC2's US-East region enough to justify the increased complexity and the overhead introduced by the latency checks when adding nodes?
答案1
得分: 5
在网络中,一种常见的距离度量标准是计算数据包到达目的地所需的跳数(节点之间的跳数)。你引用的文本中也提到了这个度量标准。即使在你提到的低延迟环境(EC2“本地”)中,这个度量标准也可以给出适当的距离值。
对于Go语言本身的逻辑,人们可能会认为**net
包**是你要寻找的。确实,对于延迟测试(ICMP ping),你可以使用它来创建一个IP连接:
conn, err := net.Dial("ip4", "127.0.0.1")
创建你的ICMP数据包结构和数据,并发送它(参见Wikipedia上的ICMP页面;IPv6需要不同的格式)。不幸的是,你不能像TCP和UDP那样直接创建一个ICMP连接,因此你将不得不自己处理数据包结构。
由于conn
是Conn
类型的Writer
,你可以将你定义的ICMP数据传递给它。
在ICMP类型字段中,你可以指定消息类型。值8、1和30是你要寻找的。8用于你的回显请求,回复将是类型1。也许30会给你一些更多的信息。
不幸的是,要计算网络跳数,你需要IP数据包头字段。这意味着你将不得不构造自己的IP数据包,而net
似乎不允许这样做。
检查Dial()
的源代码,它使用了未导出/公开的internetSocket
。我不确定是否有什么遗漏,但似乎没有简单的方法来构造自己的IP数据包以发送,且可以自定义头部值。你需要进一步检查DialIP
如何使用internetSocket
发送数据包,并复制和调整那段代码/概念。或者,你可以使用cgo和系统库来构造自己的数据包(尽管这会增加更多的复杂性)。
如果你计划使用**IPv6**,你还需要研究ICMPv6。这两个包在其v4版本上有不同的结构。
所以,我建议先使用简单的延迟(定时ping)作为一个简单的实现,然后在以后的时间/之后添加节点跳数,如果你需要的话。如果你两者都有,也许你还想将这两者结合起来(跳数较少并不自动意味着更好;考虑长距离海底电缆等因素)。
英文:
A common distance metric in networking is to count the number of hops (node-hops in-between) a packet needs to reach its destination. This metric was also mentioned in the text you quoted. This could give you adequate distance values even for the low-latency environment you mentioned (EC2 “local”).
For the go logic itself, one would think the net
package is what you are looking for. And indeed, for latency tests (ICMP ping) you could use it to create an IP connection
conn, err := net.Dial("ip4", "127.0.0.1")
create your ICMP package structure and data, and send it. (See Wikipedia page on ICMP; IPv6 needs a different format.) Unfortunately you can’t create an ICMP connection directly, like you can with TCP and UDP, thus you will have to handle the package structure yourself.
As conn
of type Conn
is a Writer
, you can then pass it your data, the ICMP data you defined.
In the ICMP Type field you can specify the message type. Values 8, 1 and 30 are the ones you are looking for. 8 for your echo request, the reply will be of type 1. And maybe 30 gives you some more information.
Unfortunately, for counting the network hops, you will need the IP packet header fields. This means, you will have to construct your own IP packets, which net
does not seem to allow.
Checking the source of Dial()
, it uses internetSocket
, which is not exported/public. I’m not really sure if I’m missing something, but it seems there is no simple way to construct your own IP packets to send, with customizable header values. You’d have to further check how DialIP
sends packages with internetSocket
and duplicate and adapt that code/concept. Alternatively, you could use cgo and a system library to construct your own packages (this would add yet more complexity though).
If you are planning on using IPv6, you will (also) have to look into ICMPv6. Both packages have a different structure over their v4 versions.
So, I’d suggest using simple latency (timed ping) as a simple(r) implementation and then add node-hops at a later time/afterwards, if you need it. If you have both in place, maybe you also want to combine those 2 (less hops does not automatically mean better; think long overseas-cables etc).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论