Contents

[Network] 1. 文件传输优化分享

[Network] 1. 文件传输优化分享

背景(敏感数据已脱敏)

  • 由于种种要求,需要将数据上传到海外的 oss 上进行存储。所以开发了一个代理服务维护数据并进行加密等操作。期间内部发现数据上传下载非常慢,经过一系列排查,最终定位到问题根源,并给出解决方案。现将排查过程进行分享。
  • 当然了,前提之一是内网打通,通过专线网络接入,才能做到理论上的物理极限。使用复杂漫长的公共网络既不适合文件安全,也不适合大文件长时间传输。

服务本身问题

描述
  • 最初怀疑是数据落盘导致的太慢。因为上传必须落盘,防止文件过大。下载直接流式传输,非常合理。唯一的改进是上传进行流式加密和传输,但是当前问题不大。

现象

  • 使用编写的脚本上传 1M 的加密数据,耗时接近 2s
1
2
3
4
5
import requests
requests.post(f"{url}/upload/files", files={
    "data": ('', upload_data, "application/json"),
    "file": transfer_data
})
1
2
3
4
5
6
7
$ python oss.py --file_input=./1M.data --region=us --model=3 --range=5
encrypted_upload
upload ./1M.data, encrypt cost 4.714599609375, upload cost 1788.95849609375
upload ./1M.data, encrypt cost 10.140625, upload cost 1945.90087890625
upload ./1M.data, encrypt cost 9.924560546875, upload cost 1756.984130859375
upload ./1M.data, encrypt cost 8.694580078125, upload cost 1930.31201171875
upload ./1M.data, encrypt cost 8.279296875, upload cost 1739.38623046875

抓包

  • 与运维进行沟通,运维怀疑是网络问题,进行抓包一探究竟。

抓包演示

ping 包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ sudo tcpdump -i bond0 | grep x.x.x.x1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:21:19.255718 IP public2.alidns.com.domain > domain1.36590: 43190 1/0/1 A x.x.x.x1 (88)
16:21:19.256404 IP domain1 > x.x.x.x1: ICMP echo request, id 32590, seq 1, length 64
16:21:19.456754 IP x.x.x.x1 > domain1: ICMP echo reply, id 32590, seq 1, length 64
16:21:20.257688 IP domain1 > x.x.x.x1: ICMP echo request, id 32590, seq 2, length 64
16:21:20.458076 IP x.x.x.x1 > domain1: ICMP echo reply, id 32590, seq 2, length 64
16:21:21.259088 IP domain1 > x.x.x.x1: ICMP echo request, id 32590, seq 3, length 64
16:21:21.459506 IP x.x.x.x1 > domain1: ICMP echo reply, id 32590, seq 3, length 64
16:21:22.260538 IP domain1 > x.x.x.x1: ICMP echo request, id 32590, seq 4, length 64
16:21:22.460976 IP x.x.x.x1 > domain1: ICMP echo reply, id 32590, seq 4, length 64
1
2
3
4
5
6
7
8
9
$ ping domain1
PING domain1 (x.x.x.x1) 56(84) bytes of data.
64 bytes from x.x.x.x1 (x.x.x.x1): icmp_seq=1 ttl=58 time=200 ms
64 bytes from x.x.x.x1 (x.x.x.x1): icmp_seq=2 ttl=58 time=200 ms
64 bytes from x.x.x.x1 (x.x.x.x1): icmp_seq=3 ttl=58 time=200 ms
^C
--- domain1 ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 3004ms
rtt min/avg/max/mdev = 200.395/200.419/200.456/0.517 ms

三次握手

1
2
3
16:54:06.286416 IP domain1.33666 > x.x.x.x1.http: Flags [S], seq 2682796272, win 64240, options [mss 1460,sackOK,TS val 2595135963 ecr 0,nop,wscale 7], length 0
16:54:06.486797 IP x.x.x.x1.http > domain1.33666: Flags [S.], seq 2198055866, ack 2682796273, win 62643, options [mss 1460,sackOK,TS val 2062390218 ecr 2595135963,nop,wscale 7], length 0
16:54:06.486840 IP domain1.33666 > x.x.x.x1.http: Flags [.], ack 1, win 502, options [nop,nop,TS val 2595136163 ecr 2062390218], length 0

四次挥手

1
2
3
16:54:28.356723 IP domain1.54028 > x.x.x.x1.http: Flags [F.], seq 1746, ack 215, win 501, options [nop,nop,TS val 2595158034 ecr 2062412087], length 0
16:54:28.557169 IP x.x.x.x1.http > domain1.54028: Flags [F.], seq 215, ack 1747, win 477, options [nop,nop,TS val 2062412289 ecr 2595158034], length 0
16:54:28.557222 IP domain1.54028 > x.x.x.x1.http: Flags [.], ack 216, win 501, options [nop,nop,TS val 2595158234 ecr 2062412289], length 0

tcpdump Flags

  • Tcpdump flags 是指示 TCP 连接状态或动作的标志。它们通常在 tcpdump 输出中用方括号表示。Tcpdump 输出中有多种 flags,输出也可能包含多个 TCP flags 的组合 1。一些常见的 flags 有:
    • S (SYN): 这个 flag 用于在两个主机之间建立连接。它在三次握手的第一个包中设置。
    • . (No flag): 这意味着在包中没有设置任何 flag。它通常用于数据传输或确认包。
    • P (PUSH): 这个 flag 用于表示发送方希望尽快发送数据,而不等待缓冲区填满。
    • F (FIN): 这个 flag 用于终止两个主机之间的连接。它在四次挥手的最后一个包中设置。
    • R (RST): 这个 flag 用于重置处于无效状态或遇到错误的连接。它也用于拒绝不想要的连接尝试。
    • W (ECN CWR): 这个 flag 用于表示发送方已经根据网络的显式拥塞通知 (ECN) 减小了其拥塞窗口大小。
    • E (ECN-Echo): 这个 flag 用于表示接收方已经收到了一个带有 ECN 位的包,这意味着网络中存在拥塞。
  • 例如,一个带有 flags [S.] 的包意味着它是一个 SYN 包,是建立 TCP 连接的第一步。一个带有 flags [P.] 的包意味着它是一个 PUSH 包,包含了发送方想要快速传送的数据。一个带有 flags [F.] 的包意味着它是一个 FIN 包,是关闭 TCP 连接的最后一步 2。

为什么 tcpdump 四次挥手只有三个包

  • Tcpdump 四次挥手只有三个包的原因可能有以下几种:
    • 一种可能是被动关闭方(收到 FIN 的一方)在回复 ACK 的同时,也发送了自己的 FIN,将第二次和第三次挥手合并为一个报文,节省了一个包 1。这种情况下,被动关闭方已经没有数据要发送了,所以可以直接进入 LAST_ACK 状态,等待主动关闭方的最后一个 ACK。
    • 另一种可能是主动关闭方(发送 FIN 的一方)在收到被动关闭方的 FIN 后,没有及时回复 ACK,而是在一段时间后才发送 ACK,并且在 ACK 中设置了 RST 标志,表示强制重置连接 2。这种情况下,主动关闭方可能遇到了异常或超时,所以不再等待 2MSL 的时间,而是直接进入 CLOSE 状态。
    • 还有一种可能是 tcpdump 没有抓到所有的包,因为网络延迟或丢包的原因,导致某个挥手的报文没有被捕获到 3。这种情况下,可以尝试重新抓包或增加抓包的时间范围,看是否能够看到完整的四次挥手过程。

实际数据

1
2
3
$ python oss.py --file_input=./1K.data --file_output=./download-1M.data --region=us --model=3 --range=5
encrypted_upload
http://domain1 upload ./1K.data, encrypt cost 1.530029296875, upload cost 408.5546875
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ sudo tcpdump -i bond0 | grep x.x.x.x1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 262144 bytes

16:54:06.286416 IP domain1.33666 > x.x.x.x1.http: Flags [S], seq 2682796272, win 64240, options [mss 1460,sackOK,TS val 2595135963 ecr 0,nop,wscale 7], length 0
16:54:06.486797 IP x.x.x.x1.http > domain1.33666: Flags [S.], seq 2198055866, ack 2682796273, win 62643, options [mss 1460,sackOK,TS val 2062390218 ecr 2595135963,nop,wscale 7], length 0
16:54:06.486840 IP domain1.33666 > x.x.x.x1.http: Flags [.], ack 1, win 502, options [nop,nop,TS val 2595136163 ecr 2062390218], length 0
16:54:06.486930 IP domain1.33666 > x.x.x.x1.http: Flags [P.], seq 1:292, ack 1, win 502, options [nop,nop,TS val 2595136164 ecr 2062390218], length 291: HTTP: POST /upload/files HTTP/1.1
16:54:06.486960 IP domain1.33666 > x.x.x.x1.http: Flags [P.], seq 292:1746, ack 1, win 502, options [nop,nop,TS val 2595136164 ecr 2062390218], length 1454: HTTP
16:54:06.687234 IP x.x.x.x1.http > domain1.33666: Flags [.], ack 292, win 488, options [nop,nop,TS val 2062390419 ecr 2595136164], length 0
16:54:06.687279 IP x.x.x.x1.http > domain1.33666: Flags [.], ack 1746, win 477, options [nop,nop,TS val 2062390419 ecr 2595136164], length 0
16:54:06.690277 IP x.x.x.x1.http > domain1.33666: Flags [P.], seq 1:215, ack 1746, win 477, options [nop,nop,TS val 2062390422 ecr 2595136164], length 214: HTTP: HTTP/1.1 200 OK
16:54:06.690314 IP domain1.33666 > x.x.x.x1.http: Flags [.], ack 215, win 501, options [nop,nop,TS val 2595136367 ecr 2062390422], length 0
16:54:06.692023 IP domain1.33666 > x.x.x.x1.http: Flags [F.], seq 1746, ack 215, win 501, options [nop,nop,TS val 2595136369 ecr 2062390422], length 0
16:54:06.892401 IP x.x.x.x1.http > domain1.33666: Flags [F.], seq 215, ack 1747, win 477, options [nop,nop,TS val 2062390624 ecr 2595136369], length 0
16:54:06.892448 IP domain1.33666 > x.x.x.x1.http: Flags [.], ack 216, win 501, options [nop,nop,TS val 2595136569 ecr 2062390624], length 0
  • 实际是上传 1M 数据,进行分析,此处简化。
  • 因为时间跳跃增长全部发生在服务端返回的数据包。此时问题已经很明了了,由于深圳和美东现实的物理距离,200ms 的来回已经做到了极限。所以其实是合理的。

灵魂拷问

  • 此时,一个灵魂拷问出现了,为什么之前走公网反而更快?
  • 与兄弟部门同事沟通,模拟他们的代码,使用 aws 的 sdk 进行测试
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import boto3
from boto3.s3.transfer import TransferConfig

def download():
    s3_client = client(access_key, access_secret, host)
    GB = 1024 ** 3
    config = TransferConfig(multipart_threshold=2 * GB, max_concurrency=10, use_threads=True)
    s3_client.download_file(Bucket="bucket", Key="name-100.jpg", Filename="name-100.jpg", Config=config)

if __name__ == '__main__':
    download()
    # ...
    download()

结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
2.359457492828369
2.34989070892334
2.4120875199635825
2.3953704833984375
2.382766008377075
2.3793430725733438
2.3801622731345042
2.374732166528702
2.393121269014147
2.387941288948059
2.3849898034876045
2.3809364239374795
2.382789208338811
2.379830701010568
2.3768802642822267
2.3746740520000458
2.374574675279505
2.3716080056296454
  • 可以看出,使用 aws-sdk,反而更慢。这就更奇怪了,为什么没有复现出兄弟部门的结果?
  • 首先看到 config 里的max_concurrency=10给了我一定的迷惑,client 肯定是自己支持线程池的,但是看起来没有用到,因为每次初始化了新的 client

优化

  • 所以复用 client 进行测试
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def download():
    s3_client = client(access_key, access_secret, host)
    GB = 1024 ** 3
    config = TransferConfig(multipart_threshold=2 * GB, max_concurrency=10, use_threads=True)
    now = time.time()
    count = 0

    while count < 20:
        s3_client.download_file(Bucket="bucket", Key="name-100.jpg", Filename="name-100.jpg", Config=config)
        count += 1
        print((time.time() - now) / count)

结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
download
2.465491533279419
1.5669758319854736
1.2221351464589436
1.0315884947776794
0.9212518692016601
0.8434466520945231
0.7922392232077462
0.7573718726634979
0.7251839107937283
0.6981703996658325
0.6772929538380016
0.6588474710782369
0.6429501130030706
0.6297299180712018
0.6190152009328206
0.6086597740650177
0.5995960656334373
0.5917102760738797
0.585765048077232
0.5791293740272522
  • 根据结果发现,只是以为默认框架全复用连接。修改为复用连接后,效果极佳。
  • 而且正在接近理论极限值 200ms(无限带宽,一次交互)

初步结论

  • 首先,关于如何加速传输,已经有了最直接的结论。复用连接即可,下文贴出 1M 文件的对比

复用连接与不复用连接对比

1
2
3
4
5
6
7
$ python oss.py --file_input=./1M.data --file_output=./download-1M.data --region=us --model=3 --range=5
encrypted_upload
http://domain1 upload ./1M.data, encrypt cost 4.924560546875, upload cost 1919.100341796875
http://domain1 upload ./1M.data, encrypt cost 4.593017578125, upload cost 1715.593994140625
http://domain1 upload ./1M.data, encrypt cost 10.076171875, upload cost 2253.67333984375
http://domain1 upload ./1M.data, encrypt cost 12.694091796875, upload cost 1714.197021484375
http://domain1 upload ./1M.data, encrypt cost 12.3076171875, upload cost 2152.773193359375

继续拷问

  • 本来,一切的一切,到这里都结束了,复用连接,效率极其提高。与服务端无关,仅与客户端有关,客户端交给兄弟部门进行改造即可。
  • 直到兄弟部门反馈了一个问题——为什么服务端会断开连接?
  • 我通过网上查询和翻源码的默认值,发现
    1. 服务端默认支持 8192 连接
    2. 默认客户端连接 30m 超时或永不超时
  • 明显都与事实不符合
  • 然后兄弟部门开始监听连接状态,发现连接状态快速进入了 CLOSE_WAIT 的状态。明显是服务端接收到了 FIN 包。为了说明该情况,通过抓包,实际证明了兄弟部门代码问题导致发送了 FIN 包。
  • 由于我非常认可通过抓包和监听连接状态的方式来查找问题,我打算复现一下之前的情况来介绍一下抓包工具和方法。但是复现的过程中,我开始了灵魂拷问

为什么效率优化这么大?

  • 按照朴素的思想,复用连接,应该是省略了三次握手和四次挥手,根据上述的了解,应该仅优化 400ms 左右才对。然而事实并非如此,而是秒级别优化,这是为什么?
1
2
3
4
5
6
7
8
# 朴素思想中的不复用连接传包
1. [S][P][P][P][P][F]
2.                   [S][P][P][P][P][F]
3.                                     [S][P][P][P][P][F]
# 朴素思想中的复用连接传包
1. [S][P][P][P][P]
2.                [P][P][P][P]
3.                            [P][P][P][P][F]
1
2
3
4
5
6
7
$ python oss-muti.py --file_input=./1M.data --file_output=./download-1M.data --region=us --model=3 --range=5
encrypted_upload
http://domain1 upload ./1M.data, encrypt cost 5.02880859375, upload cost 2589.014892578125
http://domain1 upload ./1M.data, encrypt cost 10.720947265625, upload cost 562.706787109375
http://domain1 upload ./1M.data, encrypt cost 11.202392578125, upload cost 370.651611328125
http://domain1 upload ./1M.data, encrypt cost 10.948486328125, upload cost 372.409423828125
http://domain1 upload ./1M.data, encrypt cost 11.99560546875, upload cost 371.28759765625
  • 所以再次抓包进行深究

100K 数据对比(省略返回包)

1
2
3
4
5
6
7
$ python oss.py --file_input=./100K.data --file_output=./100K.data --region=us --model=3 --range=5
encrypted_upload
http://domain1 upload ./100K.data, encrypt cost 1.81884765625, upload cost 1017.35791015625
http://domain1 upload ./100K.data, encrypt cost 1.159912109375, upload cost 1021.509521484375
http://domain1 upload ./100K.data, encrypt cost 1.11669921875, upload cost 1016.612548828125
http://domain1 upload ./100K.data, encrypt cost 1.128662109375, upload cost 1016.171875
http://domain1 upload ./100K.data, encrypt cost 0.9912109375, upload cost 1016.228759765625
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$ sudo tcpdump -i bond0 | grep x.x.x.x1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:16:03.069540 IP domain1.53580 > x.x.x.x1.http: Flags [S], seq 4211566581, win 64240, options [mss 1460,sackOK,TS val 2596452757 ecr 0,nop,wscale 7], length 0
17:16:03.270682 IP x.x.x.x1.http > domain1.53580: Flags [S.], seq 1741768869, ack 4211566582, win 62643, options [mss 1460,sackOK,TS val 2063707002 ecr 2596452757,nop,wscale 7], length 0
17:16:03.270850 IP domain1.53580 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596452958 ecr 2063707002], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:03.680467 IP domain1.53580 > x.x.x.x1.http: Flags [P.], seq 72694:74142, ack 1, win 502, options [nop,nop,TS val 2596453367 ecr 2063707405], length 1448: HTTP
17:16:03.874400 IP domain1.53580 > x.x.x.x1.http: Flags [P.], seq 101758:103124, ack 1, win 502, options [nop,nop,TS val 2596453561 ecr 2063707606], length 1366: HTTP
17:16:04.082005 IP x.x.x.x1.http > domain1.53580: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063707813 ecr 2596453561], length 214: HTTP: HTTP/1.1 200 OK

17:16:04.083769 IP domain1.53580 > x.x.x.x1.http: Flags [F.], seq 103124, ack 215, win 501, options [nop,nop,TS val 2596453771 ecr 2063707813], length 0
17:16:04.090059 IP domain1.44338 > x.x.x.x1.http: Flags [S], seq 3876376673, win 64240, options [mss 1460,sackOK,TS val 2596453777 ecr 0,nop,wscale 7], length 0
17:16:04.284937 IP x.x.x.x1.http > domain1.53580: Flags [F.], seq 215, ack 103125, win 442, options [nop,nop,TS val 2063708016 ecr 2596453771], length 0
17:16:04.291110 IP x.x.x.x1.http > domain1.44338: Flags [S.], seq 27078140, ack 3876376674, win 62643, options [mss 1460,sackOK,TS val 2063708023 ecr 2596453777,nop,wscale 7], length 0
17:16:04.291270 IP domain1.44338 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596453978 ecr 2063708023], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:04.693394 IP domain1.44338 > x.x.x.x1.http: Flags [P.], seq 42286:43734, ack 1, win 502, options [nop,nop,TS val 2596454380 ecr 2063708425], length 1448: HTTP
17:16:04.720945 IP domain1.44338 > x.x.x.x1.http: Flags [P.], seq 72694:74142, ack 1, win 502, options [nop,nop,TS val 2596454408 ecr 2063708425], length 1448: HTTP
17:16:04.894505 IP domain1.44338 > x.x.x.x1.http: Flags [P.], seq 101838:103124, ack 1, win 502, options [nop,nop,TS val 2596454582 ecr 2063708626], length 1286: HTTP
17:16:05.105003 IP x.x.x.x1.http > domain1.44338: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063708837 ecr 2596454582], length 214: HTTP: HTTP/1.1 200 OK

17:16:05.106641 IP domain1.44338 > x.x.x.x1.http: Flags [F.], seq 103124, ack 215, win 501, options [nop,nop,TS val 2596454794 ecr 2063708837], length 0
17:16:05.112610 IP domain1.44340 > x.x.x.x1.http: Flags [S], seq 1962726172, win 64240, options [mss 1460,sackOK,TS val 2596454800 ecr 0,nop,wscale 7], length 0
17:16:05.307713 IP x.x.x.x1.http > domain1.44338: Flags [F.], seq 215, ack 103125, win 442, options [nop,nop,TS val 2063709039 ecr 2596454794], length 0
17:16:05.313623 IP x.x.x.x1.http > domain1.44340: Flags [S.], seq 2582074627, ack 1962726173, win 62643, options [mss 1460,sackOK,TS val 2063709045 ecr 2596454800,nop,wscale 7], length 0
17:16:05.313779 IP domain1.44340 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596455001 ecr 2063709045], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:05.515156 IP domain1.44340 > x.x.x.x1.http: Flags [P.], seq 36494:39390, ack 1, win 502, options [nop,nop,TS val 2596455202 ecr 2063709246], length 2896: HTTP
17:16:05.739645 IP domain1.44340 > x.x.x.x1.http: Flags [P.], seq 68350:69798, ack 1, win 502, options [nop,nop,TS val 2596455427 ecr 2063709448], length 1448: HTTP
17:16:05.917341 IP domain1.44340 > x.x.x.x1.http: Flags [P.], seq 103102:103124, ack 1, win 502, options [nop,nop,TS val 2596455604 ecr 2063709649], length 22: HTTP
17:16:06.123141 IP x.x.x.x1.http > domain1.44340: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063709855 ecr 2596455604], length 214: HTTP: HTTP/1.1 200 OK

17:16:06.124569 IP domain1.44340 > x.x.x.x1.http: Flags [F.], seq 103124, ack 215, win 501, options [nop,nop,TS val 2596455812 ecr 2063709855], length 0
17:16:06.130364 IP domain1.44356 > x.x.x.x1.http: Flags [S], seq 3551691514, win 64240, options [mss 1460,sackOK,TS val 2596455817 ecr 0,nop,wscale 7], length 0
17:16:06.325653 IP x.x.x.x1.http > domain1.44340: Flags [F.], seq 215, ack 103125, win 442, options [nop,nop,TS val 2063710057 ecr 2596455812], length 0
17:16:06.331375 IP x.x.x.x1.http > domain1.44356: Flags [S.], seq 3143448434, ack 3551691515, win 62643, options [mss 1460,sackOK,TS val 2063710063 ecr 2596455817,nop,wscale 7], length 0
17:16:06.331580 IP domain1.44356 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596456019 ecr 2063710063], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:06.532839 IP domain1.44356 > x.x.x.x1.http: Flags [P.], seq 36494:39390, ack 1, win 502, options [nop,nop,TS val 2596456220 ecr 2063710264], length 2896: HTTP
17:16:06.733906 IP domain1.44356 > x.x.x.x1.http: Flags [P.], seq 68350:69798, ack 1, win 502, options [nop,nop,TS val 2596456421 ecr 2063710465], length 1448: HTTP
17:16:06.934842 IP domain1.44356 > x.x.x.x1.http: Flags [P.], seq 103102:103124, ack 1, win 502, options [nop,nop,TS val 2596456622 ecr 2063710666], length 22: HTTP
17:16:07.140676 IP x.x.x.x1.http > domain1.44356: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063710872 ecr 2596456622], length 214: HTTP: HTTP/1.1 200 OK

17:16:07.142071 IP domain1.44356 > x.x.x.x1.http: Flags [F.], seq 103124, ack 215, win 501, options [nop,nop,TS val 2596456829 ecr 2063710872], length 0
17:16:07.147323 IP domain1.44368 > x.x.x.x1.http: Flags [S], seq 402085581, win 64240, options [mss 1460,sackOK,TS val 2596456834 ecr 0,nop,wscale 7], length 0
17:16:07.343075 IP x.x.x.x1.http > domain1.44356: Flags [F.], seq 215, ack 103125, win 442, options [nop,nop,TS val 2063711075 ecr 2596456829], length 0
17:16:07.348425 IP x.x.x.x1.http > domain1.44368: Flags [S.], seq 2536787598, ack 402085582, win 62643, options [mss 1460,sackOK,TS val 2063711080 ecr 2596456834,nop,wscale 7], length 0
17:16:07.348648 IP domain1.44368 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596457036 ecr 2063711080], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:07.550153 IP domain1.44368 > x.x.x.x1.http: Flags [P.], seq 36494:39390, ack 1, win 502, options [nop,nop,TS val 2596457237 ecr 2063711281], length 2896: HTTP
17:16:07.751340 IP domain1.44368 > x.x.x.x1.http: Flags [P.], seq 68350:69798, ack 1, win 502, options [nop,nop,TS val 2596457438 ecr 2063711483], length 1448: HTTP
17:16:07.952350 IP domain1.44368 > x.x.x.x1.http: Flags [P.], seq 103102:103124, ack 1, win 502, options [nop,nop,TS val 2596457639 ecr 2063711684], length 22: HTTP
17:16:08.158407 IP x.x.x.x1.http > domain1.44368: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063711890 ecr 2596457639], length 214: HTTP: HTTP/1.1 200 OK

17:16:08.159502 IP domain1.44368 > x.x.x.x1.http: Flags [F.], seq 103124, ack 215, win 501, options [nop,nop,TS val 2596457847 ecr 2063711890], length 0
17:16:08.360623 IP x.x.x.x1.http > domain1.44368: Flags [F.], seq 215, ack 103125, win 442, options [nop,nop,TS val 2063712092 ecr 2596457847], length 0
1
2
3
4
5
6
7
$ python oss-muti.py --file_input=./100K.data --file_output=./100K.data --region=us --model=3 --range=5
encrypted_upload
http://domain1 upload ./100K.data, encrypt cost 1.713134765625, upload cost 1019.947265625
http://domain1 upload ./100K.data, encrypt cost 1.129638671875, upload cost 438.734375
http://domain1 upload ./100K.data, encrypt cost 0.930419921875, upload cost 268.240966796875
http://domain1 upload ./100K.data, encrypt cost 0.880615234375, upload cost 253.253662109375
http://domain1 upload ./100K.data, encrypt cost 1.1396484375, upload cost 254.03173828125
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ sudo tcpdump -i bond0 | grep x.x.x.x1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:16:58.582227 IP public1.alidns.com.domain > domain1.46151: 50311 1/0/1 A x.x.x.x1 (88)
17:16:58.582538 IP domain1.59132 > x.x.x.x1.http: Flags [S], seq 2857978823, win 64240, options [mss 1460,sackOK,TS val 2596508270 ecr 0,nop,wscale 7], length 0
17:16:58.783718 IP x.x.x.x1.http > domain1.59132: Flags [S.], seq 4037665047, ack 2857978824, win 62643, options [mss 1460,sackOK,TS val 2063762515 ecr 2596508270,nop,wscale 7], length 0
17:16:58.784028 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 1:294, ack 1, win 502, options [nop,nop,TS val 2596508471 ecr 2063762515], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:59.186612 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 42286:43734, ack 1, win 502, options [nop,nop,TS val 2596508874 ecr 2063762918], length 1448: HTTP
17:16:59.214991 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 72694:74142, ack 1, win 502, options [nop,nop,TS val 2596508902 ecr 2063762918], length 1448: HTTP
17:16:59.387945 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 101758:103124, ack 1, win 502, options [nop,nop,TS val 2596509075 ecr 2063763119], length 1366: HTTP
17:16:59.594321 IP x.x.x.x1.http > domain1.59132: Flags [P.], seq 1:215, ack 103124, win 442, options [nop,nop,TS val 2063763326 ecr 2596509075], length 214: HTTP: HTTP/1.1 200 OK

17:16:59.600269 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 103124:103417, ack 215, win 501, options [nop,nop,TS val 2596509288 ecr 2063763326], length 293: HTTP: POST /upload/files HTTP/1.1
17:16:59.616693 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 141065:142513, ack 215, win 501, options [nop,nop,TS val 2596509304 ecr 2063763326], length 1448: HTTP
17:16:59.807008 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 171284:172921, ack 215, win 501, options [nop,nop,TS val 2596509494 ecr 2063763538], length 1637: HTTP
17:16:59.828692 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 206225:206247, ack 215, win 501, options [nop,nop,TS val 2596509516 ecr 2063763560], length 22: HTTP
17:17:00.034796 IP x.x.x.x1.http > domain1.59132: Flags [P.], seq 215:429, ack 206247, win 1079, options [nop,nop,TS val 2063763766 ecr 2596509516], length 214: HTTP: HTTP/1.1 200 OK

17:17:00.038874 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 206247:206540, ack 429, win 501, options [nop,nop,TS val 2596509726 ecr 2063763766], length 293: HTTP: POST /upload/files HTTP/1.1
17:17:00.080191 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 281836:283284, ack 429, win 501, options [nop,nop,TS val 2596509768 ecr 2063763766], length 1448: HTTP
17:17:00.098087 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 309348:309370, ack 429, win 501, options [nop,nop,TS val 2596509786 ecr 2063763766], length 22: HTTP
17:17:00.304214 IP x.x.x.x1.http > domain1.59132: Flags [P.], seq 429:643, ack 309370, win 2029, options [nop,nop,TS val 2063764036 ecr 2596509786], length 214: HTTP: HTTP/1.1 200 OK

17:17:00.308554 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 309370:309663, ack 643, win 501, options [nop,nop,TS val 2596509996 ecr 2063764036], length 293: HTTP: POST /upload/files HTTP/1.1
17:17:00.349857 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 412471:412493, ack 643, win 501, options [nop,nop,TS val 2596510037 ecr 2063764036], length 22: HTTP
17:17:00.558243 IP x.x.x.x1.http > domain1.59132: Flags [P.], seq 643:857, ack 412493, win 3590, options [nop,nop,TS val 2063764290 ecr 2596510037], length 214: HTTP: HTTP/1.1 200 OK

17:17:00.563952 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 412493:412786, ack 857, win 501, options [nop,nop,TS val 2596510251 ecr 2063764290], length 293: HTTP: POST /upload/files HTTP/1.1
17:17:00.605371 IP domain1.59132 > x.x.x.x1.http: Flags [P.], seq 515594:515616, ack 857, win 501, options [nop,nop,TS val 2596510293 ecr 2063764290], length 22: HTTP
17:17:00.813565 IP x.x.x.x1.http > domain1.59132: Flags [P.], seq 857:1071, ack 515616, win 5197, options [nop,nop,TS val 2063764545 ecr 2596510293], length 214: HTTP: HTTP/1.1 200 OK

17:17:00.832862 IP domain1.59132 > x.x.x.x1.http: Flags [F.], seq 515616, ack 1071, win 501, options [nop,nop,TS val 2596510520 ecr 2063764545], length 0
17:17:01.033981 IP x.x.x.x1.http > domain1.59132: Flags [F.], seq 1071, ack 515617, win 5197, options [nop,nop,TS val 2063764765 ecr 2596510520], length 0
  • 首先可以明显看出,复用连接后续的 P 包传输数量明显减少,且对应业务打印的时间。包减少了,文件没变小,只能说明传输本身变大了。这时,TCP 的窗口、拥塞的知识开始从我的脑海中复活。
  • 具体完整窗口变大可以自己进行尝试。可以明显看到,tcp 中,客户端单次发送的数据包逐步增加。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 朴素思想中的不复用连接传包
1. [S][P][P][P][P][F]
2.                [S][P][P][P][P][F]
3.                               [S][P][P][P][P][F]
# 朴素思想中的复用连接传包
1. [S][P][P][P][P]
2.                [P][P][P][P]
3.                            [P][P][P][P][F]
# 实际传包
1. [S][p][p][p][p]
2.                {P}{P}
3.                      {P}{P}[F]

Tcp 窗口适应是指 TCP 根据网络状况动态调整发送和接收窗口的大小,以达到最优的传输效率。TCP 窗口适应涉及到以下几个方面

  1. 接收窗口:接收方通告给发送方的可接收数据的字节数,用于进行流量控制,避免发送方发送过快导致接收方缓冲区溢出。
  2. 拥塞窗口:发送方根据网络拥塞程度自行维护的可发送数据的字节数,用于进行拥塞控制,避免发送方发送过快导致网络拥塞。
  3. 滑动窗口:发送方根据接收窗口和拥塞窗口的较小值确定的可发送数据的字节数,用于进行滑动窗口协议,保证数据的有序和可靠传输。
  4. 窗口缩放:TCP 头部选项中的一种,用于扩展接收窗口的大小,允许接收方通告超过 65535 字节的窗口值,以适应高速网络。
  5. 慢启动:拥塞控制算法中的一种,用于在连接建立后或发生超时重传后,将拥塞窗口初始化为一个较小的值(通常为 1 个 MSS),然后每收到一个 ACK 就将拥塞窗口加 1 个 MSS,使得拥塞窗口呈指数增长,直到达到一个慢启动门限 1(ssthresh)或发生丢包。
  6. 拥塞避免:拥塞控制算法中的一种,用于在拥塞窗口达到慢启动门限后,将拥塞窗口改为每经过一个 RTT 就加 1 个 MSS,使得拥塞窗口呈线性增长,直到发生丢包。
  7. 快速重传:重传机制中的一种,用于在收到三个相同的 ACK 后,不等待超时定时器到期就立即重传丢失的报文段。
  8. 快速恢复:拥塞控制算法中的一种,用于在发生快速重传后,将慢启动门限设为当前拥塞窗口的一半,并将拥塞窗口设为慢启动门限加三个 MSS(对应三个重复 ACK),然后进入拥塞避免阶段。

连接池,都有优化哪些?

  1. 预创建连接,减少了使用时的创建销毁消耗。
  2. 复用连接,减少了连接本身的创建和销毁。
  3. 根据网络协议和网络现状,优化传输效率