TCP 连接的时间开销(一)

在互联⽹后端⽇常开发接⼝的时候中,不管你使⽤的是C、Java、PHP还是Golang,都避免不了需要调⽤mysql、redis等组件来获取数据,可能还需要执⾏⼀些rpc远程调⽤,或者再调⽤⼀些其它restful api。 在这些调⽤的底层,基本都是在使⽤TCP协议进⾏传输。这是因为在传输层协议中,TCP协议具备可靠的连接,错误重传,拥塞控制等优点,所以⽬前应⽤⽐UDP更⼴泛⼀些。

相信你也⼀定听闻过TCP也存在⼀些缺点,那就是⽼⽣常谈的开销要略⼤。但是各路技术博客⾥都在单单说开销⼤、或者开销⼩,⽽少⻅不给出具体的量化分析。不客⽓⼀点,这都是营养不⼤的废话。经过⽇常⼯作的思考之后,我更想弄明⽩的是,开销到底多⼤。⼀条TCP连接的建⽴需要耗时延迟多少,是多少毫秒,还是多少微秒?能不能有⼀个哪怕是粗略的量化估计?当然影响TCP耗时的因素有很多,⽐如⽹络丢包等等。我今天只分享我在⼯作实践中遇到的⽐较⾼发的各种情况。

正常TCP连接建⽴过程

要想搞清楚TCP连接的建⽴耗时,我们需要详细了解连接的建⽴过程。在前⽂《Linux网络收包流程》中我们介绍了数据包在接收端是怎么被接收的。数据包从发送⽅出来,经过络到达接收⽅的⽹卡。在接收⽅⽹卡将数据包DMA到RingBuffer后,内核经过硬中断、软中断等机制来处理(如果发送的是⽤户数据的话,最后会发送到socket的接收队列中,并唤醒⽤户进程)。
在这里插入图片描述
在软中断中,当⼀个包被内核从RingBuffer中摘下来的时候,在内核中是⽤ struct sk_buff结构体来表示的(参⻅内核代码 include/linux/skbuff.h )。其中的data成员是接收到的数据,在协议栈逐层被处理的时候,通过修改指针指向data的不同位置,来找到每⼀层协议关⼼的数据。
在这里插入图片描述
对于TCP协议包来说,它的Header中有⼀个重要的字段-flags。如下图:
在这里插入图片描述
通过设置不同的标记为,将TCP包分成SYNC、FIN、ACK、RST等类型。客户端通过connect系统调⽤命令内核发出SYNC、ACK等包来实现和服务器TCP连接的建⽴。在服务器端,可能会接收许许多多的连接请求,内核还需要借助⼀些辅助数据结构-半连接队列和全连接队列。我们来看⼀下整个连接过程:
在这里插入图片描述
在这个连接过程中,我们来简单分析⼀下每⼀步的耗时

  • 客户端发出SYNC包:客户端⼀般是通过connect系统调⽤来发出SYN的,这⾥牵涉到本机的系统调⽤和软中断的CPU耗时开销
  • SYN传到服务器:SYN从客户端⽹卡被发出,开始“跨过⼭和⼤海,也穿过⼈⼭⼈海~~~”,这是⼀次⻓途远距离的⽹络传输
  • 服务器处理SYN包:内核通过软中断来收包,然后放到半连接队列中,然后再发出SYN/ACK响应。⼜是CPU耗时开销
  • SYC/ACK传到客户端:SYC/ACK从服务器端被发出后,同样跨过很多⼭、可能很多⼤海来到客户端。⼜⼀次⻓途⽹络跋涉
  • 客户端处理SYN/ACK:客户端内核收包并处理SYN后,经过⼏us的CPU处理,接着发出ACK。同样是软中断处理开销
  • ACK传到服务器:和SYN包,⼀样,再经过⼏乎同样远的路,传输⼀遍。 ⼜⼀次⻓途⽹络跋涉
  • 服务端收到ACK:服务器端内核收到并处理ACK,然后把对应的连接从半连接队列中取出来,然后放到全连接队列中。⼀次软中断CPU开销
  • 服务器端⽤户进程唤醒:正在被accpet系统调⽤阻塞的⽤户进程被唤醒,然后从全连接队列中取出来已经建⽴好的连接。⼀次上下⽂切换的CPU开销

以上⼏步操作,可以简单划分为两类:

  • 第⼀类是内核消耗CPU进⾏接收、发送或者是处理,包括系统调⽤、软中断和上下⽂切换。它们的耗时基本都是⼏个us左右。
  • 第⼆类是⽹络传输,当包被从⼀台机器上发出以后,中间要经过各式各样的⽹线、各种交换机路由器。所以⽹络传输的耗时相⽐本机的CPU处理,就要⾼的多了。根据⽹络远近⼀般在⼏ms~到⼏百ms不等。。

1ms就等于1000us,因此⽹络传输耗时⽐双端的CPU开销要⾼1000倍左右,甚⾄更⾼可能还到100000倍。所以,在正常的TCP连接的建⽴过程中,⼀般可以考虑⽹络延时即可。⼀个RTT指的是包从⼀台服务器到另外⼀台服务器的⼀个来回的延迟时间。所以从全局来看,TCP连接建⽴的⽹络耗时⼤约需要三次传输,再加上少许的双⽅CPU开销,总共⼤约⽐1.5倍RTT⼤⼀点点。不过从客户端视⻆来看,只要ACK包发出了,内核就认为连接是建⽴成功了。所以如果在客户端打点统计TCP连接建⽴耗时的话,只需要两次传输耗时-既1个RTT多⼀点的时间。(对于服务器端视⻆来看同理,从SYN包收到开始算,到收到ACK,中间也是⼀次RTT耗时)

[推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值