Enter

1. 输入地址

比如: didiorg.com/

2. DNS(Domain Name System,)解析:浏览器查找域名的 IP 地址

本地 hosts 文件 => 本地 DNS 服务器 => DNS 根服务器
本地 DNS 服务器 => com 域服务器
本地 DNS 服务器 => 域名解析服务器

 这个过程很有意思,本地 DNS 服务器访问根服务器,当根胳没有的时候,并不是根服务器去访问 com 域服务器,这个时候,DNS 根服务器只会告诉 本地 DNS 服务器他没有, 叫他再去访问 com 域服务器。

 更有意思的是, 当本地 DNS 服务器访问 com 域服务器的时候,com 域服务器也不会直接给 本地 DNS 服务器 一个 IP 地址, 而是告诉本地 DNS 服务器想要查找的那个域名的域名解析服务器的地址

然后, 本地 DNS 服务器通过刚才拿到的址, 再去访问域名解析服务器,从那里拿到 IP 地址。

3. 浏览器向服务器发 http 请求

拿到 ip 后,浏览器会向服务器80端口发起 TCP 连接请求

TCP 连接: tcp连接全过程各种状态详解

第一次握手:客户端的应用进程主动打开,并向服务端发出请求报文段。其首部中:SYN=1,seq=x。
第二次握手:服务器应用进程被动打开。若同意客户端的请求,则发回确认报文,其首部中:SYN=1,ACK=1,ack=x+1,seq=y。
第三次握手:客户端收到确认报文之后,通知上层应用进程连接已建立,并向服务器发出确认报文,其首部:ACK=1,ack=y+1。当服务器收到客户端的确认报文之后,也通知其上层应用进程连接已建立。

连接成功之后, 浏览器就会发起请求:

 请求方式一般可以分为 get 请求、post 请求, 可参考get/post 请求的区别

 一个请求一般包括三部分:

  1. 请求方法URI协议/版本
  2. 请求头(Ruquest Header)
  3. 请求正文: (比如: username=ahui&parsword=ahui123456)

  常见的请求头一般会能下边这些, 我们很常用的 浏览器缓存 也在这个里边可以设置

1
2
3
4
5
6
7
8
9
Accept: 
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: keep-alive
Host: didiorg.com
If-Modified-Since: Mon, 02 Mar 2020 02:22:54 GMT
If-None-Match: W/"5e5c6dfe-4377"
Referer: http://didiorg.com/web.html
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36

4. 服务器处理请求

建立好联接之后,浏览器就会发请求,服务器就会开始处理浏览器发过来的请求

这里有一个很厉害的角色: nginx 参考:nginx 常用配置

 一些大一点的网站会将你的请求到反向代理服务器中,因为当网站访问量非常大,网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。

 此时,客户端不是直接通过HTTP协议访问某网站应用服务器,而是先请求到Nginx,Nginx再请求应用服务器,然后将结果返回给客户端,这里Nginx的作用是反向代理服务器。同时也带来了一个好处,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。

通过Nginx的反向代理,我们到达了web服务器,服务端脚本处理我们的请求,访问我们的数据库,获取需要获取的内容等等

5. 服务器返回 http 响应

 一个 http 响应也由3个部分组成:

  状态行: 由协议版本(HTTP-Verson)、数字形式的状态代码(Status-Code)、相应的状态描述(Reason-Phrase CRLF) 例如: HTTP/1.2 200 OK
  响应头: 由关键字/值对组成,每行一对,关键字和值用英文冒号”:”分隔
  响应正文: 包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等

状态码:

1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。
 100 Continue
 101 Switching Protocols

2xx:成功状态码,表示服务器已成功接收到请求并进行处理。
 200 OK 表示客户端请求成功
 204 No Content 成功,但不返回任何实体的主体部分
 206 Partial Content 成功执行了一个范围(Range)请求

3xx:重定向状态码,表示服务器要求客户端重定向。
 301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL
 302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源
 303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源
 304 Not Modified 服务器内容没有更新,可以直接读取浏览器缓存
 307 Temporary Redirect 临时重定向。与302 Found含义一样。302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能 循这一标准,但也依赖于浏览器具体实现

4xx:客户端错误状态码,表示客户端的请求有非法内容。
 400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
 401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
 403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
 404 Not Found 请求的资源不存在,例如,输入了错误的URL

5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。
 500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
 503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常

6. 浏览器收到服务器返回的资源后开始渲染 HTML

解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

  浏览器在解析html文件时,会”自上而下“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的CSS、iconfont等,请求过程是异步的,并不会影响html文档进行加载。

  解析过程中,浏览器首先会解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。

  DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。

 当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。

  JS的解析是由浏览器中的JS解析引擎完成的,比如谷歌的是V8。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。

  JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

7. 浏览器发送请求获取嵌入在 html 中的资源,如果图片,音频,css, js 等

上边我们看了浏览器所干的事情, 然后我们再看一下对他的一些优化:

性能优化

一般网站优化都是优化后台,如接口的响应时间、SQL优化、后台代码性能优化、服务器优化等。高并发情况下,对前端web优化也是非常重要的。下面说说几种常见的优化措施。

1、HTML CSS JS位置

  一般需要将CSS放页面最上面,即HEAD部分,而将JS代码放页面底部。因为页面需要加载为CSS才进行渲染,而JS如果不是在页面加载之前就要执行就要放到页面最底部,以免在页面展示之前因JS过多加载而影响页面渲染速度。

2、引用文件位置

  有一些插件需要引用到远程的图片、CSS、JS、图标等,如果远程的资源连接网速不佳,如国外的某些资源,会造成网页阻塞,同样也会造成页面展示问题,尽量能把引用远程的资源能本地化。

3、减少后台请求

  每个请求都是耗费资源影响系统性能的,所以,能减少后台请求就减少。如,尽量的将同一个资源(图片、JS、CSS等)合并成一个文件,页面只要请求一次即可,这样就节省了很多http连接的开销及往返的时间损耗。

  另外一方面,如果是关于抽奖、摇一摇、秒杀等功能,可以限制发往后台的频率,如前端操作10次才往后端发一次请求,这样从前端就做到了后台的流量控制,把流量控制到访问的最外层是最好的,尽量不要让请求落到底层。

4、压缩传输

  http压缩可以对纯文本可以压缩至原内容的40%, 从而节省了60%的数据传输,GZIP是一种常用的压缩编码。因此,对文本类型的资源如CSS、JS、HTML启用GZIP压缩加速http传输速度。

5、减少cookie传输

  cookie会包含在每次请求和响应中,如果cookie过多会影响http响应速度,所以高并发情况下尽量控制cookie的传输量,nginx对cookie传输默认是做了限制的。另外,像CSS、JS、图片等静态资源可以启用单独域名,禁用cookie对静态资源的传输,这样就能大大提高效率。

6、浏览器缓存

  高并发情况下,可以将一些不怎么变动的东西缓存到浏览器cache中,或者一些活动内容可以提前将内容在客户端缓存起来,以免活动开始大量请求涌入服务器。

7、CDN

  是一个静态内容分发网络,本质就是静态资源的缓存,可以将静态资源放到CDN上,这样,用户就能离自己最近的地方获取到资源,大大提高了用户访问速度。

8、反向代理

  常用的反向代理nginx除了负载均衡功能,它也可以通过配置缓存功能来加速请求响应速度,当用户第一次访问的时候静态资源就可以被缓存到反向代理服务器上,这样其他用户的请求就能直接从反向代理服务器直接获取返回,这样也就直到了静态资源缓存的作用。