【java总结】计算机网络-HTTP篇

本内容参考了多位大佬,几十篇博客整理出来的,方便自己的复习,同时有不全面,不正确的内容欢迎补充

HTTP

这个协议对于网络工程师来说,他只是一个协议而已,但对于我们java工程师,或者前端工程师,或者其他非网络计算机从业者都太重要了。我们java开发的很大部分都是web应用,。我们对Web的操作都是通过HTTP协议来进⾏传 输数据的,前端也是很直接的利益相关(怎么有股知乎的味道。)总而言之,Http就是Web通信的基础,这是我们必学的。我一定要总结的全面,透彻。方便自己,方便大家。

Http基本概念

HTTP全称是 HyperText Transfer Protocal,即:超文本传输协议。是互联网上应用最为广泛的一种网络通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。目前我们使用的是HTTP/1.1 版本

前面不是说了网络的分层概念吗,我们的HTTP协议是在最上层,也就是应⽤层。这是最贴近我们的程序员的层次。

我们逐步一点点来看,解决一个又一个小概念,争取建立一个完整的HTTP体系

最终解决一个大的问题:在浏览器输入 URL 后发生了什么?

URI 和 URL 有什么区别?

URI:统一资源标识符(Uniform Resource Identifier),就是在某一规则下能把一个资源独一无二地标识出来。它可以理解成是一个资源的名字,比如积木,jimu98甚至jimu98@foxmail.com或者是aaa.html,只要可以唯一的标识一个名字,那么我们就把他称作uri,甚至https://www.jimu98.cn/aaa.html也是一个URI(这个不是应该叫URL,别着急)

URI:统一资源标识符(uniform resource identifier),比如https://www.jimu98.cn/aaa.html

其实,我们可以发现,URI强调的是给资源标记命名,URL强调的是给资源定位,但是你会发现,URL显然比URI包含信息更多,我通过URL也可以知道自己的资源名字可能是aaa.html,并且我还知道了他的地址.

所以大多数情况下大家觉得给一个网络资源分别命名和给出地址太麻烦,干脆就用地址既当地址用,又当标记名用

所以,URL也充当了WWW万维网里面URI的角色,但是他比URI多了一层意义,我不光知道你叫什么,我还知道你在哪里。

我们在浏览器输入的都是URL,因为我们输入的目的是为了找到某一个资源。

DNS:负责解析域名

当我们需要访问一个远程资源的时候,必然要和他建立连接(建立TCP,或者UDP连接,基于IP协议)

所以我们要知道他的地址,可是随着互联网的发展,越来越多的web应用进入大家视线,比如我们访问一些常用的网站,www.baidu.com www.jd.com 这些时候,我们明明输入的不是ip。

其实让我们记IP,也是可以访问的,但是你愿意记那么长的数字吗,反正我不愿意,于是乎DNS 域名解析协议 诞生了,他就可以把一个特殊含义的域名转换成一个IP地址。

但是你想啊,你想要用baidu这个名字,别人也想,那到底该给谁呢。于是肯定有专门的管理机构去统一规范。

但是,我们还有一个叫做本地DNS的东西,通过配置Host文件,去自定义一个域名,实现本地映射。

DNS工作流程:

1、在浏览器中输入www.baidu.com 域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个ip地址映射,完成域名解析。

2、如果hosts里没有这个域名的映射,则会查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。

3、如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析记过给客户端,完成域名解析,此解析具有权威性。

4、如果要查询域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。

5、如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(baidu.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找baidu.com域服务器,重复上面的动作,进行查询,直至找到www.baidu.com 主机。

6、如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把请求转至上上级,以此循环。不管是本地DNS服务器用是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。

HTTP请求报文

http请求由三部分组成,分别是:请求行、请求报头、空行、请求数据

可以分别理解成我使用什么方法,我支持什么格式,我的格式说完了,我的正式数据

image-20200729170117264

请求行

请求行由请求方法、URL字段和HTTP协议的版本组成,格式如下

Method Request-URI HTTP-Version CRLF

其中 Method 表示请求方法;GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS(可选项)

Request-URI是一个统一资源标识符;(前面也说过了)

HTTP-Version表示请求的HTTP协议 版本;(后面说版本的区别)

CRLF表示回车和换行(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。

请求报头

通用报头:(现在在解释请求报文,后面还有响应报文,他们两公用的报头)

Date:表示消息产生的日期和时间。
Connection:允许发送指定连接的选项。例如指定连接是连续的;或者指定“close”选项,通知服务器,在响应完成后,关闭连接。
Cache-Control:用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制)。

//————————————————–

请求报头:(不同的报头在不同的http版本种诞生时间不同,可以看后面版本了解)

Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
User-Agent:发送请求的浏览器类型、操作系统等信息。
Accept:客户端可识别的内容类型列表,用于指定客户端接收哪些类型的信息。
Accept-Charset请求报头域用于指定客户端接受的字符集 。
Accept-Encoding:客户端可识别的数据编码。
Accept-Language:表示浏览器所支持的语言类型。
Authorization请求报头域主要用于证明客户端有权查看某个资源。
Connection:允许客户端和服务器指定与请求/响应连接有关的选项。例如,这时为Keep-Alive则表示 保持连接。
Transfer-Encoding:告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式。

//————————————————–

实体报头:(用来定义被传送数据的类型,既可用于请求,又可用于响应)

Content-Type:发送给接收者的实体正文的媒体类型。
Content-Lenght:实体正文的长度。
Content-Language:描述资源所用的自然语言。
Content-Encoding:实体报头被用作媒体类型的修饰符。它的值指示了已经被应用到实体正文的附加 内容的编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。
Last-Modified:实体报头用于指示资源的最后修改日期和时间。
Expires:实体报头给出响应过期的日期和时间。

空行

就是告诉服务器,我的请求头到此为止

请求数据

在get中,数据就在url中体现了,所以这里的数据指的在post提交中的数据,至于PUT、DELETE这些,他们其实也可以理解成post

image-20200729172717402

HTTP响应报文

HTTP 的响应报文由状态行、响应报头、空行、响应正文 (和请求体相当类似)

状态行

就是告诉我们 请求的数据是否找到,如果没找到是因为啥,返回一些状态码(404大家都遇到过吧)

1xx:表明服务端接收了客户端请求,客户端继续发送请求;
2xx:客户端发送的请求被服务端成功接收并成功进行了处理;
3xx:服务端给客户端返回用于重定向的信息;
4xx:客户端的请求有非法内容;
5xx:服务端未能正常处理客户端的请求而出现意外错误。

2xx:
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回)
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。

3xx:
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307 302相同,但不会把POST请求变成GET

4xx:
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;

5xx:
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;

突然想到某个老师教过,当你遇到404错误,你给用户返回一个503,显得你网站特别火爆(啊哈哈哈哈哈哈)

也就是说,其实看到某些状态码的时候,也不一定可信,因为后台可以改掉

Get与POST的区别

GET与POST是我们常用的两种HTTP Method(就是你在前端form表单那里写的,或者你后台用@PostMapping接收的那个)

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET产生的URL地址可以被收藏,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。

但是,GET和POST的底层都是TCP/IP,你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

但是不同的浏览器对数据量有所限制,业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。

如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到。

还有一个比较重要的区别,很多面试笔记里面都没有写这一条()

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。

并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

以上就是post和get全部区别的

image-20200729192410542

其实HTTP协议中还⽀持着其他的⽅法,⽐如:Input、Delete、OPTIONS很多这样的⽅法。

⽽由于常⽤,于是我们也可能仅仅知道GET和POST⽅法了。

HTTP提供⽅法的⽬的就是为了告知服务器该客户端想进⾏什么操作。当HTTP是OPTIONS⽅法的时候, 服务器端就会返回它⽀持什么HTTP⽅法。 当然了,现在RESTful盛⾏,也就是充分利⽤了HTTP协议的这些⽅法

RESTful 以后再专门总结一下(不然我怎么水博客)

HTTP协议版本详解

版本这里有些枯燥,都是些知识点,作为了解可以跳过

到现在为⽌,HTTP协议已经有四个版本了:

  • HTTP/0.9

    HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。

  • HTTP1.0

    引入了新的命令POST和HEAD(http数据头部)命令,可自定义类型, 常见Content-Type值:text/xml image/jpeg audio/mp3

    同时也开始支持cache,就是当客户端在规定时间内访问统一网站,直接访问cache即可。

    但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接,就是不支持keepalive。

  • HTTP1.1

    新增方法:PUT、PATCH、OPTIONS、DELETE,引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。

  • HTTP/2

    HTTP2.0是SPDY(谷歌公司研发的https的一种协议)的升级版
    1.头信息和数据体都是二进制,称为头信息帧和数据帧
    2.复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,且不用按顺序一一对应,避免了“队头堵塞“,此双向的实时通信称为多工(Multiplexing)
    3.引入头信息压缩机制(header compression),头信息使用gzip或compress压缩后再发送;客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,不发送同样字段,只发送索引号,提高速度
    4.HTTP/2 允许服务器未经请求,主动向客户端发送资源,即服务器推送(server push)

  • HTTP/3

HTTP1.0和HTTP1.1区别

HTTP1.0和HTTP1.1最主要的区别就是: HTTP1.1默认是持久化连接!

在HTTP1.0默认是短连接:简单来说就是:每次与服务器交互,都需要新开⼀个连接!

在HTTP1.1中默认就使⽤持久化连接来解决:建⽴⼀次连接,多次请求均由这个连接完成!(如果阻塞 了,还是会开新的TCP连接的)

HTTP 1.1增加host字段

HTTP 1.1中引⼊了 Chunked transfer-coding ,范围请求,实现断点续传(实际上就是利⽤ HTTP消息头使⽤分块传输编码,将实体主体分块传输)

HTTP 1.1管线化(pipelining)理论,客户端可以同时发出多个HTTP请求,⽽不⽤⼀个个等待响应之 后再请求

仅仅是提出了理论,浏览器默认关闭HTTP pipelining!

HTTP2和HTTP1.1的区别

多工

管线化(pipelining)和⾮管线化的区别:

image-20200729163522493

HTTP Pipelining其实是把多个HTTP请求放到⼀个TCP连接中⼀⼀发送,⽽在发送过程中不需要等 待服务器对前⼀个请求的响应;只不过,客户端还是要按照发送请求的顺序来接收响应!

在HTTP1.0中,发送⼀次请求时,需要等待服务端响应了才可以继续发送请求。 在HTTP1.1中,发送⼀次请求时,不需要等待服务端响应了就可以发送请求了,但是回送数据给客户端的时候,客户端还是需要按照响应的顺序来⼀⼀接收

所以说,⽆论是HTTP1.0还是HTTP1.1提出了Pipelining理论,还是会出现阻塞的情况。从专业的 名词上说这种情况,叫做线头阻塞(Head of line blocking)简称:HOLB

HTTP2与HTTP1.1最重要的区别就是解决了线头阻塞的问题!其中最重要的改动是:多路复⽤ (Multiplexing)

image-20200729164525340

二进制协议

HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议

数据流

HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。

头信息压缩

HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。

HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

服务器推送

HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

HTTP是不保存状态的协议

HTTP是⽆状态的,也就是说,它是不对通信状态进⾏保存的。它并不知道之前通信的对⽅是谁。这样 设计的⽬的就是为了让HTTP简单化,能够快速处理⼤量的事务!

但是,我们经常是需要知道访问的⼈是谁,比如当用户往购物车中添加了商品,web 应用必须在用户浏览别的商品的时候仍保存购物车的状态,以便用户继续往购物车中添加商品。(你说保存在用户的数据库里面,那首先得登录吧,我们平时用的京东之类的购物网站可不是这样,未登录状态下就可以添加购物车)于是就有了Cookie技术了。

什么是Cookie?

cookie 是浏览器的一种缓存机制,它可用于维持客户端与服务器端之间的会话。由于下面一题会讲到session,所以这里要强调cookie会将会话保存在客户端(session则是把会话保存在服务端)

  1. 首先用户在客户端浏览器向服务器发起登陆请求(或者不登录,但是第一次访问同样会给你一个cookie)
  2. 登陆成功后,服务端会把登陆的用户信息设置 cookie 中,返回给客户端浏览器
  3. 客户端浏览器接收到 cookie 请求后,会把 cookie 保存到本地(可能是内存,也可能是磁盘,看具体使用情况而定)
  4. 以后再次访问该 web 应用时,客户端浏览器就会把本地的 cookie 带上,这样服务端就能根据 cookie 获得用户信息了

什么是session?

刚才说的cookie一个重要概念就是保存在本地,那如果我想区分用户权限,有一个用户是普通用户,我给了他VIP1权限,并且保存在了他的CK里面,但是他自己改成了VIP15,然后我的网站判断这个人拥有全部权限。。。。。于是。。。。。。

很明显,这样是不安全的,于是,类似的又有了一个session的机制,session把会话内容保存在服务器端

  1. 首先用户在客户端浏览器发起登陆请求
  2. 登陆成功后,服务端会把用户信息保存在服务端,并返回一个唯一的 session 标识给客户端浏览器。
  3. 客户端浏览器会把这个唯一的 session 标识保存在起来(一般保存在ck里面)
  4. 以后再次访问 web 应用时,客户端浏览器会把这个唯一的 session 标识带上,这样服务端就能根据这个唯一标识找到用户信息。

大家会不会有一个疑问,说生成了一个session,又保存到了我的ck里面,那岂不是还是不安全,但是,我们可以抓包看一下

image-20200729195513482

我们能从这么一个字符串看出任何有效信息吗(一般来说,我们都能往服务器存数据了,应该没人往前台写隐私信息吧,emmmm~应该不会吧)他只是给了我们一个ID,有效信息都在服务器,他会根据我们的ID去服务器查找有效信息,然后返回对应内容。

session和cookie有什么区别

  1. cookie 是浏览器提供的一种缓存机制,它可以用于维持客户端与服务端之间的会话
  2. session 指的是维持客户端与服务端会话的一种机制,它可以通过 cookie 实现,也可以通过别的手段实现。
  3. 如果用 cookie 实现会话,那么会话会保存在客户端浏览器中
  4. 而 session 机制提供的会话是保存在服务端的。

HTTPS协议

本块知识对细节要求较高,还是希望大家可以了解下ssl证书,以及非对称加密之类的概念

推荐先阅读码农翻身中关于https的小故事,然后再来理解https

Http的缺点

  1. 通信使用明文不对数据进行加密(内容容易被窃听)
  2. 不验证通信方身份(容易伪装)
  3. 无法确定报文完整性(内容易被篡改)

不安全:大家还记得我在计算机网络基础篇里面说的联网过程吗

从你家的网线出发,到小区的交换机,再到城市中央的路由器,再到小伙伴的小区交换机,再到小伙伴的电脑桌面。

任意一个环节都可以接入一台电脑,然后抓包,数据是可以被抓下来的。

比如我们传输一段 password:123456,那么黑客就直接可以看到了

但是我们传输一段 password:123456,使用加密技术之后 黑客可能看到的就是 E10ADC3949BA59ABBE56E057F20F883E

因此我们应该使用加密技术,但是码农翻身中 张大胖和Bill 的聊天,也指出了问题,如果中间人获取了他们的公钥,然后进行中间人攻击,那又失去了他的安全性。

于是乎,他们把自己的公钥交给,权威机构生成证书,权威机构在保证自己绝对安全的情况下,才能为整个互联网的安全做背书。

ssl证书

SSL 协议就是用来解决 HTTP 传输过程的不安全问题,到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。

很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

(个人认为,大家还是喜欢把他叫做SSL,不信你去百度搜索下SSL证书和TLS证书,看看哪个广告多)

SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

SSL/TLS协议的基本过程是这样的

  1. 服务端将非对称加密的公钥发送给客户端;
  2. 客户端拿着服务端发来的公钥,对对称加密的key做加密并发给服务端;
  3. 服务端拿着自己的私钥对发来的密文解密,从来获取到对称加密的key;
  4. 二者利用对称加密的key对需要传输的消息做加解密传输。

然后我们来看HTTPS

HTTPS

HTTPS=HTTP+SSL

HTTPS也就是披着SSL羊皮的HTTP

HTTPS相比HTTP,在请求前多了一个「握手」的环节。

Http与Https的区别

  • HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
  • 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
  • HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
  • http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
  • HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。

个人觉得,这个HTTPS加密流程作用性价比不高

又废资源又费钱(我用的免费的。。。)

而且我访问一个网站,黑客真的会在中间截获数据吗,我觉得更应该从源头或者目的来截获吧(可能是我网络安全知识薄弱,不太懂)

而且很明显,多了9次握手,那速度势必会影响 emmmm。。。

在浏览器中输入url地址,发生了什么?

  • 1.解析url地址,
  • 2.DNS解析
  • 3.TCP连接
  • 4.发送HTTP请求
  • 5.服务器处理请求
  • 6.服务器返回HTTP报文
  • 7.浏览器解析渲染页面

1.解析该url地址的域名,浏览器会检查这是一个url还是查询的关键字,然后自动编码,还会做一些安全检查

2.DNA解析的过程是递归的,下面以请求 www.google.com 为例:首先在本地域名服务器中查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用。从上述过程中,可以看出网址的解析是一个从右向左的过程: com -> google.com -> www.google.com。

3.HTTP协议是使用TCP作为其传输层协议的,当TCP出现瓶颈时,HTTP也会受到影响。

4.发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。HTTP请求报文是由三部分组成: 请求行, 请求报头和请求体。请求行格式及示例如下:

Method Request-URL HTTP-Version CRLF
GET index.html HTTP/1.1

常用的方法有:GET, POST, PUT, DELETE, OPTIONS, HEAD

5.服务器处理这里可说可不说

image-20200731164923701

6.后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。HTTP响应报文也是由三部分组成: 状态码, 响应报头和响应体。

7.浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。

image-20200731165020227

向淘宝请求首页,怎么提高性能

从请求、传输、渲染3个方面提升

一、请求

浏览器为了减少请求传输,实现了自己的缓存机制。浏览器缓存就是把一个已经请求过的Web资源拷贝一份副本存储在浏览器中,当再次请求相同的URL时,先去查看缓存,如果有本地缓存,浏览器缓存机制会根据验证机制(Etag)和过期机制(Last-Modified)进行判断是使用缓存,还是从服务器传输资源文件。具体流程如下图所示:

img

浏览器的请求有些是并发的,有些是阻塞的,比如:图片、CSS、接口的请求是并发;JS文件是阻塞的。请求JS的时候,浏览器会中断渲染进程,等待JS文件加载解析完毕,再重新渲染。所以要把JS文件放在页面的最后。

JS也可以通过两种方式由阻塞改成并行:一种是通过创建script标签,插入DOM中;另一种是在Script标签中增加async属性。

每种浏览器对同一域名并发的数量有限制,IE6/7是2,IE9是10,其他常见的浏览器是6,所以减少资源请求数量和使用多域名配置资源文件,能大大提高网站性能。

减少资源请求数量的方法,大致有以下几种:

1、通过打包工具,合并资源,减少资源数量。就是开发版本是很多个资源文件,部署的时候,按类合并成几个文件来输出。在实现模块管理的同时,实现统一输出。

2、CSS中,使用css sprite减少图片请求数量。

3、通过延迟加载技术,在用户无感知的情况下请求资源。

4、通过服务器配置,实现一次请求,返回多个资源文件,如淘宝CDN那样。

除了减少请求数量,也可以使用CDN镜像,来减少网络节点,实现快速响应。使用了CDN的请求,会根据用户所处的地理位置,找寻最近的CDN节点,如果请求是新的,则从资源服务器拷贝到节点,然后再返回给客户端。如果请求已经存在,则直接从节点返回客户端。

通过上面我们了解的缓存机制,如果我们部署上线的时候,是需要刷新缓存的。普通缓存通过强刷就能改过来,而CDN缓存则需要通过改变URL来实现。同时我们不可能要求用户按着Ctrl来刷新,所以通过打包工具,在部署的时候,统一更改URL是最有效的方式。而不常变更的库文件,比如echart、jquery,则不建议更改。

二、传输

从服务器往客户端传输,可以开启gzip压缩来提高传输效率。

Gzip有从1-10的十个等级。越高压缩的越小,但压缩使用的服务器硬件资源就越多。根据实践,等级为5的时候最均衡,此时压缩效果是100k可以压缩成20k。

三、渲染

浏览器在加载了html后,就会一边解析,一边根据解析出来的结果进行资源请求,并生成DOM树。而加载完毕的CSS,则被渲染引擎根据生成好的DOM树,来生成渲染树。等所有资源解析完毕计算好layout后,向浏览器界面绘制。随着用户操作,JS会修改DOM节点或样式,重新绘制和重新排列。重新绘制指的是绘制DOM节点对应的渲染节点,重新排列是指重新计算这些节点在浏览器界面的位置。很显然,重排是非常耗性能的。我们要做的是减少重排的次数。

生成DOM树的时候,我们可以通过减少DOM节点来优化性能。最初都是用table布局,节点深度和数量相当复杂,性能很差。同样CSS作为层叠样式表,层级也不可太深,不然遍历的成本很高。另外CSS的expression属性相当耗性能,能不用则不用。动画效果能用CSS写的就不用JS写,渲染引擎不一样,性能损耗也不一样。

上面说的是解析渲染的过程,我们再接着说说用户交互操作的过程。用户操作就会导致重绘和重排,重排一定会引起重绘,而重绘不一定会引起重排。到底怎样会引起重排呢?简单的定义,DOM结构的变化,以及DOM样式中几何属性的变化,就会导致重排。几何属性顾名思义,就是宽、高、边框、外补丁、内补丁等俗称盒模型的属性。同时还有offset之类的边距属性。

重排是最耗能的,减少重排的方法有:

1、如果需要多次改变DOM,则先在内存中改变,最后一次性的插入到DOM中。

2、同上一条,如果多次改变样式,合成一条,再插入DOM中。

3、由于position的值为absoute和fixed时候,是脱离文档流的,操作此类DOM节点,不会引起整页重排。所以动画元素设置position使其脱离文档流。

4、当DOM节点的display等于none的时候,是不会存在于渲染树的,所以如果有比较复杂的操作,先使其display等于none,等待所有操作完毕后,再将display设成block,这样就只重排两次。

5、获取会导致重排的属性值时,存入变量,再次使用时就不会再次重排。获取这些属性会导致重排:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

以上就是浏览器如何把资源变成肉眼所见的页面的,除了上述根据浏览器流程而总结出来的性能优化,我们还需要看看javascript作为程序,需要的优化。先来看看javascript的垃圾回收机制。

Javascript的引擎会在固定的时间间隔,将不再使用的局部变量注销掉,释放其所占的内存。而闭包的存在,将使引用一直存在,无法被释放掉。全局变量的生命周期直至浏览器卸载页面才会结束。所以一般来讲,内存溢出就是由于全局变量的不释放和闭包引起。为了防止内存溢出,我们可以做的方法有:

1、业务代码放在匿名立即执行函数里面,执行完毕会立即释放掉。

2、少用全局变量,同时用完的变量手动注销掉。

3、使用回调来代替闭包访问内部属性

4、当不可避免使用闭包时,慎重的对待其中的细节。不用的时候注销掉。

5、通过浏览器自带的工具profiles,来检查内存活动情况。如果是波浪型的,说明正常。如果是倾斜式渐进上涨的,说明有内存不会被释放,需要检查相应的函数。

最后再说一点,函数里返回异步取的值,经常有人这么:

Var getList = function(){ $.ajax().then(function(data){

  Return data;

}) };

Var users = getList();

毫无疑问,由于函数内的返回是异步的,所以返回只能是undefined,而不是想要的data。于是为了实现返回data,就把ajax的async属性设置成了false,由异步改为同步,来获取到data。然而最大的问题来了,同步是会中断渲染进程的,也就是请求返回的等待中,整个页面是卡死的,用户操作也不会有响应。这个问题真正的解决方案是返回promise对象,而不是把异步改成同步。