TCP个人笔记及链接相关问题排查

177 阅读5分钟

这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

我们最常用的应用层协议http都是依赖传输层tcp协议完成的。

同时很多client-server模式的软件(中间件)大都使用tcp通信,因此详细的了解tcp通信裨益极大。

首先对网络模型先进行一个介绍。

应用层,表示层,会话层,传输层,网络层,数据链路层,物理层7层网络模型大家已经熟知。

http就属于应用层,将应用层数据进行传输,会进行tcp首部的拼接,

TCP传输控制协议

tcp的序号记录了传输内容的大小(单位字节)

小结

TCP提供了一种可靠的面向连接的字节流运输层服务。我们简单地介绍了T C P首部中的各 个字段,并在随后的几章里详细讨论它们。 T C P将用户数据打包构成报文段;它发送数据后启动一个定时器;另一端对收到的数据 进行确认,对失序的数据重新排序,丢弃重复数据; T C P提供端到端的流量控制,并计算和 验证一个强制性的端到端检验和。

TCP连接的建立与终止

建立与终止

这里写图片描述

这里写图片描述 TCP的状态是非常重要,可以帮助我们快速定位问题。 在工作中我曾经遇到服务在流量高峰期导致服务重启的事情。 表因是服务处理变慢,请求变多,导致tomcat线程打满,导致服务不可用。 但服务接口变慢的原因查了好久都没查到,只通过监控,看到redis的请求变多变慢。 发现服务里确实会对几个高流量接口使用redis set下相关记录。但redis server本身并没有慢日志。 也怀疑过序列化的问题。 但最后发现是redis 链接池参数设计的不合理,maxidle=0,导致空闲线程会被kill掉。所以高峰请求时,很多都是新建连接,连接池其实没有作用。当时也发现系统里有很多TIME_WAIT的TCP链接。修改maxidle到一个合理值之后,发现高峰系统的TIME_WAIT连接也很少。 默认的TIME_WAIT需要60S后,才会真的被kill掉

TCP服务器设计

大多数的T C P服务器进程是并发的。当一个新的连接请求到达服务器时, 服务器接受这个请求,并调用一个新进程来处理这个新的客户请求。不同的操作系统使用不 同的技术来调用新的服务器进程。在U n i x系统下,常用的技术是使用f o r k函数来创建新的进 程。如果系统支持,也可使用轻型进程,即线程( t h r e a d)。

呼入连接请求队列

一个并发服务器调用一个新的进程来处理每个客户请求,因此处于被动连接请求的服务 器应该始终准备处理下一个呼入的连接请求。那正是使用并发服务器的根本原因。但仍有可 能出现当服务器在创建一个新的进程时,或操作系统正忙于处理优先级更高的进程时,到达 多个连接请求。当服务器正处于忙时, T C P是如何处理这些呼入的连接请求?

因此引入了固定长度的连接队列,应用层会指明队列的最大长度,这个值通常称为积压值。

TCP的成块数据流

滑动窗口是每唯一的连接占用的。

tcp每一次发送的报文按照mss的大小进行分割(IP层),发送和接受端的缓冲指的就是滑动窗口的大小。(20.2 正常数据流中的实例,将报文和滑动窗口的作用解释的很明白了)

tcp粘包是因为tcp基于流的传输且收发两端存在缓存区,客户端和服务端的缓冲器不是分组的队列,而是字节的队列,这意味着,即使将两个消息作为两个独立的数据包发送,操作系统也不会将它们视为两个消息,而只是一组字节;并且由于缓冲区及报文最大长度(mss)的存在,数据发送次数不确定的(毕竟每组消息的长度也不确定),这就造成两个独立数据包之间数据的粘包。

粘包demo

PUSH标志表示该消息需直接交付给接受进程,并且该标志在发送端并没有开放出api。

慢启动

发送方一开始便向网络发送多个报文段,直至达到接 收方通告的窗口大小为止。当发送方和接收方处于同一个局域网时,这种方式是可以的。但 是如果在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。 一些中间路由器必须缓存分组,并有可能耗尽存储器的空间。[Jacobson 1988]证明了这种连 接方式是如何严重降低了T C P连接的吞吐量的。 现在,T C P需要支持一种被称为“慢启动(slow start)”的算法。该算法通过观察到新分组 进入网络的速率应该与另一端返回确认的速率相同而进行工作。 慢启动为发送方的T C P增加了另一个窗口:拥塞窗口(congestion window),记为c w n d。

PS:该篇是TCP/IP协议卷一的读书笔记,因此文中引用了很多书中的话。