当前位置:首页>Linux>网络延迟的元凶:Linux内核协议栈排查实战

网络延迟的元凶:Linux内核协议栈排查实战

  • 2026-02-04 19:23:16
网络延迟的元凶:Linux内核协议栈排查实战

在高并发、低时延的网络场景中,Linux系统凭借稳定的内核性能成为主流选择,但网络延迟问题却常成为业务瓶颈的“隐形元凶”。多数时候,延迟并非源于硬件故障或应用层逻辑,而是深埋于Linux内核协议栈的细微环节——从数据包接收的中断处理、软中断调度,到TCP/UDP协议的状态流转、队列管理,每一处微小的配置偏差或机制瓶颈,都可能导致延迟累积,引发业务响应迟缓、吞吐量下降等问题。

面对这类隐蔽性强、涉及底层原理的故障,盲目排查如同大海捞针。唯有深入理解Linux内核协议栈的工作机制,掌握针对性的排查工具与实战技巧,才能精准定位延迟根源。本文将从内核协议栈的核心流程出发,拆解延迟产生的关键节点,结合实际案例分享tcpdump、ss、perf等工具的实操方法,带大家穿透协议栈黑盒,高效揪出延迟元凶,为业务网络性能优化筑牢底层根基。

一、Linux 内核网络协议栈初相识

Linux 内核网络协议栈,简单来说,是一组实现网络通信功能的软件模块集合,它如同一个精密而复杂的通信中枢,被嵌入到 Linux 操作系统的内核之中。从系统架构的角度看,它位于应用程序与网络硬件设备之间,充当着两者沟通的关键桥梁 。当我们在浏览器中输入网址访问网页时,应用程序会将访问请求传递给 Linux 内核网络协议栈,协议栈就开始了一系列忙碌而有序的工作。

它会按照网络通信的规则,对数据进行层层封装,添加各种必要的网络协议头部信息,将数据打包成适合在网络中传输的格式,然后再将这些数据包传递给网络硬件设备(如网卡),由硬件设备将数据发送到网络上。而当网卡接收到来自网络的数据时,又会将数据传递给协议栈,协议栈则进行相反的操作,对数据包进行解封装,层层解析出原始的数据,最终将数据递交给相应的应用程序,使得我们能够顺利地看到网页的内容。

从技术层面深入剖析,Linux 内核网络协议栈严格遵循网络分层架构,其设计如同一个精密协作的模块化系统。每一层在数据通信过程中承担着特定的封装与分用职责:网络接口层负责帧的封装与解封装;网络层(IP层)处理IP数据报的路由、分片与重组;传输层(如TCP/UDP)实现端到端的连接管理、可靠传输或数据报分发;而最终应用层则完成用户数据的组包与解析。这种层次化的封装与分用机制,确保了数据在网络中能够高效、可靠地逐层传递,同时保持了各层的独立性与可扩展性。

数据报文的封装与分用,正是网络协议栈分层架构的核心体现。接下来,我们将逐层剖析这一过程在Linux内核中如何具体实现:

【1】封装(发送数据时):当应用程序通过 TCP 协议发送数据时,会经历一个自顶向下、逐层添加协议头部的“打包”过程:

  1. 起点: 数据从应用程序进入操作系统内核的网络协议栈。
  2. TCP层: 首先,传输层 TCP 协议将应用数据封装成 TCP 报文段(TCP Segment),添加了 TCP 头部(包含源/目的端口、序列号等信息)。
  3. IP层: 接着,网络层 IP 协议将 TCP 报文段封装成 IP 数据报(IP Datagram),添加了 IP 头部(包含源/目的 IP 地址等信息)。
  4. 链路层: 然后,数据链路层(如以太网)将 IP 数据报封装成 帧(Frame),添加了帧头部和尾部(包含 MAC 地址、校验和等信息)。
  5. 终点: 最终,这个完整的帧被转换成一串比特流,通过物理网络(如网线、Wi-Fi)发送出去。

【2】分用(接收数据时):当目标主机通过网络收到一串比特流后,会经历一个自底向上、逐层剥离协议头部的“解包”过程:

  1. 起点: 网卡接收到比特流,将其组装成一个完整的链路层帧。
  2. 链路层: 数据链路层检查帧的头部。如果目的 MAC 地址匹配,它就剥去帧头和帧尾,将内部的 IP 数据报向上传递给网络层。
  3. IP层: IP协议检查IP数据报的头部。如果目的IP地址匹配且校验正确,它就剥去IP头,根据其内部的“上层协议标识”(如值为6代表TCP),将载荷(即TCP报文段)向上传递给相应的传输层协议。
  4. TCP层: TCP协议检查TCP报文段的头部。根据目的端口号等信息找到对应的应用程序套接字或进程。
  5. 终点: TCP剥去TCP头后,将原始的纯应用数据交付给目标应用程序。

二、深入剖析协议栈架构

为精准深入剖析协议栈架构,我们先以协议栈全景图为核心参照,清晰锚定各层级的定位与关联,下文将基于这一全景视角,逐层拆解架构逻辑与核心特性。

2.1分层结构详解

Linux 内核网络协议栈采用了精妙的分层结构设计,这种分层架构就像一座功能完备的大厦,每一层都有其独特的职责,并且相互协作,共同保障网络通信的顺畅进行 。

  1. 系统调用接口层:这一层就像是一扇通往网络世界的大门,是面向用户空间应用程序的接口调用库,它为应用程序提供了使用网络服务的便捷通道。当我们在浏览器中输入网址发起访问请求,或者通过即时通讯软件发送消息时,应用程序会通过系统调用接口层,向内核网络子系统传达指令。它支持诸如 socket ()、connect ()、send ()、recv () 等一系列系统调用函数。以 socket () 函数为例,应用程序调用它来创建一个套接字,这个套接字就像是一个网络通信的端点,后续的网络数据收发等操作都基于此进行。系统调用接口层就像是一个翻译官,将应用程序的 “语言”(函数调用)准确无误地传达给内核网络子系统,使得应用程序能够与网络协议栈进行交互 。
  2. 协议无关的接口层(SOCKET 层):SOCKET 层宛如一个智能的抽象层,它的主要职责是屏蔽底层不同协议的差异,让应用层能够以统一、简洁的方式使用网络服务 。在网络世界中,存在着多种不同的协议族,如 TCP/IP v4、TCP/IP v6、Netlink、Unix 等。SOCKET 层为这些不同的协议族提供了一个通用的接口,使得应用程序无需关心底层具体使用的是哪种协议,只需要通过 SOCKET 层提供的接口进行操作即可。当我们创建一个 socket 时,通过传入不同的参数,就可以指定使用的协议族和 socket 类型。例如,socket (int domain, int type, int protocol) 函数,第一个参数 domain 可以指定为 AF_INET 表示使用 IPv4 协议族,AF_INET6 表示使用 IPv6 协议族;第二个参数 type 可以指定为 SOCK_STREAM 表示使用流式套接字(通常对应 TCP 协议),SOCK_DGRAM 表示使用用户数据报套接字(通常对应 UDP 协议)。这样,无论底层使用何种协议,应用层都可以通过统一的 socket 接口进行网络通信,大大提高了代码的通用性和可移植性 。
  3. 网络协议实现层:这一层是整个协议栈的核心所在,如同大厦的支柱,承担着实现各种主要网络协议的重任,其中最为重要的包括 IP(网际协议)、TCP(传输控制协议)、UDP(用户数据报协议)等 。IP 协议负责网络层的地址管理和数据包的路由转发,它就像是网络世界中的 “交通警察”,根据数据包的目的 IP 地址,为数据包规划传输路径,确保数据包能够准确无误地到达目标网络。例如,当我们的电脑向服务器发送一个数据包时,IP 协议会根据目标服务器的 IP 地址,在网络中查找合适的路由,将数据包发送到下一跳。TCP 协议则专注于提供可靠的、面向连接的数据传输服务,它通过三次握手建立连接,在数据传输过程中使用确认机制、重传机制和流量控制机制,确保数据能够完整、有序地到达接收方 。比如在文件传输场景中,TCP 协议能够保证文件的每个字节都准确无误地传输到目标设备,不会出现数据丢失或乱序的情况。UDP 协议则提供了一种简单的、不可靠的、无连接的数据传输服务,它的优势在于传输速度快、开销小,常用于对实时性要求较高但对数据准确性要求相对较低的场景,如视频直播、语音通话等。在视频直播中,偶尔丢失一些数据包可能只会导致短暂的画面卡顿,但不会影响整体的观看体验,此时 UDP 协议就能够发挥其高效传输的优势 。
  4. 与具体设备无关的驱动接口层:该层是连接网络协议层和设备驱动层的桥梁,它的作用是统一不同驱动程序与网络协议层的接口 。网络设备种类繁多,不同的设备可能来自不同的厂商,其硬件特性和驱动程序也各不相同。如果没有这一层的抽象,网络协议层与设备驱动层之间的交互将会变得异常复杂,每个网络协议都需要适配各种不同的设备驱动,这无疑会增加系统的复杂性和开发成本。有了与具体设备无关的驱动接口层,它将各种不同设备驱动的功能统一抽象为几个通用的操作,如 open(打开设备)、close(关闭设备)、init(初始化设备)等。这样,网络协议层只需要与这一层进行交互,而无需关心底层具体设备驱动的细节,大大提高了系统的可扩展性和兼容性 。
  5. 驱动程序层:这是协议栈与硬件设备直接交互的一层,它负责建立与硬件的接口,实现数据的物理传输 。以网卡为例,网卡驱动程序就位于这一层,它就像是硬件设备的 “翻译”,将上层传递下来的数据转换为硬件设备能够理解的电信号或光信号,通过物理线路发送出去;同时,它也将从硬件设备接收到的电信号或光信号转换为数据,传递给上层协议栈进行处理 。当我们的电脑接收到来自网络的数据时,网卡驱动程序会首先捕获这些数据,然后将其传递给与具体设备无关的驱动接口层,进而传递到网络协议实现层进行后续处理。驱动程序层的性能和稳定性直接影响着网络通信的质量,一个高效、稳定的驱动程序能够确保数据的快速、准确传输 。

2.2各层交互机制

当应用层有数据需要发送时,数据首先通过系统调用接口层进入内核空间,然后传递到协议无关的接口层(SOCKET 层)。在 SOCKET 层,数据会根据具体的协议类型(如 TCP 或 UDP),被进一步传递到网络协议实现层。网络协议实现层会根据协议的规则,对数据进行封装,添加相应的协议头部信息。

例如,TCP 协议会添加 TCP 头部,包含源端口、目的端口、序列号、确认号等信息;IP 协议会添加 IP 头部,包含源 IP 地址、目的 IP 地址等信息 。封装好的数据接着被传递到与具体设备无关的驱动接口层,该层将数据传递给驱动程序层。驱动程序层将数据转换为适合物理网络设备传输的格式,通过物理网络设备(如网卡)将数据发送到网络上 。

当物理网络设备接收到数据时,数据的传递过程则相反。首先,数据由驱动程序层接收,然后传递到与具体设备无关的驱动接口层。接着,数据进入网络协议实现层,在这一层,协议头部被逐步解析和处理,根据协议类型(如 TCP 或 UDP),将数据传递到相应的协议模块进行处理 。例如,TCP 模块会检查序列号、确认号等信息,确保数据的完整性和顺序性;UDP 模块则简单地将数据报传递到上一层。处理后的数据再经过协议无关的接口层(SOCKET 层),最终通过系统调用接口层返回给应用层 。

在整个过程中,各层之间紧密协作,通过定义良好的接口和规范进行数据传递和交互。每一层都专注于自己的职责,通过层层协作,实现了高效、可靠的网络通信 。这种分层架构和交互机制,使得 Linux 内核网络协议栈具有良好的可扩展性和维护性,能够适应不断发展的网络技术和应用需求 。

2.3关键协议解析

(1)TCP 协议深度解读

①三次握手建立连接:TCP 建立连接的过程如同一场严谨的对话,通过三次握手来确保双方都准备好进行可靠的数据传输 。

  1. 客户端首先发起请求,它向服务器发送一个带有 SYN(同步)标志位的数据包,这个数据包就像是一封 “介绍信”,其中包含了客户端随机生成的初始序列号(ISN),比如设为 x。此时,客户端进入 SYN_SENT 状态,就像一个人在等待对方回应的信件,焦急地盼望着服务器的回复 。
  2. 服务器接收到客户端的 SYN 数据包后,会立即做出响应。它回复一个 SYN + ACK 数据包,这个数据包是对客户端请求的双重回应 。一方面,它通过 ACK 标志位确认收到了客户端的 SYN 数据包,并将客户端的序列号 x 加 1,作为确认号(ack = x + 1)返回给客户端,就像是在回信中说 “我已经收到你的信了,期待你接下来的内容”;另一方面,服务器也会生成自己的初始序列号,假设为 y,将其放入 SYN 字段中发送给客户端 。此时,服务器进入 SYN_RECV 状态,它也在等待客户端的进一步确认 。
  3. 客户端收到服务器的 SYN + ACK 数据包后,会再次发送一个 ACK 数据包作为最后的确认 。这个 ACK 数据包的确认号为服务器的序列号 y 加 1(ack = y + 1),表示客户端已经收到了服务器的回复,并且准备好开始数据传输 。此时,客户端和服务器都进入 ESTABLISHED 状态,连接正式建立,就像两个人终于成功地约定好了见面的时间和地点,可以开始愉快地交流了 。

②四次挥手断开连接:当数据传输完成后,TCP 连接需要被优雅地断开,这一过程通过四次挥手来实现 。

  1. 主动关闭方(假设为客户端)首先发起断开请求,它向被动关闭方(服务器)发送一个 FIN(结束)标志位的数据包,表示客户端已经没有数据要发送了,就像在说 “我已经说完我的话了,准备结束这次交流” 。此时,客户端进入 FIN_WAIT_1 状态,等待服务器的确认 。
  2. 服务器收到客户端的 FIN 数据包后,会立即回复一个 ACK 数据包,确认收到了客户端的断开请求,它将客户端的序列号加 1 作为确认号返回(ack = u + 1,u 为客户端 FIN 数据包的序列号) 。服务器进入 CLOSE_WAIT 状态,此时服务器可以继续处理还未发送完的数据 。
  3. 当服务器处理完所有数据后,它也会向客户端发送一个 FIN 数据包,表示服务器也准备好断开连接了,就像在说 “我也说完了,我们可以结束了” 。服务器进入 LAST_ACK 状态,等待客户端的最后确认 。
  4. 客户端收到服务器的 FIN 数据包后,会发送一个 ACK 数据包作为最后的确认,确认号为服务器 FIN 数据包的序列号加 1(ack = w + 1,w 为服务器 FIN 数据包的序列号) 。此时,客户端进入 TIME_WAIT 状态,经过一段时间(通常为 2 倍的 MSL,即 Maximum Segment Lifetime,最长报文段寿命)后,客户端才会真正进入 CLOSED 状态,彻底关闭连接 。而服务器在收到客户端的 ACK 数据包后,会立即进入 CLOSED 状态 。TIME_WAIT 状态的存在是为了确保客户端发送的最后一个 ACK 数据包能够到达服务器,如果这个 ACK 数据包丢失,服务器会重发 FIN 数据包,客户端在 TIME_WAIT 状态下可以重新发送 ACK 数据包,从而保证连接的可靠关闭 。

③TCP 协议可靠性保障机制

  1. 确认与重传机制:确认机制是 TCP 可靠性的基石之一 。在数据传输过程中,每一个发送出去的数据包都有一个对应的序列号 。接收方在收到数据包后,会根据序列号对数据包进行排序,并通过 ACK(确认)数据包告知发送方哪些数据包已经成功接收 。发送方在发送数据包后,会启动一个定时器,如果在规定的时间内没有收到对应的 ACK 确认,就会认为数据包可能丢失或损坏,从而重发该数据包 。这种确认与重传机制就像我们寄快递时,对方收到快递后会给我们发一个签收确认,如果我们长时间没有收到签收确认,就会重新寄一次,确保快递能够准确送达 。例如,在文件传输过程中,发送方将文件分成多个数据包依次发送,接收方每收到一个数据包,都会发送一个 ACK 确认,发送方只有收到所有数据包的 ACK 确认,才会认为文件传输成功 。如果某个数据包的 ACK 确认超时未收到,发送方就会重发该数据包,直到收到确认为止 。
  2. 流量控制机制:流量控制机制是为了防止发送方发送数据过快,导致接收方来不及处理而造成数据丢失 。TCP 通过滑动窗口机制来实现流量控制 。接收方会在 ACK 数据包中告诉发送方自己当前的接收窗口大小,这个窗口大小表示接收方当前还能接收多少数据 。发送方会根据接收方的窗口大小来调整自己的发送速率,确保不会超过接收方的处理能力 。例如,接收方的接收窗口大小为 1000 字节,发送方在发送数据时,会确保一次性发送的数据量不超过 1000 字节 。如果接收方的处理能力下降,它会减小接收窗口大小,并通过 ACK 数据包通知发送方,发送方会相应地降低发送速率,从而避免数据丢失 。
  3. 拥塞控制机制:拥塞控制机制是 TCP 为了应对网络拥塞而设计的重要机制 。当网络出现拥塞时,如果所有的发送方都继续以高速率发送数据,会导致网络拥塞进一步恶化 。TCP 的拥塞控制机制通过动态调整发送方的拥塞窗口大小来控制数据发送速率 。它主要包括慢启动、拥塞避免、快重传和快恢复等阶段 。在慢启动阶段,发送方从一个较小的拥塞窗口开始发送数据,每收到一个 ACK 确认,就将拥塞窗口大小加 1,这样拥塞窗口的增长速度呈指数级增长 。当拥塞窗口大小达到一个阈值(ssthresh)时,进入拥塞避免阶段,此时拥塞窗口的增长速度变为线性增长,每收到一个 ACK 确认,只将拥塞窗口大小增加 1/cwnd(cwnd 为当前拥塞窗口大小) 。如果发送方收到三个重复的 ACK 确认,就会认为某个数据包可能丢失,但网络还没有拥塞,此时会进入快重传阶段,立即重传丢失的数据包,并将阈值 ssthresh 减半,同时进入快恢复阶段,将拥塞窗口大小设置为 ssthresh 加上 3 个最大段大小(MSS),然后继续以线性增长的方式调整拥塞窗口大小 。通过这些机制,TCP 能够在网络拥塞时,有效地降低数据发送速率,缓解网络拥塞,确保网络的稳定运行 。例如,在网络高峰期,大量用户同时进行数据传输,网络可能会出现拥塞 。此时,TCP 的拥塞控制机制会自动调整发送方的发送速率,避免网络拥塞进一步加剧,保证每个用户都能获得一定的网络带宽 。

(2)UDP 协议特点与应用

UDP(User Datagram Protocol,用户数据报协议)是一种与 TCP 截然不同的传输层协议,它具有独特的特点,使其在某些特定的应用场景中发挥着重要作用 。UDP 是一种无连接的协议,这意味着在数据传输之前,UDP 不需要像 TCP 那样进行繁琐的三次握手来建立连接,也不需要在数据传输结束后进行四次挥手来断开连接 。这种无连接的特性使得 UDP 的传输过程非常简单、直接,就像我们发送短信一样,无需事先与对方建立通话连接,直接将短信发送出去即可 。这使得 UDP 在数据传输时能够快速地将数据包发送到网络上,大大减少了传输延迟,提高了传输效率 。

UDP 不保证数据传输的可靠性,它不会像 TCP 那样对每个数据包进行确认和重传,也没有流量控制和拥塞控制机制 。在 UDP 的数据传输过程中,数据包可能会因为网络拥塞、链路故障等原因而丢失、重复或乱序到达接收方 。但在一些对实时性要求极高的场景中,如视频流、实时游戏等,少量的数据丢失或乱序可能并不会对整体的应用体验造成太大的影响 。例如,在观看在线视频时,偶尔丢失几个数据包可能只会导致画面出现短暂的卡顿,但很快就会恢复正常,用户仍然能够流畅地观看视频 。

由于 UDP 无需建立连接和进行复杂的可靠性保障机制,它的传输速度相对较快 。在传输相同大小的数据时,UDP 的传输开销要比 TCP 小得多,因为 UDP 数据包的头部相对简单,只包含源端口、目的端口、长度和校验和等基本信息,而 TCP 数据包的头部则包含了更多的控制信息 。这使得 UDP 在需要快速传输大量数据的场景中具有明显的优势 。

基于 UDP 的这些特点,它在以下应用场景中得到了广泛的应用 :

  • 视频流传输:在视频直播、在线视频播放等场景中,实时性是至关重要的 。用户希望能够尽快看到视频内容,而对于少量的数据丢失或画面的短暂卡顿,通常是可以接受的 。UDP 的快速传输特性和无连接的特点,使得它能够快速地将视频数据传输到用户的设备上,满足用户对实时性的要求 。例如,在一些热门的短视频平台和在线直播平台,大量的视频数据都是通过 UDP 协议进行传输的,用户能够在短时间内加载并观看视频,获得流畅的观看体验 。
  • 实时游戏:实时游戏对网络延迟和响应速度的要求极高,玩家需要及时地将自己的操作指令发送到游戏服务器,同时也需要快速地接收服务器返回的游戏状态信息 。UDP 的低延迟和快速传输特性,能够确保游戏数据以最快的速度在玩家和服务器之间传输,提高游戏的流畅度和实时性 。例如,在一些大型的多人在线竞技游戏中,玩家的每一个操作,如移动、攻击等,都需要及时地传输到服务器,并得到服务器的响应 。UDP 协议能够满足这种对实时性的严格要求,让玩家能够在游戏中感受到流畅的操作体验,避免因网络延迟而影响游戏的公平性和趣味性 。
  • 语音通话:在语音通话应用中,实时性和流畅性是用户最为关注的 。虽然语音数据的丢失可能会导致声音的短暂中断,但只要这种中断不频繁,用户仍然能够理解通话的内容 。UDP 的快速传输和简单机制,使得它能够在保证一定语音质量的前提下,实现快速的语音数据传输,满足用户实时通话的需求 。例如,在一些即时通讯软件的语音通话功能中,通常会采用 UDP 协议来传输语音数据,让用户能够与远方的朋友、家人进行清晰、流畅的语音交流 。

三、网络排查工具

3.1 常用排查工具

在 Linux 内核协议栈的排查之旅中,我们需要一些强大的工具来辅助我们定位问题。下面为大家介绍几款常用的工具及其在排查中的关键作用 。

  1. ethtool:这是一款用于查询和设置网卡驱动及其硬件相关信息的强大工具。通过它,我们可以查看网卡的基本状态、配置参数,如速度、双工模式、自动协商状态等。在排查网络故障时,它的一个重要用途是查看硬件丢包统计信息。使用ethtool -S命令加上网卡接口名称,比如ethtool -S eth0,就可以获取到网卡的详细统计数据,包括接收和发送的数据包数量、字节数,以及各类错误统计,如rx_errors(接收错误)、tx_errors(发送错误)等。如果发现rx_errors中的rx_dropped(接收丢弃)数值不断增加,那就可能意味着网卡接收队列出现了问题,比如队列满了导致数据包被丢弃 。它还能用于配置网卡的一些高级功能,如调整 RX/TX Ring 缓冲区大小、管理协议卸载功能等,对优化网络性能和排查硬件相关问题非常有帮助。
  2. ss:Socket Statistics 的缩写,是一个用于获取系统中 socket 统计信息的工具。它的功能类似于 netstat,但在处理大量 socket 连接时,比 netstat 更快更高效,因为它利用了 TCP 协议栈中的 tcp_diag 模块,能直接从内核获取第一手信息。在排查网络问题时,ss 可以帮助我们分析 Socket 缓冲区状态。使用ss -o命令可以显示计时器信息,通过观察retrans_timeout(重传超时)、keepalive_time(保持连接时间)等参数,我们能了解 TCP 连接的健康状况。如果发现某个 TCP 连接的retrans_timeout频繁超时,可能意味着网络存在延迟过高或者丢包的问题 。通过ss -s可以查看套接字使用概况,了解当前系统中 TCP、UDP 等连接的总数,以及处于不同状态(如 ESTABLISHED、TIME-WAIT 等)的连接数量,帮助我们快速定位连接相关的异常情况。
  3. tcpdump:这是一款经典的网络抓包工具,它可以在命令行下对网络上的流量进行截获和分析。我们可以使用 tcpdump 抓取指定网卡、指定协议、指定端口的数据包。比如,tcpdump -i eth0 tcp port 80表示抓取 eth0 网卡上的 TCP 协议、端口为 80(通常是 HTTP 服务端口)的数据包。抓取到数据包后,通过分析数据包的内容,我们可以查看 HTTP 请求和响应的具体数据,检查是否存在数据丢失、错误的数据包格式等问题。tcpdump 还支持使用各种过滤表达式,如根据源 IP 地址、目的 IP 地址、协议类型等进行过滤,帮助我们精准地抓取和分析感兴趣的网络流量 。
  4. Wireshark:一款功能强大的图形化网络分析工具,它可以读取 tcpdump 抓取的数据包文件(.pcap 格式),并以直观的图形界面展示数据包的详细信息。在 Wireshark 中,我们可以对数据包进行分层分析,从链路层、网络层到传输层、应用层,查看每个层次的协议头部和数据内容。对于 TCP 协议的数据包,我们可以查看 TCP 三次握手、四次挥手的过程,分析序列号、确认号、窗口大小等字段,判断 TCP 连接是否正常建立和关闭。对于 UDP 协议的数据包,我们可以查看 UDP 数据报的源端口、目的端口和数据内容,检查 UDP 应用是否正常通信 。Wireshark 还提供了丰富的插件和分析功能,如追踪 TCP 流、分析 HTTP 会话等,能帮助我们更深入地分析网络问题。
  5. bpftrace:这是一个基于 eBPF(extended Berkeley Packet Filter)技术的动态追踪工具,它允许我们在不修改内核代码的情况下,对内核函数、系统调用等进行追踪和分析。在排查 Linux 内核协议栈问题时,bpftrace 可以用来跟踪内核关键函数的执行过程和参数变化。比如,我们可以编写一个 bpftrace 脚本,追踪tcp_sendmsg函数的调用,查看每次发送 TCP 数据包时的参数,包括发送的字节数、套接字描述符等。通过这种方式,我们可以深入了解内核协议栈在数据发送过程中的行为,找出可能存在的问题,如数据包在发送过程中被丢弃的原因 。bpftrace 还支持对用户态程序进行追踪,为我们全面排查网络问题提供了更多的手段。

3.2 环境搭建与工具配置

在使用这些工具之前,我们需要确保它们已经安装在我们的 Linux 系统中,并进行基本的配置。不同的 Linux 发行版安装工具的方式可能略有不同,下面以常见的 Ubuntu 和 CentOS 系统为例进行介绍 。

(1)在 Ubuntu 系统安装

  1. 安装 ethtool:sudo apt-get install ethtool,安装完成后即可直接使用,无需额外配置。
  2. 安装 ss:ss 是 net-tools 的一部分,在 Ubuntu 系统中默认安装。如果没有安装,可以使用sudo apt-get install net-tools进行安装。
  3. 安装 tcpdump:sudo apt-get install tcpdump,安装后即可使用。tcpdump 抓取的数据包默认以十六进制和 ASCII 码的形式显示,如果需要更详细的分析,可以结合 Wireshark 使用。
  4. 安装 Wireshark:sudo apt-get install wireshark,安装完成后,由于 Wireshark 需要使用网卡进行抓包,而普通用户没有权限直接访问网卡,所以需要将当前用户添加到 wireshark 组中,使用sudo usermod -a -G wireshark $USER命令,然后重新登录,即可使用 Wireshark 进行抓包分析 。
  5. 安装 bpftrace:首先需要确保系统内核版本支持 eBPF(一般内核版本 4.9 及以上支持),然后可以通过以下步骤安装:添加 bpftrace 的软件源,echo "deb [trusted=yes] https://packagecloud.io/iovisor/bpftrace/ubuntu/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/bpftrace.list;更新软件源,sudo apt-get update;安装 bpftrace,sudo apt-get install bpftrace。安装完成后,就可以编写和运行 bpftrace 脚本了 。

(2)在 CentOS 系统安装

  1. 安装 ethtool:sudo yum install ethtool,安装完成后即可使用。
  2. 安装 ss:ss 在 CentOS 系统中默认安装在net-tools包中,如果没有安装,可以使用sudo yum install net-tools进行安装。
  3. 安装 tcpdump:sudo yum install tcpdump,安装后即可使用。
  4. 安装 Wireshark:由于 Wireshark 在 CentOS 的官方软件源中没有,所以需要添加第三方软件源。可以使用yum install epel-release安装 EPEL 软件源,然后yum install wireshark进行安装。同样,为了让普通用户能够使用 Wireshark 抓包,需要将用户添加到 wireshark 组中,使用sudo usermod -a -G wireshark $USER,重新登录后生效 。
  5. 安装 bpftrace:确保内核版本支持 eBPF(4.9 及以上),然后添加 bpftrace 软件源,echo "[bpftrace] \nname=bpftrace \nbaseurl=https://packagecloud.io/iovisor/bpftrace/el/7/$basearch \nenabled=1 \ngpgcheck=0 \ngpgkey=https://packagecloud.io/iovisor/bpftrace/gpgkey" | sudo tee /etc/yum.repos.d/bpftrace.repo;更新软件源,sudo yum update;安装 bpftrace,sudo yum install bpftrace。安装完成后,就可以使用 bpftrace 进行内核追踪了 。

通过以上步骤,我们就完成了常用排查工具的安装和基本配置,为后续深入排查 Linux 内核协议栈问题做好了充分的准备。

3.3数据收发流程

(1)发送流程:当我们在浏览器中点击链接访问网页,或者通过文件传输工具向远程服务器上传文件时,这些看似简单的操作背后,都涉及到复杂的数据发送流程,而 Linux 内核网络协议栈在其中扮演着关键角色 。以一个常见的文件传输场景为例,假设我们使用 FTP(文件传输协议)客户端向 FTP 服务器上传一个文件 。当应用程序调用 send 函数发送数据时,数据就像开启了一场奇妙的旅行,开始在 Linux 内核网络协议栈中逐步传递 。

  1. 应用层数据准备:在应用层,FTP 客户端程序将需要上传的文件数据进行整理和打包 。它会将文件内容按照一定的格式和规则进行组织,形成适合网络传输的数据块 。这些数据块就像是装满货物的集装箱,等待着被发送到网络上 。
  2. 系统调用与 SOCKET 层处理:应用程序通过系统调用接口层调用 send 函数,将数据传递给内核 。数据首先到达协议无关的接口层(SOCKET 层) 。在 SOCKET 层,它会根据应用程序创建 socket 时指定的协议类型(如 TCP 或 UDP),为数据选择合适的传输路径 。例如,如果使用 TCP 协议,SOCKET 层会创建一个 TCP 套接字,并将数据放入该套接字的发送缓冲区中 。此时,数据就像被放入了一个特定的 “运输通道”,等待进一步的传输 。
  3. 网络协议实现层封装:数据从 SOCKET 层进入网络协议实现层 。如果是 TCP 协议,TCP 模块会为数据添加 TCP 头部 。TCP 头部包含了源端口、目的端口、序列号、确认号等重要信息 。这些信息就像是货物的运输标签,用于确保数据能够准确无误地到达目的地,并保证数据的可靠性和顺序性 。例如,序列号用于标识数据的顺序,接收方可以根据序列号对数据进行排序;确认号用于告知发送方哪些数据已经被成功接收 。添加完 TCP 头部后,数据就变成了 TCP 报文段 。接着,IP 模块会为 TCP 报文段添加 IP 头部 。IP 头部包含了源 IP 地址、目的 IP 地址等信息 。这些信息就像是货物的送货地址和发货地址,用于在网络中为数据选择正确的路由 。添加完 IP 头部后,数据就变成了 IP 数据报 。
  4. 驱动接口层与驱动程序层传输:IP 数据报从网络协议实现层传递到与具体设备无关的驱动接口层 。这一层就像是一个中转枢纽,它将 IP 数据报传递给驱动程序层 。驱动程序层负责与硬件设备(如网卡)进行直接交互 。在驱动程序层,IP 数据报会被转换为适合网卡传输的格式,通常是以太网帧 。以太网帧包含了源 MAC 地址、目的 MAC 地址等信息 。这些信息就像是货物的运输标签,用于在局域网中识别设备 。最后,驱动程序通过网卡将以太网帧发送到物理网络上 。以太网帧就像一艘艘装满货物的船只,在网络的海洋中驶向目的地 。

(2)接收流程:当我们在浏览器中成功加载网页,或者从远程服务器下载完文件后,这些数据是如何从网络到达我们的应用程序的呢?这就涉及到 Linux 内核网络协议栈的数据接收流程 。还是以刚才的 FTP 文件传输为例,这次我们来看看 FTP 服务器是如何接收文件数据的 。

  1. 网卡数据捕获:当网卡接收到来自网络的以太网帧时,它就像一个勤劳的快递员,将这些帧从网络中 “捕获” 下来 。网卡会利用直接内存访问(DMA)机制,将以太网帧直接传输到系统内存中,这样可以大大提高数据接收的效率,就像快递员直接将包裹送到指定的仓库,而不需要经过其他繁琐的环节 。
  2. 驱动程序层与驱动接口层传递:网卡驱动程序接收到以太网帧后,会对其进行初步处理 。它会检查以太网帧的完整性和正确性,就像快递员在接收包裹时会检查包裹是否有损坏 。如果以太网帧没有问题,驱动程序会将其传递到与具体设备无关的驱动接口层 。在这一层,以太网帧会被进一步传递到网络协议实现层 。
  3. 网络协议实现层解封装:以太网帧到达网络协议实现层后,首先会进行解封装操作 。IP 模块会检查 IP 头部的校验和,验证 IP 数据报的完整性 。如果 IP 数据报是分片的,IP 模块还会进行分片重组操作,将各个分片重新组合成完整的 IP 数据报 。这就像将一个被拆开的包裹重新组装起来 。接着,IP 模块会根据目的 IP 地址查找路由表,确定数据的转发方向 。如果数据是发送给本机的,IP 模块会将 IP 数据报传递给 TCP 模块 。TCP 模块会检查 TCP 头部的校验和,验证 TCP 报文段的完整性 。它还会根据序列号和确认号对数据进行排序和确认,确保数据的顺序性和可靠性 。例如,如果 TCP 模块发现某个数据段丢失,它会要求发送方重新发送该数据段 。最后,TCP 模块会将数据从 TCP 报文段中提取出来,去除 TCP 头部 。
  4. SOCKET 层与应用层交付:经过网络协议实现层处理后的数据,会被传递到协议无关的接口层(SOCKET 层) 。在 SOCKET 层,数据会根据目的端口号被分发到相应的应用程序套接字 。例如,对于 FTP 服务器来说,数据会被分发到 FTP 服务器进程对应的套接字 。最后,数据通过系统调用接口层返回给应用层的 FTP 服务器程序 。FTP 服务器程序接收到数据后,会将其存储到指定的文件中,完成文件的接收过程 。

四、实战排查:步步逼近真相

当我们在实际工作中遇到网络延迟问题,需要从 Linux 内核协议栈入手进行排查时,一个清晰、系统的排查流程就显得尤为重要。接下来,我将详细介绍网络延迟排查的全过程,帮助大家快速定位并解决问题。

4.1初步判断:硬件还是软件问题

当网络出现丢包等异常情况时,首先要判断问题是出在硬件层面还是软件层面。这一步至关重要,它决定了我们后续排查的方向。我们可以利用 ethtool 工具来检查网卡硬件的丢包统计信息。

在服务器上执行ethtool -S eth0(假设网卡接口为 eth0),得到如下输出:

NIC statistics:     rx_packets100000     tx_packets98000     rx_bytes15000000     tx_bytes14500000     rx_errors100     tx_errors50     rx_dropped500     tx_dropped200

从这些统计数据中,我们重点关注rx_errors(接收错误)和rx_dropped(接收丢弃)以及tx_errors(发送错误)和tx_dropped(发送丢弃)这几个指标。如果rx_errors和rx_dropped数值较大,且持续增长,说明网卡在接收数据包时可能存在问题,比如网卡硬件故障、网线连接不稳定、电磁干扰等硬件相关的问题 。在这个例子中,rx_dropped达到了 500,这是一个比较异常的数值,初步怀疑可能存在硬件接收问题。

为了进一步确认,我们可以检查网卡的物理连接,查看网线是否插好,接口是否有松动或损坏的迹象。还可以尝试更换一根网线,或者将网卡插到其他插槽上,看丢包情况是否有所改善 。如果经过这些检查和操作,丢包问题依然存在,且硬件统计数据没有明显变化,那么我们就可以基本排除硬件问题,将排查重点转向软件层面。

4.2 Socket 缓冲区分析

排除硬件问题后,我们接着分析软件层面的 Socket 缓冲区,看看是否存在缓冲区溢出或过小导致数据丢失的情况。这时候,ss 命令就派上用场了。

使用ss -t -a命令查看所有 TCP socket 的状态,部分输出如下:

Netid  State      Recv-Q Send-Q Local Address:Port               Peer Address:Porttcp    ESTAB      0      0      192.168.1.10:80               192.168.1.20:50000tcp    ESTAB      1024   0      192.168.1.10:8080             192.168.1.30:45678

在这个输出中,Recv-Q表示接收队列中尚未被应用程序读取的数据量,Send-Q表示发送队列中尚未被发送出去的数据量 。正常情况下,Recv-Q和Send-Q的值应该保持在一个较低的水平。如果某个连接的Recv-Q持续增大,且长时间不为 0,说明接收缓冲区可能存在问题,应用程序读取数据的速度跟不上数据接收的速度,导致数据在缓冲区中积压,最终可能被丢弃 。

比如上面输出中,第二个连接的Recv-Q达到了 1024,这是一个比较大的数值,很可能是接收缓冲区过小,或者应用程序处理数据的效率较低。我们可以进一步查看该连接对应的应用程序代码,检查数据读取和处理的逻辑,看是否存在阻塞或其他性能问题 。也可以尝试调整 Socket 缓冲区的大小,通过改/proc/sys/net/core/rmem_default(接收缓冲区默认大小)和/proc/sys/net/core/rmem_max(接收缓冲区最大大小)等系统参数,增加缓冲区的容量,看是否能解决问题 。使用如下命令临时调整接收缓冲区最大大小为 131072 字节:

echo 131072 > /proc/sys/net/core/rmem_max

如果希望永久生效,可以将配置写入/etc/sysctl.conf文件:

net.core.rmem_max = 131072

然后执行sysctl -p使配置生效。通过调整缓冲区大小并观察Recv-Q的变化,我们可以判断缓冲区问题是否是导致丢包的原因。

4.3 数据包捕获与分析

经过 Socket 缓冲区分析后,如果问题仍未解决,我们就需要深入到数据包层面进行分析。利用 tcpdump 抓取数据包,然后配合 Wireshark 进行可视化分析,这是排查网络问题的常用手段。首先,使用 tcpdump 抓取指定网卡和端口的数据包,比如抓取 eth0 网卡上端口为 80 的 TCP 数据包,并将其保存到文件http.pcap中:

tcpdump -i eth0 tcp port 80 -w http.pcap

抓取一段时间后,按Ctrl+C停止抓包。然后将http.pcap文件传输到装有 Wireshark 的机器上(如果服务器本身安装了 Wireshark,也可以直接在服务器上打开),用 Wireshark 打开该文件。

在 Wireshark 中,我们可以看到数据包的详细信息,包括源 IP 地址、目的 IP 地址、协议类型、端口号等。通过分析这些信息,我们可以判断网络传输的各个环节是否正常 。我们可以查看 TCP 三次握手的过程,看是否存在握手失败的情况。正常的 TCP 三次握手应该是这样的:

  1. 客户端发送一个 SYN 包,请求建立连接。
  2. 服务器收到 SYN 包后,回复一个 SYN+ACK 包,表示同意建立连接。
  3. 客户端收到 SYN+ACK 包后,再发送一个 ACK 包,完成连接建立。

如果在 Wireshark 中发现 SYN 包没有得到 ACK 响应,或者出现大量的重传包,就说明网络连接存在问题,可能是网络延迟过高、丢包导致连接建立失败 。我们还可以对比内外网数据包的差异,比如抓取从外网访问服务器和服务器内部通信的数据包,查看是否存在特定网络环境下才出现的问题。如果发现只有外网访问时出现丢包,而内网通信正常,那么问题可能出在网络出口设备(如路由器、防火墙)或者网络服务提供商的线路上 。通过这样细致的数据包分析,我们可以进一步缩小问题的范围,确定问题出在网络传输的哪个环节。

4.4 深入内核:追踪关键函数

经过前面几个步骤的排查,如果问题还是没有得到解决,那就需要深入到内核层面,追踪关键函数的执行过程,找出可能导致丢包的内核逻辑。这里我们运用 bpftrace 这个强大的动态追踪工具。我们可以编写一个简单的 bpftrace 脚本,用于跟踪tcp_sendmsg函数的调用,查看每次发送 TCP 数据包时的参数,脚本内容如下:

#include <net/sock.h>intkprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk, struct msghdr *msg, size_t size){    u32 pid = bpf_get_current_pid_tgid() >> 32;    u32 uid = bpf_get_current_uid_gid() & 0xffffffff;    printf("PID %d (UID %d) is sending %zu bytes via tcp_sendmsg\n", pid, uid, size);    return 0;}

将上述脚本保存为tcp_sendmsg_trace.bt,然后执行bpftrace tcp_sendmsg_trace.bt运行脚本。脚本运行后,每当tcp_sendmsg函数被调用,就会输出调用该函数的进程 PID、UID 以及发送的字节数 。通过观察这些输出,我们可以了解到内核在发送 TCP 数据包时的行为,判断是否存在异常的发送操作。

我们还可以进一步扩展脚本,跟踪其他与网络相关的关键函数,比如tcp_recvmsg(接收 TCP 数据包的函数)、ip_forward(IP 转发函数)等,通过分析这些函数的执行路径和参数变化,定位到具体的内核函数及执行路径中可能出现丢包的位置 。这一步需要对 Linux 内核协议栈的原理有较深入的理解,但一旦定位到问题所在,就能够从根本上解决网络故障。

五、常见问题与避坑指南

在排查网络延迟问题时,常常会掉进一些 “坑” 里,导致排查工作走弯路,甚至无法找到问题的真正原因。下面我就来给大家讲讲一些常见的问题以及如何避免它们。

5.1工具使用不当

排查网络延迟离不开各种工具,但如果使用不当,不仅无法获取有效的信息,还可能得出错误的结论。比如,tcpdump 是一个强大的抓包工具,但如果过滤条件设置不合理,可能会抓取到大量无关的数据包,让人眼花缭乱,难以从中找到关键信息。在排查一个 Web 服务器的网络延迟问题时,运维人员使用 tcpdump 抓包,却没有设置正确的过滤条件,结果抓取到了大量的广播包和其他无关的网络流量,导致分析工作陷入困境。后来,经过仔细分析,明确了需要关注的是与 Web 服务器通信的 TCP 数据包,于是设置了 “tcp and host [Web 服务器 IP 地址]” 的过滤条件,才成功抓取到了有用的数据包,为后续的分析提供了依据。

为了避免工具使用不当的问题,在使用前一定要仔细阅读工具的文档,了解其各种参数和选项的含义 。可以先在测试环境中进行一些简单的测试,熟悉工具的使用方法和输出结果的含义。同时,在设置过滤条件时,要根据具体的排查需求,尽可能精确地指定过滤条件,避免抓取到过多无关的数据。

5.2误判问题根源

网络延迟问题往往是由多种因素共同作用导致的,有时候表面上看起来是某个层面的问题,但实际上问题的根源可能在其他层面。在一个企业网络中,用户反映访问外部网站速度很慢,运维人员首先检查了网络层的路由配置,发现一切正常,于是认为问题出在链路层,检查了网线和交换机等设备,也没有发现问题。后来经过深入分析,才发现是应用层的某个代理服务器配置错误,导致数据在代理服务器上处理缓慢,从而引发了网络延迟。

为了避免误判问题根源,在排查时要保持全面、系统的思维方式 ,不要仅仅根据某一个层面的现象就轻易下结论。要从 Linux 内核协议栈的各个层次入手,逐步深入分析,综合考虑各种因素,才能准确地找到问题的根源。同时,在遇到问题时,可以多与其他技术人员交流,分享自己的排查思路和发现,从不同的角度获取建议和启发,有助于更快地解决问题。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-07 23:42:14 HTTP/2.0 GET : https://f.mffb.com.cn/a/468775.html
  2. 运行时间 : 0.110695s [ 吞吐率:9.03req/s ] 内存消耗:4,874.06kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=caf1d8a69f3ea4a524adc376a6aaee06
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000499s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000639s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.005026s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001396s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000615s ]
  6. SELECT * FROM `set` [ RunTime:0.003655s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000600s ]
  8. SELECT * FROM `article` WHERE `id` = 468775 LIMIT 1 [ RunTime:0.000507s ]
  9. UPDATE `article` SET `lasttime` = 1770478934 WHERE `id` = 468775 [ RunTime:0.010495s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.007365s ]
  11. SELECT * FROM `article` WHERE `id` < 468775 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001898s ]
  12. SELECT * FROM `article` WHERE `id` > 468775 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001958s ]
  13. SELECT * FROM `article` WHERE `id` < 468775 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003892s ]
  14. SELECT * FROM `article` WHERE `id` < 468775 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004537s ]
  15. SELECT * FROM `article` WHERE `id` < 468775 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000994s ]
0.112834s