计算机网络
一、协议分层
1.什么是网络协议(protocol)?
协议是指两个或多个网络实体之间交换的报文的格式和顺序, 以及在报文发送和接收后所采取的动作。
即:通信双⽅需要遵守的 统⼀规则,如:语法、语义、同步或规则。
即:通信双⽅需要遵守的 统⼀规则,如:语法、语义、同步或规则。
2.TCP/IP分层模型 和 OSI参考模型
(1)TCP/IP分层模型
-
应用层:是应用程序及其应用层协议存在的地方。应用层协议主要有:HTTP协议、SMTP协议、FTP协议、DNS协议。
HTTP:提供了Web文档的请求和传送。
SMTP:提供了电子邮件报文的传输。
报文(message):位于应用层的信息分组(数据)称为报文。
FTP:提供了两个端系统之间的文件传送。
DNS:⽤来进行域名和IP地址间的转换。 -
传输层(运输层):网络的运输层在应用程序端点之间传送应用层报文。两种运输协议:TCP协议和UDP协议。
TCP:面向连接的服务。确保传递和流量控制。
UDP:面向无连接的服务。无可靠性,无流量控制和拥塞控制。 -
网络层(IP层):负责将数据包从一台主机移动到另一台主机。网络层协议:IP协议、路由选择协议。
IP协议:定义了数据包中的各字段及端系统和路由器如何使用作用于这些字段。
路由选择协议:决定数据包的路由。 - 网络接口层:网络接口层包括数据链路层和物理层,是TCP/IP与各种LAN(局域网)或WAN(广域网)的接口。协议?
(2)OSI参考模型
OSI(Open System Interconnection,开放系统互联)参考模型相较于TCP/IP分层模型附加了两个层——表示层和会话层,同时数据链路层和物理层对应TCP/IP分层模型中的网络接口层,他们的功能是相同的。
- 表示层为在应用程序之间传送的信息提供表示方法的服务,它只关心信息发出的语法和语义,处理所有与数据表示及运输有关的问题,包括转换、加密和压缩。
- 会话层建立在传输层之上,利用传输层提供的服务,使应用程序建立和维持会话,并使会话获得同步,包括了建立校验点和恢复通信的方法。
二、应用层
1.HTTP协议
(1)简介
HTTP(Hyper Text Transfer Protocol)协议: 又称为超文本传输协议,HTTP由一个客户端和一个服务端来实现,运行在不同端系统中的客户端和服务端通过交换HTTP报文进行会话,而HTTP定义了这些报文的结构及进行报文交换时的方式。
HTTP是在TCP协议上运行的,客户端发起 HTTP 请求,服务器做出响应处理后,返回 HTTP 响应报文。
【超文本】超文本就是超越了普通文本的文本,是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。 HTML 就是最常见的超文本。
(2)万维网(WWW)的构建技术
- HTML (HyperText Markup Language):作为页面的文本 标记 语言,用于页面的文本显示。
- HTTP (HyperText Transfer Protocol):超文本传输协议。
- URL (Uniform Resource Locator):统一资源定位符,指定⽂档所在地址,URL组成:<协议>://<主机>:<端⼝>/<路径>?<参数>。
- 1996 年5 ⽉,HTTP/1.0,并记载于 RFC1945。现在 HTTP/1.0,仍然被使用在服务器端
- 1997 年 1 ⽉,发布 HTTP/1.1 ,是目前主流的 HTTP 协议版本
- 现今,HTTP/2.0 正在制订中,但还未得到⼴泛的使用
(4)HTTP/1.1的特点
HTTP/1.1最突出的优点就是简单、灵活、易于扩展。
-
简单:
HTTP的基本报文格式为header+body(请求头请求体、响应头响应体),头部信息也是key-value的简单文本形式,易于理解。 -
★灵活和易于扩展:
HTTP协议⾥的各种请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充;
同时HTTP⼯作在应⽤层(OSI第七层),它的下层可以随意变化:比如HTTPS就是在HTTP与TCP之间增加了SSL/TSL安全传输层,HTTP/3(https://view.inews.qq.com/a/20220524A02BPE00)把TCP换成了基于UDP的QUIC。
-
无状态、明文传输、不安全:
无状态(双刃剑):无状态指的是服务器不会去记忆HTTP的状态(不保存关于客户端的任何信息),所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,但在完成有关联性的操作时会非常麻烦。
例如登录->添加购物车->下单支付等一系列操作都要知道用户的身份,但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。
【对于无状态的解法方案】可以用 Cookie 技术。Cookie 通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。
明文传输(双刃剑):传输过程中的信息方便阅读,通过浏览器的F12控制台(或Wireshark抓包)都可以直接⾁眼查看,但这种信息透明容易导致信息被窃取。
不安全(纯纯的缺点):
使用明文通信,因此内容可能被窃听
不验证通信方的身份,因此可能遭遇伪装
无法证明报文的完整性,因此信息可能已被篡改
可以⽤ HTTPS 的⽅式解决,也就是通过引⼊ SSL/TLS 层,使其变得安全。
(5)HTTP报文格式
-
HTTP请求报文:主要由请求行、请求头、请求体构成。
-
请求行有三个字段:请求方法、URL、HTTP版本号,如:POST /chapter17/user.html HTTP/1.1
-
请求头包含请求的附加信息,以键值对的形式组成。
①Host字段:客户端发送请求时,用来指定服务器的域名。
②Connection 字段:常用于客户端要求服务器使用「 HTTP 长连接」机制,以便其他请求复用。
③Accept 字段:客户端声明自己可以接受哪些数据格式。
- 请求体包含多个请求参数的数据。含回⻋、换行和请求数据(并⾮都有)
-
请求行有三个字段:请求方法、URL、HTTP版本号,如:POST /chapter17/user.html HTTP/1.1
-
HTTP响应报文:主要由响应行、响应头、响应体构成。
-
响应行有三个字段:HTTP协议版本号、状态码、状态码描述,如:HTTP/1.1 200 OK
★五大HTTP状态码:
常见状态码及描述:
200:客户端请求成功
206:partial content 服务器已经正确处理部分GET请求,实现断点续传或同时分⽚下载,该请求必须包含Range 请求头来指示客户端期望得到的范围
301(永久重定向):说明请求的资源已经不存在了,需要用新的URL再次访问。(该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URL 之一。)
302(临时重定向):说明请求的资源还在,但暂时需要用另一个 URL 来访问。(请求的资源现在临时从不同的URI中获得。)
【tips】301 和 302 都会在响应头里使用 Location 字段,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
304:如果客户端发送⼀个待条件的GET请求并且该请求以经被允许,而文档内容未被改变,则返回304,该响应不 包含包体(即可直接使用缓存)
400:表示客户端请求的报文有错误,但只是个笼统的错误码
401:请求需要认证
403:请求的对应资源禁止被访问,并不是客户端的请求出错
404:表示请求的资源在服务器上不存在或未找到
500:与 400 类似,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道
502:通常是服务器作为网关或代理时返回的错误码,表示服务器访问后端服务器发生了错误
503:表示服务器正忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思
-
响应头、响应体与请求头、请求体的作用类似。
①Content-Length 字段:表明本次响应的数据长度。
②Content-Type 字段:用于服务器回应时,告诉客户端,响应数据是什么格式。
-
响应行有三个字段:HTTP协议版本号、状态码、状态码描述,如:HTTP/1.1 200 OK
(6)HTTP请求过程
- 首先在浏览器地址栏中输入页面的URL;
- 浏览器依次在浏览器缓存→操作系统缓存→路由器缓存中寻找匹配的URL,若有则直接显示页⾯内容;
- 若没有,浏览器将发送HTTP请求,在发送请求之前,浏览器需要先进行域名解析(即DNS解析),获取相应的IP地址;
- 获取到IP地址后,浏览器向服务器发起TCP连接,与服务器建立TCP三次握手;
- 握手成功后,浏览器向服务器发送HTTP请求,来请求服务器端的数据;
- 服务器处理请求,将数据返回给浏览器;
- 浏览器收到HTTP响应,查询状态,状态不成功则弹出相应提示;状态成功则读取页面内容、进⾏浏览器渲染、解析HTML源码进行页面展示;
- 关闭TCP连接(四次挥⼿)
(7)HTTP的8种请求方法
- GET:申请获取资源,不对服务器产⽣影响
- POST:客户端向服务器提交数据,会影响服务器,服务器可能动态创建新的资源或更新原有资源
- HEAD:类似GET,仅要求服务器返回头部信息
- PUT:上传某个资源
- DELETE:删除某个资源
- TRACE:用于测试,要求目标服务器返回原始的HTTP请求内容
- CONNECT:用于代理服务器
- OPTION:查询服务器对特定URL支持的请求方法
(8)GET和POST的区别?
二者都是HTTP请求的两种请求方式,底层都是基于TCP/IP协议进行通信的,本质上并无区别,只是被HTTP规定了不同的行为和方式。主要有以下几方面的不同:
- 概念上:GET请求是客户端从服务器获取指定资源,不会对服务器产生影响;POST请求是客户端向服务器提交数据,会影响服务器,服务器可能动态创建新的资源或更新原有资源。
- 请求参数上:GET通过URL携带请求参数,由于浏览器对 URL⼀般都有长度限制(HTTP协议本身对 URL长度并没有做任何规定),所以请求参数也有长度限制;POST的请求参数是位于请求体中,没有长度限制。
- 缓存上:GET会被浏览器主动缓存(如果下⼀次传输的数据相同,就会直接返回缓存中的内容,以求更快的展示数据);POST请求不会被缓存。
-
安全幂等性上:GET是安全幂等的(因为它只进行读操作,⽆论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的);POST是不安全且不幂等的(因为是新增或者提交数据的操作,所以会修改服务器上的资源,且多次提交数据就会创建多个资源)
【补充】 ①安全:HTTP协议中,安全是指请求⽅法不会破坏服务器上的资源;
②幂等:多次执⾏相同的操作,结果都相同。
-
★TCP数据包数量上:GET方法只产生一个TCP数据包,浏览器会把请求头和请求数据⼀起发送出去,服务器响应200 ok(返回数据);POST会产生两个TCP数据包,浏览器会先将请求头发送给服务器,待服务器响应100 continue,浏览器再发送请求数据,服务器响应200 ok(返回数据)。
(9)HTTP的keep-alive
1)简介
早期HTTP1.0协议都是建立在TCP协议基础上,其特点就是传输完数据后,立马就释放掉该TCP连接,也就是短连接/非持续连接(每次都经一个单独的TCP连接)。
HTTP/1.1 版本的默认连接都是长连接,但为了兼容老版本的 HTTP,需要指定 Connection 首部字段的值为 Keep-Alive。
随着技术的发展,一个网页往往需要建立很多次短连接,这大大影响了消息的处理,所以就提出了持续连接(长连接)的概念,也就是让连接保存一段时间,后续的HTTP请求可以复用这个连接继续传输消息,称之为Keep-Alive模式(又称持久连接、连接重用)。Keep-Alive功能使客户端到服务器的连接持续有效,当出现对服务器的后继请求时,避免了建立或者重新建立连接。
主要优势:避免了短连接每次连接时的三次握手和四次挥手的网络交互。
2)如何使用keep-alive?
在HTTP的请求头有两个Tag可以控制keep-alive——Connection:keep-alive 和 Keep-Alive:timeout,它们表示保持持续连接状态的时间为timeout秒。
3)HTTP能不能一次连接多次请求,不等后端返回?
答:可以,HTTP本质是使⽤socket连接,写⼊TCP缓冲是可以连接多次的。
(10)HTTP的优化方案
- TCP复用:将多个客户端的HTTP请求复用到⼀个服务端的TCP连接上
- HTTP复用:将⼀个客户端的多个HTTP请求复用到⼀个TCP连接进行处理
- 内容缓存:将常用内容进行缓存,下⼀次想获取这些内容时,可以直接在内存中获取了
- 压缩:压缩文本数据,减少带宽
- SSL加速:客户端采用HTTPS协议访问服务器时,双方要交换证书、协商密钥、对数据进行加解密,这时服务器性能会急剧下降,SSL加速正是为了解决这种状况而出现的。
-
TCP缓冲:通过采⽤TCP缓冲技术,提⾼服务端响应时间和处理效率
(11)HTTP 1.0、1.1、2.0的比较?
-
HTTP1.0与HTTP1.1区别
- 长连接:HTTP 1.0默认是短连接,若需要设置长连接,则需要设置keep-live参数;HTTP1.1默认是长连接;
- 节约带宽:HTTP 1.1可以只发送header信息,而不带任何body信息,可以节约带宽;
- 管线化:HTTP 1.1允许客户端同时发送多个HTTP请求,不用等待响应。
-
HTTP1.1与HTTP2.0区别
- 传输格式变化:HTTP1.X都是基于文本的;HTTP2.0采用二进制传输数据。
- 多路复用:HTTP2.0采用了多路复用技术,可以并发处理多个请求,支持的并发请求数量就会更多。
- 数据压缩:HTTP1.1不支持header数据的压缩,HTTP2.0对header的数据进行了压缩,这样数据体积小了,在网络上传输就会更快。
- 服务器推送:HTTP2.0中服务器可以把客户端需要的资源随index.html⼀起发送给客户端,省去了客户端重复请求的步骤。同时因为没有发起请求、建立连接等操作,所以静态资源通过服务器推送,可以极大的提高速度。
2.HTTPS
(1)名词释义
- SSL:Secure Socket Layer,安全套接字协议
- TLS:Transport Layer Security,安全传输层协议
- HTTPS(Hyper Text Transfer Protocol Secure):超⽂本安全传输协议,HTTPS = HTTP + SSL/TLS安全协议
(2)简介
HTTPS解决了HTTP不安全的缺陷,在 TCP 和 HTTP 网络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输。
(3)优缺点
-
优点:
- 信息加密:在数据传输过程中,使⽤秘钥加密,安全性更高
- 校验机制:无法篡改通信的内容,篡改了就不能正常显示
- 身份证书:证明报文的完整
-
缺点:
-
需要加解密计算,占⽤CPU资源,需要服务器配置或数目大
- 握手阶段延时较高:在会话前还需进行SSL握手
- 部署成本⾼:需要购买CA证书
-
需要加解密计算,占⽤CPU资源,需要服务器配置或数目大
(4)HTTPS解决了HTTP的哪些问题?怎么解决的?
-
HTTP 存在一定的安全风险:
- 使用明文通信,因此内容可能被窃听
- 无法证明报文的完整性,因此信息可能已被篡改窃听风险(比如强制植入垃圾广告)
-
不验证通信方的身份,因此可能遭遇伪装(比如冒充淘宝网站)
-
HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,可以很好的解决上述的安全问题。怎么解决的?:
-
通过混合加密的方式对信息进行加密;
-
通过摘要算法(哈希函数)来实现信息的完整性;
- 通过将服务器公钥放入到数字证书中,对服务器的身份进行验证。
-
通过混合加密的方式对信息进行加密;
(5)混合加密
HTTPS 通过非对称加密和对称加密相结合的混合加密的方式来保证信息的安全性。
- 在通信建立前,使用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密;
- 在通信过程中,使用对称加密的「会话秘钥」加密明文数据。
采用混合加密的方式的原因:
- 对称加密只使用一个密钥,既做加密又做解密,运算速度快,但是无法做到安全的密钥交换。
-
非对称加密使用两个密钥——公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。
双向加解密:
- 公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,只有私钥持有者才能解密出实际的内容。
- 私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。
(6)摘要算法和数字签名
-
摘要算法——保证数据完整性
为了保证传输内容不被篡改,客户端使用摘要算法(哈希函数)计算出传输内容的唯一哈希值A(但无法通过哈希值推导出内容),将传输内容和哈希值A一起发送给服务器;然后服务器根据传输内容和相同的哈希运算计算出哈希值B,通过比较两个哈希值,如果相同表示数据是完整的;不同表示数据被篡改了。
-
数字签名——验证消息来源(能确认消息是由持有私钥的一方发送的)
通过摘要算法只能确保内容不会被篡改,但是不能保证「内容 + 哈希值A」不会被中间人整个替换,因此还缺少对消息来源的证明。可以通过数字签名对消息的来源进行证明。
客户端使用私钥将通过哈希运算得到的哈希值A进行加密,得到数字签名,将传输内容和数字签名一起发送给服务器;服务器根据传输内容和相同的哈希运算计算出哈希值B,并用公钥将数字签名解密得到哈希值A,通过比较两个哈希值,如果相同说明签名成立;不同说明签名不成立。
(7)数字证书
数字签名只能由私钥拥有者生成,但是私钥拥有者不一定是请求的那个客户端,其他人也可生成一套公钥私钥进行数字签名来冒充请求客户端。这个问题可以通过数字证书来解决。
-
服务器把自己的公钥注册到CA机构,CA机构用自己的私钥将服务器的公钥进行数字签名并颁发数字证书;
“CA机构用自己的私钥进行数字签名”:客户端可以用CA的公钥对CA的身份进行确认,确保证书的合法性。 - 客户端向服务器发送HTTPS请求,服务器将数字证书(服务器公钥+CA数字签名)返回给客户端;
- 客户端拿到证书后使用CA的公钥(已事先嵌入客户端或系统中)对证书进行确认;
-
如果确认证书是可信的就从证书中获取服务器公钥,使用服务器公钥对传输内容进行加密后发送给服务器;
“客户端使用服务器公钥对内容进行加密”:因为这些内容只能给服务器看,所以用服务器公钥进行加密,只有服务器自己的私钥才能对内容解密。 - 服务器用自己的私钥对内容进行解密。
(8)★HTTPS完整请求流程(建立连接的流程)?
HTTPS通过TCP三次握手建立连接后,还需要进行SSL/TLS握手才能进行通信。
-
通信双方经过三次握手建立TCP连接后,客户端向服务器发起加密通信请求(即ClientHello请求),客户端主要向服务器发送以下信息:
①客户端支持的 TLS 协议版本,如 TLS 1.2 版本;
②客户端生成的随机数(Client Random),后面用于生成「会话秘钥」条件之一;③客户端支持的密码套件列表,如 RSA 加密算法。 -
服务器收到请求后,向客户端发出响应(即SeverHello),响应信息有如下内容:
①确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信;
②服务器生成的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一;
③确认的密码套件列表,如 RSA 加密算法;
④服务器的数字证书。 -
客户端收到响应后,通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。 如果证书可信,客户端从证书中取出服务器的公钥,用它加密报文,再向服务器发送如下信息:
①一个随机数(pre-master key),该随机数会被服务器公钥加密;
②加密通信算法改变通知,表示后续信息都将用「会话秘钥」进行加密通信;
③客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key)后就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。 -
服务器收到第三个随机数后,通过协商的加密算法,计算出「会话秘钥」,然后向客户端发送最后的信息:
①加密通信算法改变通知,表示后续信息都将用「会话秘钥」进行加密通信;
②服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
至此整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。
(9)HTTPS一定是安全可靠的吗?
【场景假设】客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个「中间人服务器」,于是客户端是和「中间人服务器」完成了 TLS 握手,然后这个「中间人服务器」再与真正的服务端完成 TLS 握手。
【分析】从客户端的角度来看,其实并不知道网络中存在中间人服务器这个角色。那么中间人就可以解开浏览器发起的 HTTPS 请求里的数据,也可以解开服务端响应给浏览器的 HTTPS 响应数据,也就是说中间人能够 “偷看” 浏览器与服务端之间的 HTTPS 请求和响应的数据。
但是这种情况的发生是有前提条件的,前提是需要用户接受了中间人服务器的证书。中间人服务器与客户端在 TLS 握手过程中,实际上发送了自己伪造的证书给浏览器,而这个伪造的证书是能被浏览器(客户端)识别出是非法的,于是就会提醒用户该证书存在问题(如下图)。如果用户还是选择接受中间人伪造的证书,那么后续整个 HTTPS 通信都能被中间人监听了。所以,这其实并不能说 HTTPS 不够安全,毕竟浏览器都已经提示证书有问题了,如果用户坚决要访问,那不能怪 HTTPS。另外,如果用户的客户端中病毒了,被恶意导入了中间人的根证书,那么在验证中间人证书的时候,就会认为他的证书是合法的,这种情况下,浏览器是不会弹出证书存在问题的风险提醒的。 这其实也不关 HTTPS 的事情,是你电脑中毒了才导致 HTTPS 数据被中间人劫持的。
因此就 HTTPS 协议本身而言它是安全可靠的,即使你成功进行中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书),并不是 HTTPS 不够安全。
3.★HTTPS与HTTP的区别
(1)URL地址和端口号
HTTP的URL地址以 http 开头,默认端口号是80;
HTTPS以 https 开头,默认端口号是443。
(2)安全性
HTTP是在TCP协议上运行的,数据以明文传输,通信双方不能验证彼此的身份,存在安全风险的问题;
HTTPS是运行在SSL/TLS上的HTTP协议,SSL/TLS运行在TCP之上,传输的数据都进行了加密。
HTTPS是运行在SSL/TLS上的HTTP协议,SSL/TLS运行在TCP之上,传输的数据都进行了加密。
(3)建立连接
HTTP连接的建立相对简单,TCP三次握手后就能建立连接,进行数据传输;
HTTPS 在 TCP 三次握手之后,还需要进行 SSL/TLS 的握手过程,才能进行加密数据传输。
(4)资源消耗
HTTPS通过混合加密(非对称+对称)的方式保证传输内容的安全性:在连接建立前采用非对称加密来交换会话密钥;在传输数据时采用对称加密来加密传输内容。因此,HTTPS比HTTP要耗费更多的服务器资源。
4.DNS协议
(1)简介
- DNS(Domain Name System)协议⽤来进行域名和IP地址间的转换
- DNS:⾯向⽤户 IP:⾯向主机
-
域名服务主要是基于UDP实现的,服务器端⼝号为53
-
三种类型的DNS服务器:根域名DNS服务器、顶级域名DNS服务器、权威域名DNS服务器
(2)DNS解析过程
浏览器查询URL对应IP的大致过程:浏览器缓存→操作系统缓存→路由器缓存。
具体过程如下:
具体过程如下:
- ① 找浏览器缓存:浏览器检查浏览器自身DNS缓存中是否有域名对应的DNS缓存,如果有的话返回对应的ip地址;
-
② 找系统缓存:如果没有的话,查看系统的hosts文件(C:\Windows\System32\drivers\etc)是否有域名对应的IP地址,有则返回;
【补充】hosts文件用于将常用的域名与对应IP地址建立关联,相当于本地的一个DNS服务。
-
③路由器缓存: 如果没有的话,浏览器发起DNS系统调用,向本地配置的首选DNS服务器发起域名解析请求(即通过UDP协议,向DNS的53端口发起请求)
- 请求先在运营商DNS服务器(本地服务器)上进行请求,如果找到对应的没有过期的条目,则解析成功;
-
如果没有找到,运营商DNS服务器根据请求进行迭代查询:
- 首先向根域名DNS服务器发送请求,服务器收到请求后,根据域名返回对应的顶级域名DNS服务器的IP地址,并返回给运营商DNS服务器;
- 然后运营商DNS服务器收到返回的顶级域名服务器IP地址后,向顶级域名服务器发送请求,顶级域名服务器收到请求后,根据域名返回对应的权威域名DNS服务器的IP地址,并返回给运营商DNS服务器;
- 运营商DNS服务器收到返回的权威域名服务器IP地址后,向权威域名服务器发送请求,权威域名服务器将目标ip地址返回给运营商DNS服务器;
- 最后运营商DNS服务器将目标ip地址返回给请求的主机,DNS解析完成
(3)集中式DNS服务器存在的问题
对于DNS服务器若采⽤集中式的设计(与之对应的是分布式)有以下问题:
-
单点故障
如果 DNS 服务器崩溃(单点故障),会导致整个网络随之瘫痪。 -
通信容量
一台 DNS 服务器要处理所有 DNS 查询,这种查询级别可能是上百万上千万级,⼀台服务器很难满足。 -
远距离集中式数据库
单个 DNS 服务器不可能邻近所有的⽤户,查询请求肯定会经过低速和拥堵的链路,造成严重的时延。 - 维护成本巨大,需要频繁更新。
(4)DNS三种查询方式
-
递归查询
DNS 服务器接收到DNS客户端的请求,将请求的资源响应给客户端;如果无法找到请求资源记录,则返回错误消息。
在递归查询模式下,用户主机和本地DNS服务器都是只发送一次请求:
用户主机→本地DNS服务器→根域名DNS服务器→顶级域名DNS服务器→权威域名DNS服务器→得到映射结果
用户主机←本地DNS服务器←根域名DNS服务器←顶级域名DNS服务器←权威域名DNS服务器←映射结果
-
迭代查询
DNS 服务器收到DNS客户端请求后,不会直接返回查询结果,而是告诉客户端另一台DNS 服务器地址,客户端再向这台 DNS 服务器发送请求,依次循环直到返回查询结果或发生错误或超时为止。
在迭代查询模式下,用户主机只发送一次请求,本地DNS服务发送不少于一次请求:
本地DNS服务器→根域名DNS服务器,根域名DNS服务器→(顶级域名DNS服务器的IP地址)→本地DNS服务器;
本地DNS服务器→顶级域名DNS服务器,顶级域名DNS服务器→(权威域名DNS服务器的IP地址)→本地DNS服务器;
本地DNS服务器→权威域名DNS客户端,权威域名DNS服务器→(能够解析的查询结果)→本地DNS服务器;
本地DNS服务器→(目标ip地址)→客户端
-
非递归查询
当请求主机查询 DNS 服务器来获取DNS服务器有权访问的记录时通常会进⾏此查询,因为DNS服务器对该记录具有权威性,或者该记录存在于其缓存内。
5.cookie和session
cookie和session都是用来缓存用户信息的。
(1)cookie
1)作用
在第⼀次登录服务器后,服务器会返回⼀些数据(cookie)给浏览器。浏览器将这些数据保存在本地,当浏览器再次发送请求时,会自动把上⼀次请求存储的cookie发送给服务器。服务器可以通过这些数据来判断用户。
2)特点
可存储的数据量有限,⼀般不会超过4KB。
(2)session
1)session与cookie的区别
cookie是存储在本地浏览器,而session存储在服务器。
2)优缺点
2)优缺点
优点:数据存储在服务器更加安全;
缺点:将数据存储在服务器占用了服务器资源。
三、传输层
1.TCP和UDP
(1)★TCP与UDP的区别?(7点)
- 连接:TCP是面向连接的,在传输前需要进行三次握手建立连接;UDP是面向无连接的,不需要三次握手建立连接,立刻传输数据。
- 服务形式:TCP只能一对一提供服务(只能一个客户端与一个服务器建立连接),UDP支持一对一、一对多、多对一、多对多的通信。
- 可靠性:TCP保证了数据的可靠交付,使数据无差错、不重复、不丢失、按序到达; UDP是尽可能交付,不保证可靠性。
- 连接控制机制:TCP拥有流量控制、拥塞控制,保证传输安全性;UDP在网络拥堵情况下也不会降低发送速率。
-
传输方式:TCP基于字节流,没有边界,但是保证传输顺序和可靠性;UDP继承了IP层特性,基于报文,有边界,可能出现乱序和丢包。
【字节流】不包含边界数据的连续流。 - 首部大小:TCP首部长度在不使用选项字段时是20字节,使用选项字段长度增加(可变);UDP首部固定8字节。
-
分片方式:当TCP数据大于接收方MSS(最大报文长度)时,会在传输层对数据进行分片和重组,如果有某个分片丢失,则只需要重传丢失的分片;当UDP数据大于MTU(最大传输单元)时会在网络层对数据进行分片和重组,再传给传输层,如果某个分片丢失,则需要重传所有分片,开销大。
(有关二者分片的详细内容:https://www.cnblogs.com/yanchengwang/p/5919676.html)
(如何理解TCP面向字节流、UDP面向报文?——https://blog.csdn.net/qq_34827674/article/details/123458428)
(2)TCP和UDP分别的应用场景?
由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:
- FTP 文件传输
- HTTP / HTTPS
由于 UDP 面向无连接,它可以随时发送数据,再加上 UDP 本身的处理既简单又高效,因此经常用于:
- 包总量较少的通信,如 DNS 、SNMP 等
- 视频、音频等多媒体通信
- 广播通信
(3)TCP与UDP报文段格式
-
UDP报文段结构
UDP首部只有四个字段,每个字段由两字节(16bit)组成。
目标端口和源端口: 告诉 UDP 协议应该把报⽂发给哪个进程。
包长度: 保存了 UDP ⾸部的⻓度跟数据的⻓度之和。
校验和: 为了提供可靠的 UDP ⾸部和数据⽽设计,接收⽅使⽤检验和来检查该报⽂段中是否出现差错。 -
TCP报文段结构
TCP报文段的首部一般是20字节(选项部分可选,不在20字节里),有与UDP一样的四个字段(红框部分)。
源端⼝号和⽬的端⼝号: ⽤于多路复⽤/分解来⾃或送到上层应⽤的数据。告诉主机报⽂段来⾃哪⾥,该传给哪个上层协议或应⽤程序。
32bit序列号: 该报文段第一个字节的字节流编号,⽤来解决网络包乱序问题。
32bit确认应答号:对发送来的 TCP 报文段的响应,★值是收到的 TCP 报文段的序号值加1,⽤来解决不丢包的问题。
序列号和确认应答号都用于实现可靠数据传输。
4bit首部长度:表示 TCP 的首部有多少字节。由于选项字段的存在,TCP首部长度是可变的,通常选项字段为空,所以首部的典型长度是20字节,最长是60字节。
接收窗口:告诉对⽅本端TCP缓冲区还有多少空间可以接收数据,⽤来做流量控制。
6bit的标志字段:
ACK:用于指示确认应答(acknowledge)号的值是否有效,1表示包含对已成功接收报文段的确认;
RST:用于重置(reset)⼀个已经混乱的连接,或拒绝⼀个无效的数据段或者连接请求;
SYN:用于连接建立过程,1表示请求建立⼀个连接;
FIN:finish,用于断开连接,1表示发送方没有数据要传输了,希望断开连接。
检验和:接收方使⽤检验和来检查该报⽂段是否出现差错(CRC算法),同 UDP。
(4)TCP选项字段
TCP头部的最后⼀个选项字段(options)是可变长度的可选信息,最多包含40字节,因此TCP头部最长可以是60 字节。
-
选项字段可以有三个字段:kind、length、info:
- kind:说明选项类型,有的TCP选项没有后⾯两个字段,仅包含1字节的kind字段。
- length:(如果有的话)指定该选项的总长度。该长度包括kind字段和length字段占据的2字节。
- info:(如果有的话)表示选项的具体信息。
-
常见的TCP选项类型有7种:
-
kind=0,选项表结束(EOP)选项。
⼀个报⽂段仅⽤⼀次,放在末尾⽤于填充,⽤来说明首部已经没有更多的消息,应用数据在下⼀个32位开始处。 -
kind=1,空操作(NOP)选项。
没有特殊含义,⼀般用于将TCP选项的总长度填充为4字节的整数倍。 -
kind=2,最大报文长度(MSS)选项。
TCP连接初始化时,通信双⽅使⽤该选项来协商最⼤报⽂段⻓度。TCP模块通常将MSS设置为 MTU - 40 字节(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。
这样携带TCP报⽂段的IP数据报的⻓度就不会超过MTU(假设TCP头部和IP头部都不包含选项字段,并且这也是⼀般情况),从⽽避免本机发⽣IP分⽚。对以太⽹⽽⾔,MSS值是1460(1500-40)字节。 -
kind=3,窗口扩大因子选项。
TCP连接初始化时,通信双⽅使⽤该选项来协商接收窗⼝的扩大因子。在TCP的头部中,接收窗⼝⼤⼩是⽤16位表示的,故最⼤为65535字节,但实际上TCP模块允许的接收窗⼝⼤⼩远不⽌这个数(为了提⾼TCP通信的吞吐
量)。窗⼝扩⼤因⼦解决了这个问题。
假设 TCP 头部中的接收通告窗⼝⼤⼩是 N,窗⼝扩⼤因⼦(移位数)是 M,那么 TCP 报⽂段的实际接收通告窗⼝⼤⼩是 N*2M,或者说 N 左移 M 位。注意,M的取值范围是 0~14。和 MSS 选项⼀样,窗⼝扩⼤因⼦选项只能出现在同步报⽂段中,否则将被忽略。但同步报⽂段本身不执⾏窗⼝扩⼤操作,即同步报⽂段头部的接收窗⼝⼤⼩就是该 TCP 报⽂段的实际接收窗⼝⼤⼩。当连接建⽴好之后,每个数据传输⽅向的窗⼝扩⼤因⼦就固定不变了。 -
kind=4,选择性确认(Selective Acknowledgment,SACK)选项。
选择性确认选项⽤在连接初始化时,表示是否⽀持 SACK 技术。SACK 技术使 TCP 只需要重新发送丢失的 TCP 报⽂段,⽽不⽤发送所有未被确认的 TCP 报⽂段。
TCP 通信时,如果某个 TCP 报⽂段丢失,则 TCP 会重传最后被确认的 TCP 报⽂段后续的所有报⽂段,这样原先已经正确传输的 TCP 报⽂段也可能重复发送,从⽽降低了 TCP 性能。 -
kind=5,SACK实际⼯作的选项。
该选项的参数告诉发送⽅本端已经收到并缓存的不连续的数据块,从⽽让发送端可以据此检查并重发丢失的数据块。
每个块边沿(edge of block)参数包含⼀个4字节的序号。其中块左边沿表示不连续块的第⼀个数据的序号,⽽块右边沿则表示不连续块的最后⼀个数据的序号的下⼀个序号。这样⼀对参数(块左边沿和块右边沿)之间的数据是没有收到的。因为⼀个块信息占⽤8字节,所以 TCP 头部选项中实际上最多可以包含4个这样的不连续数据块(考虑选项类型和⻓度占⽤的2字节)。 -
kind=8,时间戳选项。
该选项提供了较为准确的计算通信双方之间的往返时间(Round Trip Time,RTT)的方法,为TCP流量控制提供信息。
【补充】往返时间RTT:表示发送方发出最后一个数据到收到最后一个确认信号的时间。
-
kind=0,选项表结束(EOP)选项。
(5)有一个 IP 的服务端监听了一个端口,它的 TCP 最大连接数是多少?
TCP连接的双方是服务器端和客户端,所以对于一个服务端来说,它的最大TCP连接数就是能与多少个客户端建立连接。因为客户端的 IP 和 端口是可变的,所以TCP最大连接数的理论上应该是:
(有几个客户端 * 每个客户端有几个端口)
(有几个客户端 * 每个客户端有几个端口)
对于 IPv4 来说,客户端的 IP 数最多为 2^32 ,一个客户端的端口数最多为 2^16 ,因此服务端单机最大 TCP 连接数约为 2^48 。但是这只是一个理论值,实际上远不能达到这个值,主要受文件描述符和内存的限制:
-
文件描述符限制:每个 TCP 连接都是一个文件,如果文件描述符被占满了,会发生 too many open files。
Linux 对可打开的文件描述符的数量分别作了三个方面的限制:- 系统级:当前系统可打开的最大数量,通过 cat /proc/sys/fs/file-max 查看;
- 用户级:指定用户可打开的最大数量,通过 cat /etc/security/limits.conf 查看;
- 进程级:单个进程可打开的最大数量,通过 cat /proc/sys/fs/nr_open 查看;
- 内存限制:每个 TCP 连接都要占用一定内存,操作系统的内存是有限的,如果内存资源被占满后,会发生 OOM(Out of Memory,内存溢出) 。
2.滑动窗口
(1)什么是滑动窗口?
TCP每发送⼀个数据,都需要⼀次确认应答,然后才能继续发送,这样可以为每个数据包都进行确认应答。但是数据往返时间越长,网络吞吐量越低。
滑动窗口允许发送方发送多个分组而不需要等待确认。
滑动窗口实现就是操作系统开辟的⼀个缓存空间,发送方主机在收到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
滑动窗口实现就是操作系统开辟的⼀个缓存空间,发送方主机在收到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
上图中的 ACK 600 确认应答报⽂丢失,也没关系,因为可以通过下⼀个确认应答进⾏确认:只要发送⽅收到了 ACK 700 确认应答,就意味着接收方收到了 700 之前的所有数据。这种模式就叫累计确认或者累计应答。
(2)窗口大小
滑动窗口受限于在流水线中未确认的分组数不能超过某个最大允许数N,这个N通常被称为窗口长度。换句话来说,窗口大小就是无需等待确认应答,可以继续发送数据的最大值。
在TCP头部中有⼀个字段叫窗口大小(window),接收端通过这个字段告诉发送端自己还有多少缓冲区可以接收数据,这样发送端就可以根据接收端的处理能力来发送数据,不会导致接收端处理不过来。因此通常窗口的大小是由接收方的窗口大小来决定的。
在TCP头部中有⼀个字段叫窗口大小(window),接收端通过这个字段告诉发送端自己还有多少缓冲区可以接收数据,这样发送端就可以根据接收端的处理能力来发送数据,不会导致接收端处理不过来。因此通常窗口的大小是由接收方的窗口大小来决定的。
(3)发送方的滑动窗口
发送方的窗口根据处理的情况分成四个部分:
- #1 是已发送并收到 ACK确认的数据:1到31 字节
- #2 是已发送但未收到 ACK确认的数据:32到45 字节
- #3 是未发送但总大小在接收⽅处理范围内(接收⽅还有空间):46到51字节
-
#4 是未发送但总大小超过接收⽅处理范围(接收⽅没有空间):52字节以后
- 滑动窗口内数据全部发送后,可用窗口为0,但在没收到ACK确认之前⽆法继续发送数据。
-
在收到32~36的ACK确认后,如果滑动窗口大小不变的话,滑动窗口向后移动5个字节,52-56变成可用窗口,可以继续发送数据。
(4)程序是如何表示发送方的四个部分的呢?
TCP 滑动窗口使用三个指针来跟踪在四个传输类别中的每一个类别中的字节。其中两个指针是绝对指针(指特定的序列号),一个是相对指针(需要做偏移)。
- SND.WND :表示发送窗口的大小(大小是由接收方指定的)
- SND.UNA :代表Send Unacknowledged(未被接受的)指针,是一个绝对指针,指向的是已发送但未收到确认的第一个字节的序列号,也就是 #2 的第一个字节
- SND.NXT :代表Send Next指针,也是一个绝对指针,指向未发送但可发送范围的第一个字节的序列号(即下一个要发送的),也就是 #3 的第一个字节。
-
指向 #4 的第一个字节是个相对指针,需要 SND.UNA 指针加上 SND.WND 大小的偏移量,就可以指向#4 的第一个字节了( 32 + 20 = 52 )。
那么可用窗口大小就是:
可用窗口大小 = SND.WND - ( SND.NXT - SND.UNA )
(5)接收方的滑动窗口
接收窗口相对简单一些,根据处理的情况划分成三个部分:
- #1 + #2 是已成功接收并确认的数据(等待应用进程读取);
- #3 是未收到数据但可以接收的数据;
-
#4 是未收到数据还不可以接收的数据;
其中三个接收部分,使用两个指针进行划分:
- RCV.WND:表示接收窗口的大小,它会通告给发送方。
- RCV.NXT:是一个绝对指针,指向期望收到的下一个数据字节的序列号,也就是 #3 的第一个字节。
- 指向 #4 的第一个字节是个相对指针,它需要 RCV.NXT 指针加上 RCV.WND 大小的偏移量,就可以指向#4 的第一个字节了。
3.拥塞控制
(1)拥塞控制与流量控制的区别?
流量控制是一个速度匹配服务(即发送方的发送速率与接收方应用程序的读取速率相匹配),避免发送方的数据填满接收方的缓存,但是并不知道网络的中发生了什么。
⼀般来说,计算机网络都处在⼀个共享的环境,因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是⼀重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大。所以当网络发送拥塞时,TCP会降低发送的数据量,就有了拥塞控制,控制的目的就是避免发送方的数据填满整个网络。
为了在发送方调节所要发送的数据量,定义了⼀个叫做拥塞窗口的概念。
(2)拥塞控制简介
拥塞控制通过拥塞窗口来防止过多的数据注入网络,使得网络中的路由器或者链路过载。
- 拥塞窗口cwnd是发送方维护的⼀个状态变量,根据⽹络拥塞程度⽽变化。
- 发送窗口大小等于拥塞窗口和接收窗口中的最小值,即swnd = min(cwnd, rwnd)。
-
如果网络中没有出现拥塞,cwnd增⼤;出现拥塞,cwnd减⼩。
- 只要发送方没有在规定时间内接收到 ACK 应答报⽂,也就是发生了超时重传,就会认为⽹络出现了拥塞。
拥塞控制算法:慢启动、拥塞避免、拥塞发生、快速恢复。
(3)慢启动
TCP 在刚建立连接完成后,首先是有个慢启动的过程,这个慢启动的意思就是⼀点⼀点的提高发送数据包的数量, 如果一上来就发大量的数据,这不是给网络添堵吗?
慢启动的算法记住⼀个规则就行:当发送方每收到⼀个 ACK,拥塞窗口 cwnd 的大小就会加 1。
这里假定拥塞窗口 cwnd 和发送窗口 swnd 相等,下面举个例子:
- 连接建立完成后,初始化 cwnd = 1 ,表示可以传⼀个 MSS 大小的数据;
- 当收到⼀个 ACK 确认应答后,cwnd 增加 1,于是下⼀次能够发送 2 个;
- 当收到 2 个 ACK 确认应答后,cwnd 增加 2,于是就可以比之前多发2 个,所以下⼀次能够发送 4 个;
-
当收到 4 个 ACK 确认应答后,cwnd 增加 4,于是就可以比之前多发4 个,所以下⼀次能够发送 8 个。
可以看出慢启动算法发包个数是呈指数增长的。那慢启动涨到什么时候是个头呢?
-
有⼀个叫慢启动门限 ssthresh (slow start threshold—阈值、门限)状态变量。
当 cwnd < ssthresh 时,使用慢启动算法。
当 cwnd >= ssthresh 时,使用拥塞避免算法。
(4)拥塞避免算法
⼀般来说 ssthresh 的大小是65535字节,超过后会进入拥塞避免算法。进入拥塞避免算法后的规则是:每当收到⼀个 ACK 时,cwnd 增加 1/cwnd。
拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,虽然还是增长阶段,但是速度缓慢了⼀些。
因为还是在不断增长,所以网络会慢慢进入拥塞状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。当触发了重传机制,也就进入了拥塞发生算法。
(5)拥塞发生算法
当网络出现拥塞时会发生数据包重传,重传机制主要有两种:
- 超时重传
- 快速重传
这两种使用的拥塞发送算法是不同的,接下来分别来说说。
1)超时重传
发生超时重传时的拥塞发生算法:ssthresh 设为 cwnd/2,cwnd 重置为 1,然后再进行慢启动。
可以发现慢启动会突然减少数据流的,但是这种方式太激进了,反应也很强烈,会造成网络卡顿。
2)快速重传
发生快速重传时的拥塞发生算法:当接收方发现丢了⼀个中间包的时候,发送三次前⼀个包的ACK,于是发送端就会快速地重传,不必等待超时再重传。
TCP 认为这种情况不严重,因为大部分没丢,只丢了⼀⼩部分,ssthresh 和 cwnd 变化如下:
在快速重传更新cwnd 和 ssthresh后进入快速恢复算法:
TCP 认为这种情况不严重,因为大部分没丢,只丢了⼀⼩部分,ssthresh 和 cwnd 变化如下:
- ssthresh = cwnd
- cwnd = cwnd/2
(6)快速恢复算法
快速重传和快速恢复算法⼀般同时使用,快速恢复算法认为,既然还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像超时重传那么强烈。在快速重传更新cwnd 和 ssthresh后进入快速恢复算法:
- cwnd = ssthresh + 3 (3 的意思是确认有 3 个数据包被收到了) ;
- 重传丢失的数据包;
- 如果再收到重复的 ACK,那么 cwnd 增加 1;
- 如果收到新数据的 ACK 后,把 cwnd 设置为第⼀步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从重复的 ACK 开始时的数据都已收到,快恢复过程已经结束,可以回到快恢复之前的状态了,即再次进入拥塞避免状态(每当收到⼀个 ACK 时,cwnd 增加 1/cwnd);
可以看到快恢复结束以后cwnd还是比较高的值(超时重传相比),并且后续呈线性增长(拥塞避免)。
4.★建立TCP连接——三次握手
(1)三次握手的过程
TCP是面向连接的协议,所以使用TCP进行通信的时候就要先建立连接,而建立连接是通过三次握手来完成的。
-
一开始,客户端和服务器都处于Close状态,先是服务器主动监听某个端口,处于Listen状态。
- client_isn:客户端初始化序列号
-
server_isn:服务端初始化序列号
【tips】图中的Seq Num是sequence number的缩写,代表序列号的意思。
-
第一次握手:客户端发起第一个报文——SYN报文:
客户端会随机初始化序列号client_isn,将此序号放在TCP首部序列号字段中,同时把SYN标志位置为1,表示SYN报文。接着把SYN报文发生给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN_SENT状态。 -
第二次握手:服务端发起第二个报文——SYN+ACK报文:
服务端收到 SYN 报文后,服务端先随机初始化自己的序列号server_isn,将此序号放在TCP 首部序列号字段中,然后把收到的 client_isn + 1 后填入确认应答号字段,接着把 SYN 和 ACK 标志位置为 1,最后把SYN+ACK报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。 -
第三次握手:客户端发起第三个报文——ACK报文:
客户端收到服务器报文后,向服务器回应ACK报文,把收到的 server_isn + 1 后填入确认应答号字段 ,并将TCP 首部 ACK 标志位置为 1 ,最后把ACK报文发送给服务端,这次报文可以携带客户端到服务器的数据,之后客户端处于 ESTABLISHED 状态。
服务器收到应答报文后,也进入 ESTABLISHED 状态。
【tips】当客户端和服务器都进入ESTABLISHED状态后,客户端和服务器之间就可以开始双向传递数据了。 - 至此,三次握手完成,连接建立。
(2)两次握手和四次握手
几次握手指的是通过发送几次报文,通信双方可以建立连接。
- 两次握手:服务器收到客户端发来的SYN报文,返回SYN+ACK报文后直接进入ESTABLISHED状态,不等客户端确认收到SYN+ACK报文就建立了连接。
-
四次握手:四次握手是指将三次握手时服务器返回的SYN+ACK报文分两次返回,先返回ACK报文,再返回SYN报文。因此四次握手可以优化成三次握手,有了三次握手就没必要四次握手了。
(3)为什么要进行三次握手?不是两次、四次?
①三次握手才可以阻止重复历史连接的初始化;
②三次握手才可以同步双方的初始序列号;
③三次握手才可以避免资源浪费。
-
①三次握手才可以阻止重复历史连接(序列号过期或超时的连接叫历史连接)的初始化(主因):
假设客户端给服务器发送了一个SYN报文(seq=100),但是这个报文由于网络波动被阻塞了,没有到达服务器,此时客户端又发送了一个新的SYN报文(seq=200)【注意不是重传,重传的SYN的序列号是一样的】,让我们看一下三种握手都是怎么做的?
-
三次握手:当旧的SYN报文(seq=100)先到达服务端,服务端会返回⼀个SYN+ACK报文,此时的ACK是100+1;客户端收到后,发现不是想要的200+1,就判断这是⼀个历史连接,客户端就会发送一个RST 报文给服务端,表示中止这⼀次连接。
-
两次握手:两次握手情况下,当服务端收到旧的SYN报文(seq=100)后就建立了连接,但是服务端并不知道这是历史连接,并且在返回给客户端的报文中携带了数据(因为建立了连接所以会携带数据),但是客户端通过收到的SYN+ACK报文,发现这是历史连接;对于客户端来说,它根本来不及在服务端给客户端发送数据前来阻止这个历史连接,导致这个历史连接被创建,服务端白白发送了数据。
- 因此,要解决阻止重复历史连接建立的问题,客户端就必须在服务端发送数据之前来阻止建立历史连接,而这个功能的实现就需要三次握手。
-
三次握手:当旧的SYN报文(seq=100)先到达服务端,服务端会返回⼀个SYN+ACK报文,此时的ACK是100+1;客户端收到后,发现不是想要的200+1,就判断这是⼀个历史连接,客户端就会发送一个RST 报文给服务端,表示中止这⼀次连接。
-
②三次握手才可以同步双方的初始序列号:
- 三次握手:当客户端给服务器发送携带了自己的初始序列号的SYN报文时,需要服务器返回一个ACK报文,表示收到了客户端的SYN报文,同样的在这个ACK报文中还要携带服务器自己的初始化序列号,也就是说服务器返回的是SYN+ACK报文;客户端收到这个SYN+ACK报文后,再发送一个ACK报文来确保服务端的SYN被成功接收;这样一来一回就能保证双方的初始化序列号被可靠同步。
- 两次握手:两次握手只能保证客户端的初始序列号能被服务器成功接收,无法保证服务器的被客户端成功接收(因为服务器光发出去了,不管客户端收没收到都会建立连接)。
-
四次握手:四次握手其实也能够可靠同步双方的初始化序列号,但由于第二步和第三步可以优化成一步,所以就成了三次握手。
-
【tips】为什么要同步通信双方的序列号?
——序列号是实现可靠传输的一个关键因素,其作用如下:
a. 接收方可以根据序列号进行重复数据的去重和按序接收数据;
b. 通过ACK报文中的序列号可以识别发出去的数据包中,哪些已经被对方收到了。
-
③三次握手才可以避免资源浪费:
-
两次握手:假设服务器收到大量来自客户端的SYN报文,因为是两次握手,服务器只要收到一个SYN报文就要建立连接,为这些连接分配资源。因此两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,造成重复分配资源。
-
两次握手:假设服务器收到大量来自客户端的SYN报文,因为是两次握手,服务器只要收到一个SYN报文就要建立连接,为这些连接分配资源。因此两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,造成重复分配资源。
-
总结:TCP 建立连接时,通过三次握手能阻止历史连接的建立,能减少双方不必要的资源开销,能保证双方同步初始化序列号。而两次握手无法防止历史连接的建立,还会造成资源的浪费,也无法可靠的同步双方序列号。三次握手理论上就是最少的可靠连接建立,所以不需要使用更多的通信次数来进行四次握手了。
5.★断开TCP连接——四次挥手
(1)四次挥手的过程
- 客户端打算关闭连接,向服务器发送⼀个TCP首部FIN被置1的FIN报文;
- 服务端收到FIN报文后,先向客户端返回一个 ACK 应答报文;
- 服务端处理完数据后,再向客户端发送 FIN 报文;
- 客户端收到服务端的 FIN 报文后,返回一个 ACK 应答报文,之后进入 TIME_WAIT 状态;
- 服务器收到 ACK 应答报文后,进入 CLOSED 状态,服务端完成关闭连接;
-
客户端在经过 2MSL时间后,自动进入 CLOSED 状态,客户端也完成连接的关闭。
【tips】主动关闭连接的一方才有 TIME_WAIT 状态。
(2) 为什么断开连接需要四次挥手?
断开连接是客户端和服务端协商的一个过程。
客户端向服务器发送 FIN 报文,表示不会再发送数据了,但是还可以接收数据;同时服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
从上面过程可知:
从上面过程可知:
- 服务端通常需要等待完成数据的和处理和发送,所以服务端的 ACK报文 和 FIN报文 一般都会分开发送,因此比三次握手多了一次。
【延迟确认】接收方收到包后,如果暂时没有内容要回复给发送方,则延迟⼀段时间再确认。假如在这个时间范围内刚好有数据需要传输,则和确认包⼀起回复,这种方式也被称为数据捎带。延迟确认只是减轻网络负担,未必可以提升网络性能,有些情况下反而会影响性能。
(3)为什么需要TIME_WAIT状态?
TIME_WAIT 状态的出现,是为了解决网络的丢包和网络不稳定所带来的其他问题。需要 TIME_WAIT 状态有以下两个原因:
-
①防止历史连接中因网络延迟的数据包或者丢失重传的数据包被新的连接(与历史连接的端口号相同)复用。
有相同端口的 TCP 连接被复⽤后,被延迟的相同四元组(TCP四元组可以唯一确定一个连接)的数据包抵达了客户端,客户端有可能正常接收这个过期的报文,这就会产⽣数据错乱等严重的问题。
假设服务端向客户端发送了 Seq=300 的报文和 Seq=301 的报文,因为是处于连接状态的,所以此次报文是夹带着数据的。但是由于网络原因导致 Seq=301 的报文阻塞在网络中;紧接着服务端以相同的四元组重新打开了新连接(即与历史连接的端口号相同的新连接),这时前面被阻塞的 Seq=301 抵达了客户端,而且它的序列号刚好在客户端的接收窗口内,因此客户端会正常接收这个数据报文,但是这个数据报文是上一个连接残留下来的,这样就产生了数据错乱等问题。
就是为了防止历史连接中的数据被后面相同四元组的连接错误的接收,TCP 设计了 TIME_WAIT 状态。这个状态会持续 2MSL 时长,这个时间足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。
-
②保证被动关闭连接的一方,能够正确关闭。
如果没有 TIME_WAIT 状态,客户端发送ACK报文后直接进入CLOSED状态关闭连接,假设第四次挥手的ACK报文丢了,服务器会一直等待这个ACK报文;当客户端想发起连接向服务器发送SYN报文时,服务器会返回RST报文,连接建立会关闭。
有了 TIME_WAIT 状态,即使ACK报文丢失了,客户端在一段时间内仍然能够接收服务器重发的 FIN 报文并对其进行响应,这样大概率能保证最后一个ACK被服务器收到,让服务器也正常关闭连接。
(4)为什么 TIME_WAIT 状态等待的时间是 2MSL?
- MSL 指的是报文最大存活时间( Maximum Segment Lifetime),超过这个时间报文将被丢弃。
-
2MSL:网络中可能存在发送方的数据包,当这些发送方的数据包被接收方处理后⼜会向发送方发送响应,所以一来一回需要等待 2 倍的时间。
比如被动关闭方没有收到断开连接的最后一个 ACK 报文时,就会触发超时,重发 FIN 报文,另一方接收到 FIN 后,会重发 ACK 给被动关闭方,这样一来一回刚好是 2 个 MSL。
可以看到 2MSL时长其实是至少允许报文丢失一次。 - 2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有到达服务端,客户端⼜接收到了服务端重发的 FIN 报⽂,那么 2MSL 时间将重新计时。
(5)TIME_WAIT 过多有什么危害?
- 内存资源占用;
- 对端口资源的占用,一个 TCP 连接至少要消耗⼀个本地端口,如果连接发起方的 TIME_WAIT 状态过多,占满了所有端口资源,会导致无法建立新连接。
6.TCP怎么保证数据的可靠性?
(1)应用数据被分割成 TCP 认为最适合发送的数据块。(2)TCP 给发送的每⼀个包进⾏编号,接收⽅对数据包进⾏排序,把有序数据传送给应⽤层。
(3)校验和
TCP 将保持它⾸部和数据的检验和。这是⼀个端到端的检验和,⽬的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报⽂段和不确认收到此报⽂段。
(4)TCP 的接收端会丢弃重复的数据
(5)流量控制
TCP 连接的每⼀⽅都有固定⼤⼩的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收⽅来不及处理发送⽅的数据,能提示发送⽅降低发送的速率,防⽌包丢失。TCP 使⽤的流量控制协议是可变⼤⼩的滑动窗⼝协议。(TCP 利⽤滑动窗⼝实现流量控制)
(6)拥塞控制:当⽹络拥塞时,减少数据的发
(7)ARQ协议
也是为了实现可靠传输的,它的基本原理就是每发完⼀个分组就停⽌发送,等待对⽅确认。在收到确认后再发下⼀个分组。
(8)超时重传
当 TCP 发出⼀个段后,它启动⼀个定时器,等待⽬的端确认收到这个报⽂段。如果不能及时收到⼀个确认,将重发这个报⽂段。
7.★TCP和UDP中的端口问题合集
(1)TCP和UDP可以使用同一个端口号吗?
可以。
传输层「端口号」的作用,是为了区分同一个主机上不同应用程序的。当主机收到数据包后,可以从 IP 包首部的「协议号」字段知道该数据包是由 TCP 还是 UDP 处理,然后根据 TCP 或者 UDP 首部的「端口号」字段确定要发送给哪个应用程序处理。因此,TCP 和 UDP 各自的端口号相互独立,二者可以使用同一个端口号,并不冲突。
【tips】★在数据链路层中,通过 MAC 地址来寻找局域网中的主机。在网络层中,通过 IP 地址来寻找网络中互连的主机或路由器。在传输层中,需要通过端口进行寻址,来识别同一计算机中同时通信的不同应用程序。
(2)多个 TCP 服务进程可以绑定同一个端口吗?
多个 TCP 服务进程可以绑定不同 ip 地址的相同端口;对于同一 ip 地址的相同端口,会报错——“Address already in use”。
但是如果 TCP 服务进程 A 绑定的地址是 0.0.0.0 和端口 8888,而 B 绑定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么执行 bind() 时候也会出错。因为 0.0.0.0 比较特殊,代表任意地址,包含了192.168.1.100,还是相当于绑定了同一 ip 地址的相同端口。
(3)重启 TCP 服务进程时,为什么会有“Address in use”的报错信息?
当我们重启 TCP 服务进程的时候,意味着通过服务器端发起了关闭连接的操作,然后经过四次挥手后关闭连接。而对于主动关闭方,会在 TIME_WAIT 这个状态里停留大约 2MSL 的时间。TIME_WAIT 状态的连接使用的 IP+PORT 仍然被认为是有效的,所以在同一台机器上就不能绑定这个 IP+PORT 组合了,就会有“Address already in use”的错误。等 TIME_WAIT 状态的连接结束后,重启 TCP 服务进程就能成功。
(4)重启 TCP 服务进程时,如何避免“Address in use”的报错信息?
我们可以在调用 bind 前,对 socket 设置 SO_REUSEADDR 属性。
SO_REUSEADDR 的作用是:如果当前启动的进程绑定的 IP+PORT 与处于 TIME_WAIT 状态的连接占用的 IP+PORT 存在冲突,但是要启动的进程使用了 SO_REUSEADDR 属性,该进程就可以绑定成功。
(5)客户端的端口可以重复使用吗?(客户端可以通过同一个端口发起 TCP 连接请求吗?)
可以。
TCP 连接是由四元组(源IP地址,源端口,目的IP地址,目的端口)唯一确认的,只要四元组中的一个元素发生了变化,那么就表示不同的 TCP 连接,不会因为客户端的端口号相同,而导致连接冲突的问题。
(6)客户端 TCP 连接 TIME_WAIT 状态过多,会导致端口资源耗尽而无法建立新的连接吗?
这取决于客户端是否与同一服务器(即 ip 和端口号相同)建立连接。
- 如果客户端都是与同一个服务器建立连接,那么客户端 TIME_WAIT 状态的连接过多,当端口资源被耗尽,就无法与这个服务器再建立连接了。
- 但是,因为只要客户端连接的服务器不同,端口是可以重复使用的(参考第(5)问)。所以这种情况下就可以建立新的连接了。
(7)如何解决客户端 TCP 连接 TIME_WAIT 过多,导致无法与同一个服务器建立连接的问题?
在客户端开启 net.ipv4.tcp_tw_reuse 内核参数(很好理解,tw_reuse就是time-wait reuse的意思)。
开启后,客户端调用 connect 函数选择端口时,如果已经被同一连接占用,就会判断该连接是否处于 TIME_WAIT 状态,如果处于 TIME_WAIT 状态且持续时间超过了 1 秒,就会重用(reuse)这个连接,然后就可以正常使用该端口与同一服务器建立连接了。
四、Web页面请求
1.Web页面的请求流程和涉及到技术
Web页面的请求流程即在浏览器地址栏输入URL回车后涉及到的流程。
-
①查找DNS缓存(浏览器缓存→本地缓存→路由器缓存→ISP缓存)
- 先查找浏览器的DNS缓存,看是否有目标IP地址;
- 如果浏览器缓存中没有,浏览器就会对操作系统发起系统调用,查询本地缓存;
- 如果本地缓存中没有,浏览器就会查询与之相连的路由器缓存;
- 如果路由器缓存中没有,浏览器会检查ISP缓存(本地通信服务商)。
-
②发起DNS请求(是否同一子网→DNS递归查询请求)
-
首先判断DNS服务器和主机是否在同一子网:如果
- 在同一子网,则采用 ARP (地址解析协议)对 DNS 服务器进行 ARP 查询
- 不在同一子网,则对 默认网关 进行ARP查询
-
如果还是查不到 IP 地址,则根据拿到的 DNS 服务器或者默认网关的 IP 地址进行 DNS 请求:
- 使用53号端口先向本地 DNS 服务器发送 UDP 请求包(此处一般使用 UDP 协议,如果响应包太大,就使用 TCP 协议)。如果没有查到目标 IP 地址,它会发送⼀个递归查询请求,向高层DNS服务器查询,直到查到 IP 地址,然后将结果返回
-
首先判断DNS服务器和主机是否在同一子网:如果
-
③封装TCP数据包
- 将应⽤层传下来的实际数据,在传输层添加TCP⾸部;
- 将传输层传下来的数据在网络层添加IP⾸部;
- 将⽹络层传下来的数据,在数据链路层添加以太网⾸部,并在传输介质中进⾏传输。
-
④浏览器与目标服务器建立TCP连接
- 经过DNS域名解析后,浏览器会收到⽬标服务器的IP和MAC地址,然后经过三次握手后建⽴TCP连接;
- 如果使用HTTP协议(端口号80),浏览器发送请求到服务器,服务器直接返回结果;
- 如果使用HTTPS协议(端口号443),浏览器发送请求到服务器,服务器会返回⼀个以 3 开头的重定向消息,告诉浏览器使⽤的是 HTTPS,IP 没变,只是端⼝号变成 443;完成四次挥手;重新建⽴ TCP 连接,将端⼝号修改为 443,同时沟通好双⽅的使⽤的认证算法、加密和解密算法,在这个过程中也会检查对⽅的 CA 安全证书,采⽤ SSL 加密技术进⾏传输数据。
-
⑤浏览器发送HTTP/HTTPS请求到web服务器
-
⑥服务器处理请求并返回⼀个响应
⼀般响应包含:请求的页面以及状态码,压缩类型,如何缓存的页面,设置的cookie; -
⑦最后通过浏览器渲染HTML骨架、检查HTML标记并发送GET请求获取页面其他元素,如图像、CSS样式、JS文件等,最后显示HTML页面
【tips】静态资源⼀般由浏览器缓存,再次访问时,不用重新请求。
2.web页面请求涉及到的问题
(1)DNS服务器
对于DNS服务器若采⽤集中式的设计(与之对应的是分布式)有以下问题:
对于DNS服务器若采⽤集中式的设计(与之对应的是分布式)有以下问题:
-
单点故障
如果 DNS 服务器崩溃(单点故障),会导致整个网络随之瘫痪。 -
通信容量
一台 DNS 服务器要处理所有 DNS 查询,这种查询级别可能是上百万上千万级,⼀台服务器很难满足。 -
远距离集中式数据库
单个 DNS 服务器不可能邻近所有的⽤户,查询请求肯定会经过低速和拥堵的链路,造成严重的时延。 - 维护成本巨大,需要频繁更新。
-
递归查询
DNS 服务器接收到DNS客户端的请求,将请求的资源响应给客户端;如果无法找到请求资源记录,则返回错误消息。
在递归查询模式下,用户主机和本地DNS服务器都是只发送一次请求:
用户主机→本地DNS服务器→根域名DNS服务器→顶级域名DNS服务器→权威域名DNS服务器→得到映射结果
用户主机←本地DNS服务器←根域名DNS服务器←顶级域名DNS服务器←权威域名DNS服务器←映射结果
-
迭代查询
DNS 服务器收到DNS客户端请求后,不会直接返回查询结果,而是告诉客户端另一台DNS 服务器地址,客户端再向这台 DNS 服务器发送请求,依次循环直到返回查询结果或发生错误或超时为止。
在迭代查询模式下,用户主机只发送一次请求,本地DNS服务发送不少于一次请求:
本地DNS服务器→根域名DNS服务器,根域名DNS服务器→(顶级域名DNS服务器的IP地址)→本地DNS服务器;
本地DNS服务器→顶级域名DNS服务器,顶级域名DNS服务器→(权威域名DNS服务器的IP地址)→本地DNS服务器;
本地DNS服务器→权威域名DNS客户端,权威域名DNS服务器→(能够解析的查询结果)→本地DNS服务器;
本地DNS服务器→(目标ip地址)→客户端
-
非递归查询
当请求主机查询 DNS 服务器来获取DNS服务器有权访问的记录时通常会进⾏此查询,因为DNS服务器对该记录具有权威性,或者该记录存在于其缓存内。
(3)HTTPS三次握手的过程
五、RPC远程过程调用
RPC:Remote Procedure Call,远程过程调用,借助RPC可以像调用本地服务一样地调用远程服务。
RPC的本质是提供了⼀种轻量无感知的跨进程通信的方式。
RPC的本质是提供了⼀种轻量无感知的跨进程通信的方式。
1.RPC架构设计组成
RPC技术在架构设计上有四部分组成,分别是:客户端、客户端存根、服务端、服务端存根。
- 客户端(Client):服务调用发起方,也称为服务消费者。
- 客户端存根(Client Stub) :该程序运行在客户端所在的计算机上,主要用来存储要调用的服务器的地址,负责将客户端请求远端服务器程序的数据信息打包成数据包,通过网络发送给服务端Stub程序;还要接收服务端Stub程序发送的调用结果数据包,并解析返回给客户端。
- 服务端(Server):远端的计算机上运行的程序,其中有客户端要调用的方法。
- 服务端存根(Server Stub):接收客户Stub程序通过网络发送的请求消息数据包,并调用服务端中真正的程序功能方法,完成功能调用;其次,将服务端执行调用的结果进行数据处理打包发送给客户端Stub程序。
2.RPC调用流程
- 客户端调用函数(函数3个参数:待调⽤的接口名+函数名,待调⽤函数的形参和接收结果的指针)
- 客户端存根收到调⽤之后将 待调⽤的接⼝名和函数名、待调⽤函数的参数和执⾏函数后接收执⾏结果的指针类型 打包序列化成二进制数据,通过网络传输到服务端
- 服务端反序列化从客户端传来的数据,根据反序列化后的数据去找到并执行客户端需要调用的函数
- 将函数执行的结果序列化成二进制数据,通过网络传输给客户端
- 客户端反序列化收到的⼆进制数据,得到执行结果
3.RPC 的架构???
- 传输层(TCP传输插件,HTTP传输插件)
- 协议层(协议插件,序列化插件,解压缩插件)
- 集群层(服务发现插件,连接管理插件,负载均衡插件,路由插件,容错插件,配置管理插件)
- 入口层(动态代理插件,链路追踪插件,过滤链插件)
4.服务发现的模式
(1)CAP理论
- Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致。
- Availability(可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。
-
Partition tolerance (分区容错性):
Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接(没有宕机),形成独立分区。Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务。
(2)CP与AP
服务发现的模式分为 CP 模式 和 AP 模式。
- AP 模式:保证了可用性和分区容错性。各子事务分别执行和提交,允许临时出现结果不一致,然后采用弥补措施恢复数据即可,实现数据的最终一致(弱一致)。
- CP 模式:保证了一致性和分区容错性。各子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态(基本可用)。
(3)CP模式的例子和存在的问题
ZooKeeper是CP设计,它的一大特点就是强一致性。ZooKeeper 集群的每个节点的数据每次发生更新操作,都会通知其它 ZooKeeper 节点同时执行更新。
用Zookeeper作为服务注册中心时:
- 服务平台管理端创建⼀个服务根目录
- 当服务提供方发起注册时,会在提供方目录中创建一个临时节点,存储自己的注册信息
- 当服务调用方(服务请求方)发起订阅时,会在调用方目录中创建一个临时节点,存储自己的信息,同时会监控提供方目录中所有的服务节点数据
- 当提供方目录下有节点数据发生变更时,ZooKeeper 就会通知给发起订阅的服务调用方
CP 存在⼀个问题:当超大规模集中上线的时候,大量的服务注册,就会导致 zookeeper 集群 CPU 飙升,最后不能工作。
(问题的详细描述:当连接到 ZooKeeper 的节点数量特别多,读写特别频繁,且 ZooKeeper 存储的目录达到一定数量的时候,ZooKeeper 将不再稳定,CPU 持续升高,最终宕机。而宕机之后,由于各业务的节点还在持续发送读写请求,刚一启动,ZooKeeper 就因无法承受瞬间的读写压力,马上宕机。)
(问题的详细描述:当连接到 ZooKeeper 的节点数量特别多,读写特别频繁,且 ZooKeeper 存储的目录达到一定数量的时候,ZooKeeper 将不再稳定,CPU 持续升高,最终宕机。而宕机之后,由于各业务的节点还在持续发送读写请求,刚一启动,ZooKeeper 就因无法承受瞬间的读写压力,马上宕机。)
对于上面的问题可以牺牲强⼀致性,选择AP的最终⼀致,采⽤消息总线机制,可以⽤消息队列来缓存。
- 注册中心节点收到注册请求的时候,服务列表发⽣变化,会发送⼀个消息到消息总线中,每个消息都有⼀个递增的版本号
- 消息总线会主动推送消息到各个注册中⼼中,注册中⼼也会定时拉取消息,获取到的消息放到消息回放中,相当于⼀个接⼝,⽤来存可以调⽤的⽅法,只存⼤于本地版本号的消息,从⽽实现⼀致性
- 消费者订阅从注册中⼼内存获取到所有接⼝信息,然后存到消费者缓存⾥
- 采⽤推拉模式,消费者可以及时的拿到服务端中变化的情况和内存缓存的数据合并
(4)如何判断实例是否健康?——监控的原理
基于心跳机制监测服务状态:服务调用方定时向提供⽅发送心跳包来判断提供方的健康状态,⽐如说在⼀定时间内连续发送的包,失败的次数大于设置的最大失败上限,就得把健康转换亚健康,如果⼀个时间段内根本没成功过,从亚健康转换到死亡,具体的失败次数看个⼈的设置。在有些场景下根据失败数来定义⼀个连接是否健康不是特别的准确,可以计算可用率(在⼀个时间段内,成功个数/总发包的个数)来判断是否健康。
三种健康状态:健康、亚健康、死亡。除了死亡不能转换成亚健康,其他的都可以双向转换。
(5)RPC的路由策略和负载均衡
- 路由策略:主要应用的是灰度发布,平滑切换:比如可以先发布少量实例观察是否有异常,再根据观察的情况,选择发布更多实例还是回滚已经上线的实例。
- 负载均衡:RPC中实现智能负载,根据不同的场景智能的调整每个节点的权值。
六、