冲刺之路(网络)

线程与进程

进程是 CPU资源分配的最小单位;线程是 CPU调度的最小单位

相信大家经常会听到 JS 是单线程执行的,但是你是否疑惑过什么是线程?

讲到线程,那么肯定也得说一下进程。本质上来说,两个名词都是 CPU 工作时间片的一个描述。

进程描述了 CPU 在运行指令及加载和保存上下文所需的时间,放在应用上来说就代表了一个程序。线程是进程中的更小单位,描述了执行一段指令所需的时间。

把这些概念拿到浏览器中来说,当你打开一个 Tab 页时,其实就是创建了一个进程,一个进程中可以有多个线程,比如渲染线程、JS 引擎线程、HTTP 请求线程等等。当你发起一个请求时,其实就是创建了一个线程,当请求结束后,该线程可能就会被销毁。

上文说到了 JS 引擎线程和渲染线程,大家应该都知道,在 JS 运行的时候可能会阻止 UI 渲染,这说明了两个线程是互斥的。这其中的原因是因为 JS 可以修改 DOM,如果在 JS 执行的时候 UI 线程还在工作,就可能导致不能安全的渲染 UI。这其实也是一个单线程的好处,得益于 JS 是单线程运行的,可以达到节省内存,节约上下文切换时间,没有锁的问题的好处。当然前面两点在服务端中更容易体现,对于锁的问题,形象的来说就是当我读取一个数字 15 的时候,同时有两个操作对数字进行了加减,这时候结果就出现了错误。解决这个问题也不难,只需要在读取的时候加锁,直到读取完毕之前都不能进行写入操作。

HTTP/2

在 HTTP/1 中,每次请求都会建立一次HTTP连接,也就是我们常说的3次握手4次挥手,这个过程在一次请求过程中占用了相当长的时间,即使开启了 Keep-Alive ,解决了多次连接的问题,但是依然有两个效率上的问题:

第一个:串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
第二个:连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。

HTTP/2的多路复用就是为了解决上述的两个性能问题。

在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。

帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

UDP

UDP 与 TCP 的区别是什么?

首先 UDP 协议是面向无连接的,也就是说不需要在正式传递数据之前先连接起双方。然后 UDP 协议只是数据报文的搬运工,不保证有序且不丢失的传递到对端,并且UDP 协议也没有任何控制流量的算法,总的来说 UDP 相较于 TCP 更加的轻便。

面向无连接

首先 UDP 是不需要和 TCP 一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。

并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。

具体来说就是:

  • 在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
  • 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作

不可靠性

首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。

并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。

再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP

高效

虽然 UDP 协议不是那么的可靠,但是正是因为它不是那么的可靠,所以也就没有 TCP 那么复杂了,需要保证数据不丢失且有序到达。

因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的。

UDP头部

UDP 头部包含了以下几个数据

  • 两个十六位的端口号,分别为源端口(可选字段)和目标端口
  • 整个数据报文的长度
  • 整个数据报文的检验和(IPv4 可选 字段),该字段用于发现头部信息和数据中的错误

传输方式

UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。

Post 和 Get 的区别?

首先先引入副作用和幂等的概念。

副作用指对服务器上的资源做改变,搜索是无副作用的,注册是副作用的。

幂等指发送 M 和 N 次请求(两者不相同且都大于 1),服务器上资源的状态一致,比如注册 10 个和 11 个帐号是不幂等的,对文章进行更改 10 次和 11 次是幂等的。因为前者是多了一个账号(资源),后者只是更新同一个资源。

在规范的应用场景上说,Get 多用于无副作用,幂等的场景,例如搜索关键字。Post 多用于副作用,不幂等的场景,例如注册。

在技术上说:

  • Get 请求能缓存,Post 不能
  • Post 相对 Get 安全一点点,因为Get 请求都包含在 URL 里(当然你想写到 body 里也是可以的),且会被浏览器保存历史纪录。Post 不会,但是在抓包的情况下都是一样的。
  • URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的
    Post 支持更多的编码类型且不对数据类型限制

常见状态码

200 OK

表示请求被服务器正常处理。最常见的就是这个了。随着这个状态码返回的信息跟你的请求方法有关。比如GET请求,请求的资源会作为响应实体返回。而HEAD请求,信息只存在于响应报文首部,因为它不会返回报文实体,只返回报文首部

200ok

204 No Content

表示请求已成功处理,但是没有内容返回(就应该没有内容返回的状况)。也就是返回的响应报文中没有报文实体(其实是没有报文实体的主体部分)。浏览器向服务器发送请求后收到了204,那么浏览器页面不会发生更新。一般用在只是客户端向服务器发送信息,而服务器不用向客户端返回什么信息的情况

204

206 Partial Content

表示服务器已经完成了部分GET请求(客户端进行了范围请求)。响应报文中包含Content-Range指定范围的实体内容

206

301 Moved Permanently

永久重定向,表示请求的资源已经永久的搬到了其他位置。就是说资源已经被分配了新的URI
。新的URI应该提示在响应报文的Location首部字段。只要不是HEAD请求,响应实体应该包含新URI的超链接和简短的说明

301

302 Found

临时重定向,表示请求的资源临时搬到了其他位置。请求的资源暂时被配到到了新的URI。和301很像,只不过资源是临时移动,资源在将来可能还会改变。同样地,新的临时URI应该提示在响应报文的Location首部字段。只要不是HEAD请求,响应实体应该包含新URI的超链接和简短的说明

302

304 Not Modified

表示客户端发送附带条件的请求(GET方法请求报文中的IF…)时,条件不满足。返回304时,不包含任何响应主体。虽然304被划分在3XX,但和重定向一毛钱关系都没有

304

307 Temporary Redirect

临时重定向,和302有着相同含义。尽管302标准禁止POST变为GET,但没人听他的。而307就会遵照标准,不会从POST变为GET。但处理响应行为,各个浏览器可能不同

307

400 Bad Request

表示请求报文存在语法错误或参数错误,服务器不理解。服务器不应该重复提交这个请求。需要修改请求内容后再次发送

400

401 Unauthorized

表示发送的请求需要有HTTP认证信息或者是认证失败了。返回401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部以质询用户信息。浏览器初次接受401时,会弹出认证窗口

401

403 Forbidden

表示对请求资源的访问被服务器拒绝了。服务器可以对此作出解释,也可以不解释。想说明的话可以在响应实体的主体部分描述原因。比如说你可能没有访问权限

403

404 Not Found

表示服务器找不到你请求的资源。也有可能服务器就是不想给你然后骗你找不到(⊙ˍ⊙)。而且大多服务器都是这么玩这个状态码的

404

500 Internal Server Error

表示服务器执行请求的时候出错了。可能是Web应用有bug或临时故障。更有可能是服务器源代码有bug…

500

503 Service Unavailable

表示服务器超负载或正停机维护,无法处理请求。如果服务器知道还需要多长时间,就写入Retry-After首部字段返回

503

0%