我想运行每秒大量请求的负载测试。我在Go中写了一个套接字发送器和一个接收器。发送方向端口7357发送大量数据包,每个数据包包含当前时间(以纳秒为单位)。接收方侦听端口7357并解析每条消息,计算延迟。
问题是,在阅读时,我会在一个conn.Read()
中获得多个数据包。我理解这意味着我实际上每个数据包发送多个消息:每个conn.Write()
都不发送套接字数据包,但它会等待一段时间,然后在发送之前与下一个(或接下来的几个)合并
如何确保每个conn.Write()
作为单独的数据包通过套接字单独发送? 注意:我不想重新发明TCP,我只想模拟每个发送邮件的多个外部实体的负载。
我搜索了文档,但似乎没有conn.Flush()
或类似的。我尝试过使用缓冲编写器:
writer := bufio.NewWriter(conn)
...
bytes, err := writer.Write(message)
err = writer.Flush()
没有错误,但我仍然在接收端收到混合数据包。我也尝试在每conn.Read()
之后做一个假的conn.Write()
0字节,但它也没有工作。发送消息终止符(例如\r\n
)似乎没有任何区别。最后,默认情况下禁用Nagle算法,但我已调用tcp.SetNoDelay(true)
进行测量。
在Node.js中,我设法在每个setImmediate()
之后使用socket.write()
执行此操作:setImmediate()
等待所有I / O完成后再继续。如何在Go中执行相同操作以便获取单独的数据包?
发送:
func main() {
conn, _ := net.Dial("tcp", ":7357")
defer conn.Close()
for {
timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
conn.Write([]byte(timestamp))
conn.Read(buff)
}
}
接收:
func main() {
listen, _ := net.Listen("tcp4", ":7357")
defer listen.Close()
for {
conn, _ := listen.Accept()
go handler(conn)
}
}
func handler(conn net.Conn) {
defer conn.Close()
var buf = make([]byte, 1024)
for {
conn.Read(buf)
data := string(buf[:n])
timestamp, _ := strconv.ParseInt(data, 10, 64)
elapsed := timestamp - time.Now().UnixNano()
log.Printf("Elapsed %v", elapsed)
}
}
为了清晰起见,已删除错误处理,但在实际代码中对其进行了彻底检查。它在第一次运行strconv.ParseInt()
时崩溃,出现value out of range
错误,因为它收到了很多合并的时间戳。
答案 0 :(得分:2)
曾经有一条规则,在允许任何人编写任何使用TCP的代码之前,他们需要从内存中重复以下句子并解释它的含义:" TCP不是消息协议,它是一种可靠的字节流协议,不保留应用程序消息边界。"
除了使用TCP无法可靠地建议的解决方案之外,它不是减少延迟的解决方案。如果网络不堪重负,使用更多数据包发送相同数据只会使延迟变得更糟。
TCP是字节流协议。它提供的服务是一个字节流。周期。
您似乎想要一种适用于TCP的低延迟消息协议。大。设计一个并实现它。
获得低延迟的主要技巧是使用应用程序级别的确认。 TCP ACK标志将捎带到确认上,提供低延迟。
不要禁用Nagling。只有在您无法设计出适合使用TCP的协议时,才能实现这一目标。在非理想条件下,由于同样的原因,即使有可能,您提出的解决方案也是一个糟糕的主意,这会使延迟变得更糟。
但是必须设计和实现消息协议或使用现有协议。您的代码期望TCP(不是消息协议)以某种方式向其传递消息。那段时间不会发生。
如何确保每个conn.Write()作为单独的数据包通过套接字单独发送?注意:我不想重新发明TCP,我只想模拟每个发送消息的外部实体的负载。
即使你可以,也不会做你想做的事情。即使它们是以单独的数据包发送的,也不能保证另一方的read
不会合并。如果要发送和接收消息,则需要一个TCP不支持的消息协议。
在Node.js中,我设法在每个socket.write()之后用setImmediate()完成这个技巧:setImmediate()在继续之前等待所有I / O完成。如何在Go中执行相同操作以便获取单独的数据包?
你可能已经改变了#34;发生了不工作"当我尝试它时,#14;碰巧工作了#34;但由于我已经解释过的原因,你永远无法使这项工作可靠而且你是一个傻瓜的差事。
如果您想发送和接收消息,则需要准确定义"消息"将是并编写代码来发送和接收它们。没有可靠的捷径。 TCP是字节流协议,句号。
如果您关心延迟和吞吐量,请设计优化的消息协议,以通过TCP进行分层,从而优化这些协议。不要禁用Nagle,因为需要Nagle来防止病理行为。只有当您无法更改协议并且使用未设计为在TCP之上进行分层的协议时,才应禁用它。禁用Nagle将一只手绑在背后,通过增加发送数据所需的数据包数量,在网络状况不佳的情况下导致延迟和吞吐量显着降低,即使没有任何意义。
您可能需要/需要应用程序级别的确认。这与TCP很好地协同工作,因为TCP ACK将依赖于应用程序级别的确认。
答案 1 :(得分:-1)
您可以在每次迭代时从套接字读取预定义的字节数,这可能会有所帮助,但您需要创建自己的协议,该协议将由您的应用程序处理。没有proto就不可能保证一切都能稳定运行,因为在接收器上你无法理解开始的位置和消息的结束位置。