网络模型
OSI 网络模型
应用层,负责为应用程序提供统一的接口。
表示层,负责把数据转换成兼容接收系统的格式。
会话层,负责维护计算机之间的通信连接。
传输层,负责为数据加上传输表头,形成数据包。
网络层,负责数据的路由和转发。
数据链路层,负责 MAC 寻址、错误侦测和改错。
物理层,负责在物理网络中传输数据帧。
TCP/IP 模型
应用层,负责向用户提供一组应用程序,比如 HTTP、FTP、DNS 等。
传输层,负责端到端的通信,比如 TCP、UDP 等。
网络层,负责网络包的封装、寻址和路由,比如 IP、ICMP 等。
网络接口层,负责网络包在物理网络中的传输,比如 MAC 寻址、错误侦测以及通过网卡传输网络帧等。
网络包的接收流程
当一个网络帧到达网卡后,网卡会通过 DMA 方式,把这个网络包放到收包队列中;然后通过硬中断,告诉中断处理程序已经收到了网络包。
接着,网卡中断处理程序会为网络帧分配内核数据结构(sk_buff),并将其拷贝到 sk_buff 缓冲区中;然后再通过软中断,通知内核收到了新的网络帧。
接下来,内核协议栈从缓冲区中取出网络帧,并通过网络协议栈,从下到上逐层处理这个网络帧。比如,
- 在链路层检查报文的合法性,找出上层协议的类型(比如 IPv4 还是 IPv6),再去掉帧头、帧尾,然后交给网络层。
- 网络层取出 IP 头,判断网络包下一步的走向,比如是交给上层处理还是转发。当网络层确认这个包是要发送到本机后,就会取出上层协议的类型(比如 TCP 还是 UDP),去掉 IP 头,再交给传输层处理。
- 传输层取出 TCP 头或者 UDP 头后,根据 < 源 IP、源端口、目的 IP、目的端口 > 四元组作为标识,找出对应的 Socket,并把数据拷贝到 Socket 的接收缓存中。
最后,应用程序就可以使用 Socket 接口,读取到新接收到的数据了。
如何衡量系统的网络性能?
-
-
带宽 -> ethtool
- ethtool eth0 | grep Speed
-
吞吐量 -> sar -n DEV 1
-
pps -> sar -n DEV 1
-
延时 -> ping
- 通常指应用请求到收到响应的时间 (RTT)
- 也可能指tcp连接建立的时间
-
连通性 -> ping
-
丢包率/重传率 -> ifconfig
-
-
如何查看网卡/网络配置信息
- ifconfig <网卡>
- ip -s addr show dev <网卡>
-
如何查看系统当前连接(socket)信息
- 查看连接信息即查看socket信息,一个socket对应一个唯一的5元祖
- <protocol, source_ip, source_port, target_ip, target_port>
- 查看当前监听状态的tcp socket及其所属进程
- netstat -ntlp
- ss -ntlp
- 查看协议栈的统计信息
- netstat -s
- ss -s
- 查看连接信息即查看socket信息,一个socket对应一个唯一的5元祖
-
如何理解netstat或ss输出的两个队列含义(Recv-Q和Send-Q)
- 可以参考这篇文章:
- 半连接队列(sync队列) -> 第一次握手(sync)后将连接放入sync队列
- 全连接队列(accept队列) -> 第三次握手(ack) 后将连接放入accept队列
- Recv-Q 表示当前队列长度
- Send-Q 表示配置的最大长度
- 例如nginx默认是511
- Recv-Q > Send-Q 时,说明队列饱和,将发生overFlows
- netstat -s 可查看sync或accept队列溢出信息
- 半连接队列饱和
- 常见与sync flood攻击, 导致连接一直无法建立并影响正常连接
- 全连接队列饱和
- 如果Send-Q设置过小(例如java NIO 默认50),在并发连接较大时容易发生
- 饱和后默认丢弃ack包,客户端将按策略重传,超过一定时间关闭连接
- netty如何设置全连接队列长度? -> BACKLOG
- .option(ChannelOption.SO_BACKLOG, 1024)
- 如果Send-Q设置过小(例如java NIO 默认50),在并发连接较大时容易发生
- 可以参考这篇文章: