Unix Like, VPN, 网络

TCP Sendbuffer Size与RTT的问题

最近从A服务器下载数据时,发现如果走B服务器的VPN下载,速率只能跑到300KB左右,但是B从A直接下载却能跑到1MB+/s,B到本地的速度也远超过A到B的速度,其实一开始我以为是VPN实现的问题,有段时间在思考如何优化VPN,但是尝试了其它VPN实现,问题并没有解决。后来发现,走B的代理而不是VPN,速度正常。

本地到B的RTT大约160ms,B到A大约50ms。

Wireshark抓包,对tcp sequence number统计了下:

放大点看:

大概每传输60KB,就要等大约200ms才能继续。200ms刚好差不多等于本地走VPN到A的RTT。传这60KB,只花了大概10ms,忽略这10ms不算的话,每秒大概只能接收五次60KB,5*60KB=300KB,刚好接近走VPN的下载速度。

TCP要发送的数据包存放在send buffer中,send buffer已使用的空间,在收到ACK前是不能释放的,所以,如果这时send buffer满了而未收到ACK,那kernel就不会继续对外发送数据。

所以,走VPN慢的原因,是因为A设定的的send buffer太小,在本地发出的ACK送达A前,A的send buffer就满了。走B代理快,是因为B到A的RTT比较小,ACK是由B上的代理程序在接收到数据后发送给A的,所以A很快就能收到ACK而继续向B发送数据,B到本地没有send buffer过小的问题,所以B上的代理往本地发回数据的速率几乎与A到B的速率一致。