写点什么

网络篇夺命连环 12 问

作者:冇先生
  • 2021 年 11 月 10 日
  • 本文字数:3438 字

    阅读完需:约 11 分钟

面试题系列:网络篇夺命连环 12 问

为了增强通用性和兼容性,计算机网络都被设计成层次机构,每一层都遵守一定的规则。因此有了 OSI 这样一个抽象的网络通信参考模型,按照这个标准使计算机网络系统可以互相连接。

一、谈一谈你对 TCP/IP 四层模型,OSI 七层模型的理解?

为了增强通用性和兼容性,计算机网络都被设计成层次机构,每一层都遵守一定的规则。

因此有了 OSI 这样一个抽象的网络通信参考模型,按照这个标准使计算机网络系统可以互相连接。

  • 物理层:通过网线、光缆等这种物理方式将电脑连接起来。传递的数据是比特流,0101010100。

  • 数据链路层:首先,把比特流封装成数据帧的格式,对 0、1 进行分组。电脑连接起来之后,数据都经过网卡来传输,而网卡上定义了全世界唯一的 MAC 地址。然后再通过广播的形式向局域网内所有电脑发送数据,再根据数据中 MAC 地址和自身对比判断是否是发给自己的。

  • 网络层:广播的形式太低效,为了区分哪些 MAC 地址属于同一个子网,网络层定义了 IP 和子网掩码,通过对 IP 和子网掩码进行与运算就知道是否是同一个子网,再通过路由器和交换机进行传输。IP 协议属于网络层的协议。

  • 传输层:有了网络层的 MAC+IP 地址之后,为了确定数据包是从哪个进程发送过来的,就需要端口号,通过端口来建立通信,比如 TCP 和 UDP 属于这一层的协议。

  • 会话层:负责建立和断开连接

  • 表示层:为了使得数据能够被其他的计算机理解,再次将数据转换成另外一种格式,比如文字、视频、图片等。

  • 应用层:最高层,面对用户,提供计算机网络与最终呈现给用户的界面


TCP/IP 则是四层的结构,相当于是对 OSI 模型的简化。

  • 数据链路层,也有称作网络访问层、网络接口层。他包含了 OSI 模型的物理层和数据链路层,把电脑连接起来。

  • 网络层,也叫做 IP 层,处理 IP 数据包的传输、路由,建立主机间的通信。

  • 传输层,就是为两台主机设备提供端到端的通信。

  • 应用层,包含 OSI 的会话层、表示层和应用层,提供了一些常用的协议规范,比如 FTP、SMPT、HTTP 等。

总结下来,就是物理层通过物理手段把电脑连接起来,数据链路层则对比特流的数据进行分组,网络层来建立主机到主机的通信,传输层建立端口到端口的通信,应用层最终负责建立连接,数据格式转换,最终呈现给用户。

二、说说 TCP 3 次握手的过程?

建立连接前 server 端需要监听端口,所以初始状态是 LISTEN。

  • client 端建立连接,发送一个 SYN 同步包,发送之后状态变成 SYN_SENT

  • server 端收到 SYN 之后,同意建立连接,返回一个 ACK 响应,同时也会给 client 发送一个 SYN 包,发送完成之后状态变为 SYN_RCVD

  • client 端收到 server 的 ACK 之后,状态变为 ESTABLISHED,返回 ACK 给 server 端。server 收到之后状态也变为 ESTABLISHED,连接建立完成。

为什么要 3 次?2 次,4 次不行吗?

因为 TCP 是双工传输模式,不区分客户端和服务端,连接的建立是双向的过程。

如果只有两次,无法做到双向连接的建立,从建立连接 server 回复的 SYN 和 ACK 合并成一次可以看出来,他也不需要 4 次。

挥手为什么要四次?因为挥手的 ACK 和 FIN 不能同时发送,因为数据发送的截止时间不同。

四、那么四次挥手的过程呢?

  1. client 端向 server 发送 FIN 包,进入 FIN_WAIT_1 状态,这代表 client 端已经没有数据要发送了

  2. server 端收到之后,返回一个 ACK,进入 CLOSE_WAIT 等待关闭的状态,因为 server 端可能还有没有发送完成的数据

  3. 等到 server 端数据都发送完毕之后,server 端就向 client 发送 FIN,进入 LAST_ACK 状态

  4. client 收到 ACK 之后,进入 TIME_WAIT 的状态,同时回复 ACK,server 收到之后直接进入 CLOSED 状态,连接关闭。但是 client 要等待 2MSL(报文最大生存时间)的时间,才会进入 CLOSED 状态。


为什么要等待 2MSL 的时间才关闭?

  • 为了保证连接的可靠关闭。如果 server 没有收到最后一个 ACK,那么就会重发 FIN。

  • 为了避免端口重用带来的数据混淆。如果 client 直接进入 CLOSED 状态,又用相同端口号向 server 建立一个连接,上一次连接的部分数据在网络中延迟到达 server,数据就可能发生混淆了。

六、TCP 怎么保证传输过程的可靠性?

校验和:发送方在发送数据之前计算校验和,接收方收到数据后同样计算,如果不一致,那么传输有误。

确认应答,序列号:TCP 进行传输时数据都进行了编号,每次接收方返回 ACK 都有确认序列号。

超时重传:如果发送方发送数据一段时间后没有收到 ACK,那么就重发数据。

连接管理:三次握手和四次挥手的过程。

流量控制:TCP 协议报头包含 16 位的窗口大小,接收方会在返回 ACK 时同时把自己的即时窗口填入,发送方就根据报文中窗口的大小控制发送速度。

拥塞控制:刚开始发送数据的时候,拥塞窗口是 1,以后每次收到 ACK,则拥塞窗口+1,然后将拥塞窗口和收到的窗口取较小值作为实际发送的窗口,如果发生超时重传,拥塞窗口重置为 1。这样做的目的就是为了保证传输过程的高效性和可靠性。

七、说下浏览器请求一个网址的过程?

  • 首先通过 DNS 服务器把域名解析成 IP 地址,通过 IP 和子网掩码判断是否属于同一个子网

  • 构造应用层请求 http 报文,传输层添加 TCP/UDP 头部,网络层添加 IP 头部,数据链路层添加以太网协议头部

  • 数据经过路由器、交换机转发,最终达到目标服务器,目标服务器同样解析数据,最终拿到 http 报文,按照对应的程序的逻辑响应回去。

知道 HTTPS 的工作原理吗?

  • 用户通过浏览器请求 https 网站,服务器收到请求,选择浏览器支持的加密和 hash 算法,同时返回数字证书给浏览器,包含颁发机构、网址、公钥、证书有效期等信息。

  • 浏览器对证书的内容进行校验,如果有问题,则会有一个提示警告。否则,就生成一个随机数 X,同时使用证书中的公钥进行加密,并且发送给服务器。

  • 服务器收到之后,使用私钥解密,得到随机数 X,然后使用 X 对网页内容进行加密,返回给浏览器

  • 浏览器则使用 X 和之前约定的加密算法进行解密,得到最终的网页内容


九、负载均衡有哪些实现方式?

DNS:这是最简单的负载均衡的方式,一般用于实现地理级别的负载均衡,不同地域的用户通过 DNS 的解析可以返回不同的 IP 地址,这种方式的负载均衡简单,但是扩展性太差,控制权在域名服务商。

Http 重定向:通过修改 Http 响应头的 Location 达到负载均衡的目的,Http 的 302 重定向。这种方式对性能有影响,而且增加请求耗时。

反向代理:作用于应用层的模式,也被称作为七层负载均衡,比如常见的 Nginx,性能一般可以达到万级。这种方式部署简单,成本低,而且容易扩展。

IP:作用于网络层的和传输层的模式,也被称作四层负载均衡,通过对数据包的 IP 地址和端口进行修改来达到负载均衡的效果。常见的有 LVS(Linux Virtual Server),通常性能可以支持 10 万级并发。

按照类型来划分的话,还可以分成 DNS 负载均衡、硬件负载均衡、软件负载均衡。

其中硬件负载均衡价格昂贵,性能最好,能达到百万级,软件负载均衡包括 Nginx、LVS 这种。

十、说说 BIO/NIO/AIO 的区别?

BIO:同步阻塞 IO,每一个客户端连接,服务端都会对应一个处理线程,对于没有分配到处理线程的连接就会被阻塞或者拒绝。相当于是一个连接一个线程。

NIO:同步非阻塞 IO,基于 Reactor 模型,客户端和 channel 进行通信,channel 可以进行读写操作,通过多路复用器 selector 来轮询注册在其上的 channel,而后再进行 IO 操作。这样的话,在进行 IO 操作的时候再用一个线程去处理就可以了,也就是一个请求一个线程。


AIO:异步非阻塞 IO,相比 NIO 更进一步,完全由操作系统来完成请求的处理,然后通知服务端开启线程去进行处理,因此是一个有效请求一个线程。

十一、那么你怎么理解同步和阻塞?

首先,可以认为一个 IO 操作包含两个部分:

  • 发起 IO 请求

  • 实际的 IO 读写操作

同步和异步在于第二个,实际的 IO 读写操作,如果操作系统帮你完成了再通知你,那就是异步,否则都叫做同步。

阻塞和非阻塞在于第一个,发起 IO 请求,对于 NIO 来说通过 channel 发起 IO 操作请求后,其实就返回了,所以是非阻塞。

十二、谈一下你对 Reactor 模型的理解?

Reactor 模型包含两个组件:

  1. Reactor:负责查询、响应 IO 事件,当检测到 IO 事件时,分发给 Handlers 处理。

  2. Handler:与 IO 事件绑定,负责 IO 事件的处理。

它包含几种实现方式:

单线程 Reactor

这个模式 reactor 和 handler 在一个线程中,如果某个 handler 阻塞的话,会导致其他所有的 handler 无法执行,而且无法充分利用多核的性能。


单 Reactor 多线程

由于 decode、compute、encode 的操作并非 IO 的操作,多线程 Reactor 的思路就是充分发挥多核的特性,同时把非 IO 的操作剥离开。

但是,单个 Reactor 承担了所有的事件监听、响应工作,如果连接过多,还是可能存在性能问题。

多 Reactor 多线程

为了解决单 Reactor 的性能问题,就产生了多 Reactor 的模式。其中 mainReactor 建立连接,多个 subReactor 则负责数据读写。

(转自作者:艾小仙来源:阿里云云栖号)


用户头像

冇先生

关注

还未添加个人签名 2021.05.26 加入

还未添加个人简介

评论

发布
暂无评论
网络篇夺命连环12问