什么是 TCP Fast Open
TCP Fast Open 簡稱 TFO,其目的是縮短 TCP 三次握手的時間。通過加入 cookie,在握手階段就可以傳輸數(shù)據(jù)包,從而將三次握手的延時降低到最低。比較適用于網(wǎng)絡延時比較長的場景。
TCP Fast Open 流程
首次請求
- 客戶端發(fā)送 syn,并且字段里面請求 cookie (tfo request)
- 服務端發(fā)送 syn+ack以及cookie
- 客戶端保存cookie并發(fā)送ack
- 客戶端發(fā)送數(shù)據(jù)
后續(xù)請求
- 客戶端發(fā)送 syn、數(shù)據(jù)以及 cookie
- 服務端驗證 cookie 并發(fā)送 syn+ack
- 服務端不必等客戶端ack開始發(fā)送數(shù)據(jù)
- 客戶端發(fā)送 ack
延時分析
假設單程延時為 t,如果沒有用 TFO,那么需要三次握手后才會開始發(fā)送數(shù)據(jù),即發(fā)送數(shù)據(jù)延時至少為 2t,而用了 TFO,發(fā)送數(shù)據(jù)延時就是0。當然從用戶體驗來看,從發(fā)起請求到接收到服務端發(fā)送過來數(shù)據(jù)的延時分別是4t和2t。
TFO 的一些問題
由于帶了 cookie 有些防火墻認為數(shù)據(jù)包異常,在這種環(huán)境下用起來就會有問題。有報告說某些4G網(wǎng)絡就有這種問題。
TCP Fast Open 實踐
系統(tǒng)層面
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 方式發(fā)送數(shù)據(jù),不需要 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/