网络是怎样工作的?

网络是怎样工作的

故事的开始,是一道面试题

汽车之家的一道面试题:

汽车之家面试题

网络基础

为什么要学习网络协议?

《圣经》中有一个通天塔的故事,大致是说,上帝为了阻止人类联合起来,就让人类说不同的语言。人类没法儿沟通,达不成“协议”,通天塔的计划就失败了。

搜狗截图22年09月25日1958_3.jpg

但是千年以后,有一种叫”程序猿”的物种,敲着一种这个群体通用的语言,连接着全世界所有的人,打造这互联网世界的通天塔。如今的世界,正是因为互联网,才连接在一起。

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args){
System.out.println("Hello World!");
}
}

只有通过这种协议,计算机才知道我们想让它做什么。

但是,要想打造互联网世界的通天塔,只教给一台机器做什么是不够的,你需要学会教给一大片机器做什么。这就需要网络协议。只有通过网络协议,才能使一大片机器互相协作、共同完成一件事。

所以,我们要了解我们无时无刻都要接触到的网络的工作原理。

网络分层模型

OSI 七层网络模型由国际标准化组织进行制定,它是正统意义上的国际标准。但其实现过于复杂,且制定周期过长,在其整套标准推出之前,TCP/IP 模型已经在全球范围内被广泛使用,所以 TCP/IP 模型才是事实上的国际标准。

TCP/IP 模型定义了应用层、传输层、网际层、网络接口层这四层网络结构,但并没有给出网络接口层的具体内容,因此在学习和开发中,通常将网络接口层替换为 OSI 七层模型中的数据链路层和物理层来进行理解,这就是五层网络模型:

七层、五层、四层对比.drawio

七层模型对应层的常用协议都有哪些呢?

作用 常用协议
应用层 为操作系统或网络应用程序提供访问网络服务的接口 TELENT、DNS、HTTP、HTTPS、FTP、NFS
表示层 用于数据转换,确保源端和目的端之间的数据能够互相理解 LPP
会话层 建立通信连接,保持会话过程通信连接的通畅 LDAP
传输层 进行分段和传输,达到目的地址后进行重组 TCP、UDP、TLS。
网络层 进行IP地址的封装和解封装 IP、ICMP、ICMPv6
数据链路层 进行mac地址的封装与解封装 VLAN、STP、IEEE 802.3、WIFI(IEEE 802.11)、ATM、HDLC、PPP、ARP、RARP
物理层 为数据链路层提供物理连接
  • OSI参考模型并不是一个标准,而是一个在制定标准时所使用的概念性框架。

  • TCP/IP 常被称为事实上的国际标准。

网络为啥要分层?

因为,是个复杂的系统/程序都要分层

  • 相互通信的两个计算机系统必须高度协调工作才行,而这种“协调”是相当复杂的。
  • 分层”可将庞大而复杂的问题,转化为若干较小的局部问题,而这些较小的局部问题就比较易于研究和处理。
  • 分工和合作

四层负载均衡、七层负载均衡的区别?

LVS 是四层负载均衡,是我们国家著名技术专家:章文嵩博士研发的,也就是说建立在 OSI 模型的第四层——传输层之上,传输层上有我们熟悉的TCP/UDPLVS支持TCP/UDP的负载均衡。

LVS的转发主要通过修改IP地址(NAT模式,分为源地址修改SNAT和目标地址修改DNAT)、修改目标MAC(DR 模式)来实现。

四层负载均衡和七层负载均衡在互联网协议栈的层次上有所区别,但它们都是用于在网络中分配服务流量的技术。

四层负载均衡:

  • 四层负载均衡工作在OSI网络模型的第四层,即传输层。
  • 它主要负责在接收到客户端的流量后,通过修改数据包的地址信息将流量转发到应用服务器。这种负载均衡基于IP+端口进行操作,只负责转发并且会记录当前连接是由哪个服务器处理的,后续这个连接的请求就由同一台服务器去处理,以此达到负载均衡的目的。
  • 四层负载均衡通常使用如LVS、HAProxy等工具来实现。

七层负载均衡:

  • 七层负载均衡工作在OSI网络模型的第七层,即应用层。
  • 它主要工作是代理,因为需要解析应用层流量,所以在接收到客户端流量之后,还需要接受完整的TCP/ IP协议栈。之后将与客户端建立一条完整的连接并将应用层的请求流量解析出来,再按照调度算法选择应用服务器,最后与应用服务器建立一条连接将请求发送过去。
  • 七层负载均衡能理解应用协议,例如HTTP、FTP、MySQL等,在处理用户需求上能更加灵活。常见的实现七层负载均衡的工具有HAProxy、Nginx等。

总的来说,四层负载均衡和七层负载均衡的主要区别在于工作层次和应用场景不同。它们分别在传输层和应用层上对网络流量进行优化,以提供更高效、灵活的服务。

四层负载均衡的应用场景主要有:

  1. 负载均衡来做四层负载均衡和七层负载均衡的组合,四层负载均衡可以保证七层负载均衡的高可用性。
  2. 负载均衡可以做端口转发。
  3. 数据库读写分离。

七层负载均衡在多种应用场景中都可以使用,以下是几种常见的应用场景:

  1. Web应用:七层负载均衡可以用于Web应用中,对请求进行URL和Cookie分发,根据业务需求对请求进行处理和转发,确保请求的高可用性和可靠性。
  2. 流媒体应用:七层负载均衡在流媒体应用中,可以根据请求分发流媒体数据,支持高质量的音视频流传输。
  3. 文件传输应用:七层负载均衡可以根据应用层的FTP协议进行请求分发,支持大规模的文件传输。
  4. API应用:七层负载均衡可以识别RESTful API的URL、HTTP头等信息,进行请求的流量控制和路由转发。

七层负载均衡在以上应用场景中,可以有效地处理和分发请求,保证应用的可用性和可靠性。

HTTP 2.0

HTTP2与HTTP1.1在传输方式、使用协议、头部压缩以及通信方式等方面存在一些显著的区别。

  1. 传输方式:HTTP2采用二进制传输,以二进制分帧的方式进行流传输,而HTTP1.1则采用报文形式进行传输。这意味着HTTP2的传输效率更高,因为二进制数据的传输速率通常比文本数据快。
  2. 使用协议:HTTP2使用的是http+Hpack+Stream的协议,而HTTP1.1使用的是http+tcp的协议。这种协议上的差异使得HTTP2可以实现更高效的数据传输。
  3. 压缩算法:HTTP2使用了Hpack压缩头部信息,以减少传输的数据量。而HTTP1.1并没有这样的压缩功能,这意味着在同样的网络环境下,HTTP2可以提供更快的传输速度。
  4. 通信方式:HTTP2支持全双工通信方式,即客户端和服务器都可以主动发起请求。而HTTP1.1只支持半双工通信方式,即只有一方(客户端或服务器)可以主动发起请求。这种通信方式上的差异使得HTTP2可以更好地利用网络带宽,提高数据传输的效率。

总的来说,HTTP2相比HTTP1.1在多个方面进行了优化和改进,提供了更高效的数据传输和更好的网络使用体验。

网络设备

TODO

回到我们最初的问题,在浏览器输入URL到显示汽车之家页面,这中间发生了什么?

打开汽车网站的过程是怎样的?

接入互联网的方式有:

  1. 电话线拨号接入(PSTN)。这种接入方式是家庭用户接入互联网的普遍的窄带接入方式。即通过电话线,利用当地运营商提供的接入号码,拨号接入互联网,速率不超过56Kbps。
  2. ISDN。ISDN是Integrated Service Digital Network的缩写,即窄带综合业务数字网,俗称“一线通”。用户利用一条ISDN用户线路,可以在上网的同时拨打电话、收发传真,就像两条电话线一样。
  3. ADSL接入。这是运用最广泛的铜线接入方式。
  4. HFC(CABLEMODEM)。这是一种基于有线电视网络铜线资源的接入方式。具有专线上网的连接特点,允许用户通过有线电视网实现高速接入互联网。
  5. 光纤宽带接入。这种接入方式通过光纤接入到小区节点或楼道,再由网线连接到各个共享点上,提供一定区域的高速互联接入。

应用

Wireshark

image-20230916131028875

从一次请求外部接口失败说起

故障描述:有一个请求外部接口上传文件的功能,会偶发性的报错Connection Timeout,经过排查发现规律,文件过大时才会出现问题。

排查过程:通过模拟请求,在请求数据包达到一定大小,接口返回错误;

所以通过Wireshark在服务器上抓包分析,抓包结果:

image-20230917114401916

  • TCP Out-of-Order:后一个包的 Seq 号小于前一个包的 Seq+Len 时。
  • TCP Retransmission:发送方只好等到超时了再重传。

排查结果:因为公司防火墙对TCP乱序策略的设置问题导致丢包,在运维联系防火墙厂家修改配置之后,问题解决。

502问题怎么排查?

在一个风和日丽的下午,某一个上游服务在调用下游服务是,接口接收到502错误的返回,遂让下游服务排查问题。

下游服务应用刚好有一套监控HTTP响应状态码的系统,但是在系统中,并未发现产生了502错误的状态码。

在rfc7231中有关于502错误码的官方解释是:

1
2
502 Bad Gateway
The 502 (Bad Gateway) status code indicates that the server, while acting as a gateway or proxy, received an invalid response from an inbound server it accessed while attempting to fulfill the request.

翻译一下:

1
502 (Bad Gateway) 状态代码表示服务器在充当网关或代理时,在尝试满足请求时从它访问的入站服务器接收到无效响应。

汝听,人言否?

image-20230917131402464 image-20230917133656349

Nginx返回5xx状态码

有了Nginx这一中间层后,客户端从直连服务端,变成客户端直连Nginx,再由Nginx直连服务端。从一个TCP连接变成两个TCP连接。

于是,当服务器发生异常时,Nginx发送给服务器的那条TCP连接就不能正常响应,Nginx在得到这一信息后,就会返回5xx错误码给客户端,也就是说5xx的报错,其实是由Nginx识别出来,并返回给客户端的,服务端本身,并不会有5xx的日志信息。所以才会出现上游收到了我服务的502报错,但在自己的服务日志里却搜索不到这一信息。

解释下,其实是说,502其实是由网关代理(Nginx)发出的,是因为网关代理把客户端的请求转发给了服务端,但服务端却发出了无效响应,而这里的无效响应,一般是指TCP的RST报文或四次挥手的FIN报文。

四次挥手估计大家背的很熟了,所以略过,我们来重点说下RST报文是什么。

RST是什么?

我们都知道TCP正常情况下断开连接是用四次挥手,那是正常时候的优雅做法。

异常情况下,收发双方都不一定正常,连挥手这件事本身都可能做不到,所以就需要一个机制去强行关闭连接。

RST 就是用于这种情况,一般用来异常地关闭一个连接。它是TCP包头中的一个标志位,在收到置这个标志位的数据包后,连接就会被关闭,此时接收到 RST的一方,在应用层会看到一个 connection resetconnection refused 的报错。

image-20230917154956193

RST报文一般在以下情况下使用:

  1. 当连接请求到达时,如果目的端口没有进程正在监听,那么就会产生RST报文。在TCP中,如果一个数据报到达目的端口,而该端口没有在使用,那么就会产生一个ICMP端口不可达的信息。而在UDP中,当一个数据报到达目的端口时,如果该端口没在使用,它将产生一个ICMP端口不可达的信息。
  2. 当客户端发起请求连接的时候,会设置一个范围值,如果在这个范围内没有收到回复,就会发送RST报文给服务器,表示不想再连接。
  3. 在某些异常情况下,如数据包被防火墙拦截或套接字接收缓冲区中的数据未完全接收应用,也可能会产生RST报文。

之所以发出RST报文,一般有两个常见原因

  1. 服务端设置的超时时间过短。
  2. 第二个原因,也是造成502状态码最常见的原因,就是服务端应用进程崩了(crash)

实践来了~~~我们来复现一下上面第一种状况的过程:

首先,通过Go语言写一个WEB接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
"fmt"
"net/http"
"time"
)

type Handler struct {
}

func main() {

server := &http.Server{
Addr: "0.0.0.0:8081", // 监听端口
Handler: &Handler{},
ReadTimeout: time.Second * 3,
WriteTimeout: time.Second * 3, // 设置写超时
}

server.ListenAndServe()
}

func (h *Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
time.Sleep(time.Duration(5) * time.Second) //睡5s
fmt.Fprint(writer, "Hello, World!") // 将字符串写入响应体
}

然后在Nginx配置一下:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name http-test.autohome.com.cn;
proxy_read_timeout 300;
proxy_send_timeout 300;
location / {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}

发送请求:

image-20230917175214448

通过Wireshark抓包看一下:

image-20230917202027311

出现了一个奇怪的现象:

image-20230917175319946

第二种状况,服务确实挂了,那网络请求到服务器发现端口并没有在监听,直接就返回502,没必要分析了。。。

服务器内核设置导致tcp连接失败

TODO

最后

从输入网址到显示出网页内容,这个过程只有短短几百毫秒的时间。然而,在这短短几百毫秒的背后,离不开各种设备和软件的相互配合。

这次分享的内容还仅仅是网络世界的一小部分而已,还有很多内容我们还无法一一了解,如果深入挖掘其中一些细节也是难以穷尽的。网络的复杂度由此可见一斑。

感谢各位。

附录

名词解释

简写 全称 解释
LVS Linux Virutal Server Linux 虚拟服务器
DR Direct Route 直接路由
RS Real Server 真实服务器
DIR Director LVS 中的转发器
VIP Virtual IP Address LVS 暴露的公网 IP
向外部直接面向用户请求,作为用户请求的目标的IP地址
主要是用来进行不同主机之间的切换。
RIP Real Server IP RS 对应的 IP
NAT Network Address Transfer 网络地址转换
CIP Client IP 访问客户端的IP地址

分层模型对应协议

网络七层协议