Go 语言使用 TCP_NODELAY 控制发包流量( 二 )

如果我们打开客户端中被注释掉的conn.SetNoDelay(false)这行代码,也即禁用掉TCP_NODELAY,开启 Nagle 算法,再次抓包,结果如下:
14:27:20.120673 IP localhost.64086 > localhost.irdmi: Flags [P.], seq 8:36, ack 1, win 6379, options [nop,nop,TS val 745574362 ecr 745574362], length 280x0000:4500 0050 0000 4000 4006 0000 7f00 0001E..P..@.@.......0x0010:7f00 0001 fa56 1f40 07c9 d46f a115 3444.....V.@...o..4D0x0020:8018 18eb fe44 0000 0101 080a 2c70 8fda.....D......,p..0x0030:2c70 8fda 474f 5048 4552 0a47 4f50 4845,p..GOPHER.GOPHE0x0040:520a 474f 5048 4552 0a47 4f50 4845 520aR.GOPHER.GOPHER.可以看到,有四个"GOPHER"被合并到了一个 TCP 包中 。
结论TCP_NODELAY并不是万能的,有好处有坏处,需要根据实际业务场景决定打开还是关闭 。但是,在使用具体语言编写网络服务时,我们需要知道它是否被默认开启 。
还有其他一些类似的 socket 选项,比如TCP_QUICKACK和TCP_CORK等 。但是由于有些 socket 选项是平台相关的,因此 Go 没有提供和TCP_NODELAY相同的方式来控制这些 socket 选项 。我们可以通过一些平台相关的包来实现这一点 。比如说,在类 unix 系统下,我们可以使用golang.org/x/sys/unix包中的SetsockoptInt方法 。
举例:
err = unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_QUICKACK, 1)if err != nil {return os.NewSyscallError("setsockopt", err)}最后,如果你想学习更多和 Nagle 算法相关的知识,可以看看这篇英文博客[1]
英文原文链接:Control packet flow with TCP_NODELAY in Go[2]
参考资料[1]
英文博客: https://www.extrahop.com/company/blog/2016/tcp-nodelay-nagle-quickack-best-practices/
[2]
Control packet flow with TCP_NODELAY in Go: https://blog.gopheracademy.com/advent-2019/control-packetflow-tcp-nodelay/




推荐阅读