什么是 TCP Fast Open
TCP Fast Open 简称 TFO,其目的是缩短 TCP 三次握手的时间。通过加入 cookie,在握手阶段就可以传输数据包,从而将三次握手的延时降低到最低。比较适用于网络延时比较长的场景。
TCP Fast Open 流程
首次请求
- 客户端发送 syn,并且字段里面请求 cookie (tfo request)
- 服务端发送 syn+ack以及cookie
- 客户端保存cookie并发送ack
- 客户端发送数据
后续请求
- 客户端发送 syn、数据以及 cookie
- 服务端验证 cookie 并发送 syn+ack
- 服务端不必等客户端ack开始发送数据
- 客户端发送 ack
延时分析
假设单程延时为 t,如果没有用 TFO,那么需要三次握手后才会开始发送数据,即发送数据延时至少为 2t,而用了 TFO,发送数据延时就是0。当然从用户体验来看,从发起请求到接收到服务端发送过来数据的延时分别是4t和2t。
TFO 的一些问题
由于带了 cookie 有些防火墙认为数据包异常,在这种环境下用起来就会有问题。有报告说某些4G网络就有这种问题。
TCP Fast Open 实践
系统层面
echo 3 > /proc/sys/net/ipv4/tcp_fastopen
其中1表示启用客户端(sendto),2表示启用服务端(bind),3表示两者都启用。
客户端代码
#!/usr/bin/env python
import socket
import sys
MSG_FASTOPEN = 0x20000000
host = sys.argv[1]
print("connecting to host {} ...".format(host))
addr = (host, 8000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 以 Fast Open 方式发送数据,不需要 connect
s.sendto("hello!", MSG_FASTOPEN, addr)
print s.recv(1000)
服务端代码
import socket
TCP_FASTOPEN = 23
def listen():
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 设置 TCP Fast Open 队列
connection.setsockopt(socket.SOL_TCP, TCP_FASTOPEN, 5)
connection.bind(('0.0.0.0', 8000))
connection.listen(10)
while True:
current_connection, address = connection.accept()
while True:
data = current_connection.recv(2048)
if data:
current_connection.send(data)
print data
current_connection.close()
break
if __name__ == "__main__":
try:
listen()
except KeyboardInterrupt:
pass
软件配置
在 haproxy 中,如果要启用 TCP Fast Open,那么需要在 bind 中显式指定。譬如:
bind 0.0.0.0:12345 tfo
参考链接
https://tools.ietf.org/html/rfc7413
https://lwn.net/Articles/508865/
网友评论