这是一道比较经典的面试题,主要考察的是对网络方面的认识。
先通过一张图对整个处理流程进行描述(出自参考资料1):
简单地说:首先通过DNS域名解析出服务器IP,然后通过TCP/IP协议建立起客户端到服务器的TCP连接。网络连接建立好之后,通过HTTP协议发出请求包,从网络模型的应用层传到物理层,随后发送出去。请求包在服务器端经过负载均衡,到达服务器,经服务器处理后返回结果给客户端,客户端收到结果后进行页面渲染,最终展示到浏览器上。
下面将分阶段进行介绍。
1 域名解析
每个客户端上都配置了DNS服务器地址。DNS按照如下顺序查找服务器ip:浏览器缓存->系统缓存->路由器缓存->ISP DNS缓存->递归搜索。
2 TCP连接
找到服务器对应的IP地址之后,在双方进行通信之前,需要先连接网络连接。这里是TCP连接,需要通过3次握手来建立(事实上,在不可靠信道上建立可靠连接的次数理论上最少就是3次)。
三次握手的过程如下:
(1)第一次握手,客户端发送一个SYN同步报文给服务器,SYN中含有客户端的报文序列号x。
(2)第二次握手,服务器给客户端发送一个SYN同步报文和一个ACK确认。表示收到了客户端发送的报文,并且在SYN中放入了本次发送报文的序列号y。
(3) 第三次握手,客户端收到服务器的回复之后,再次发送一个SYN报文和一个ACK确认,SYN中包含报文序列号x+1。
经过三次握手之后,TCP连接建立起来,双方之间才可以通信。
在博主之前的文章中提到过的SYN Flood攻击,正是利用第二次握手之后,服务器维持半连接状态需要一定的资源这一点,来进行DDos攻击的。
3 发送HTTP请求
建立好TCP连接之后,就准备开始正式通信了。
3.1 请求报文
从应用层面看,HTTP请求报文包含:请求行,报文头和报文主体。
一个简单的例子如下:
POST /user HTTP/1.1 //请求行
Host: www.user.com
Content-Type: application/x-www-form-urlencoded
Connection: Keep-Alive
User-agent: Mozilla/5.0. //以上是首部行
(此处必须有一空行) //空行分割header和请求内容
name=world 请求体
3.1.1 请求行
请求行由三部分组成:请求方法,请求URL(不包含域名),HTTP协议版本。
请求方法
请求方法有:GET,POST,PUT,DELETE,HEAD,OPTINS,TRACE,CONNECT。最常用的方法是GET和POST。
GET请求不适合传递敏感数据,因为请求参数会直接显示在url中。也不适合传递大量数据,因为url长度受限。
POST请求将请求参数封装在HTTP请求数据中,对数据量没有限制。
HTTP协议版本
当前使用的HTTP协议是1.1版本。HTTP/1.0版支持GET,POST和HEAD三种方法,1.1版本在此基础上新增了OPTIONS,PUT,DELETE,TRACE,CONNECT五种方法。新版本默认采用持久连接,支持以管道方式同时发送多个请求,以便降低线路负载,提高传输速度。
3.1.2 请求头
请求头部由键值对组成,表明了请求的相关信息。
- User-Agent:请求产生的浏览器类型。
- Accept:客户端希望接受的数据类型。
- Content-Type:客户端发送的实体数据的数据类型。
常用的几种类型如下:
Content-Type | 说明 |
---|---|
text/html | html格式 |
text/plain | 纯文本格式 |
application/x-www-form-urlencoded | 普通表单提交的默认格式。数据被编码为key/value格式发送到服务器。 |
application/json | json字符串格式 |
multipart/from-data | 多媒体表单格式 |
multipart/from-data用以支持向服务器发送二进制数据,以便在post请求中实现文件上传等功能。
- Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
- Connection:表示是否要持久连接,close/keep-alive。
- Cookie:这是最重要的请求头信息之一。
- 条件请求头部:If-Modified-Since是浏览器向服务器端询问某个资源文件如果自从什么时间修改过,那么重新发给我,这样就保证服务器端资源文件更新时,浏览器再次去请求,而不是使用缓存中的文件。
3.1.3 请求体
GET方法无请求体数据,因为其参数在url中,POST方法请求参数封装在请求体中。
3.2 响应报文
HTTP响应报文跟请求报文的结构差不多,由状态行,报文头和响应体组成。
3.2.1 状态行
状态行由HTTP协议版本,响应状态码和状态码的文本描述组成。格式如下:
HTTP/1.1 200 OK
状态码由3位数字组成,第一个数字定义了响应的类别。说明如下:
状 态 码 | 说 明 |
---|---|
1xx | 指示信息,表明请求已接收,继续处理。 |
2xx | 成功。表示请求已被成功接收并处理。 |
204 | 服务端成功处理,但未返回内容。一般用在只是客户端向服务端发送信息,而服务端不用向客户端返回什么信息的情况。不会刷新页面。 |
206 | 服务器已经完成了部分GET请求(客户端进行了范围请求)。响应报文中包含Content-Range指定范围的实体内容。 |
3xx | 重定向 |
301 | 永久重定向。表示请求的资源永久地搬到了其他位置。 |
302 | 临时重定向,表示请求的资源临时搬到了其他位置。 |
303 | 临时重定向,应使用GET定向获取请求资源。303功能与302一样,区别在于303明确客户端应该使用GET访问。 |
307 | 临时重定向,与302含义相同。POST不会变成GET。 |
304 | 表示客户端发送附带条件的请求时(如If-Modified-Since),条件不满足。返回304时,不包含任何响应主体。虽然304被划分到3xx,但其实和重定向没有关系。 |
4xx | 客户端错误 |
400 | 客户端请求语法有错误,服务器无法理解。 |
401 | 请求未经授权,这个状态代码必须和www-authenticate报文域一起使用。 |
403 | 服务器收到请求,但是拒绝提供服务。 |
404 | 请求资源不存在。 |
415 | 不支持的媒体类型。 |
5xx | 服务端错误,服务器未能实现合法的请求。 |
500 | 服务器发生不可预期的错误。 |
503 | 服务器当前不能处理客户端的请求,一段时间后可能恢复正常。 |
3.2.2 响应头
响应头中常见的字段如下:
- Server:服务器应用程序软件的名称和版本
- Content-Type:响应正文的类型
- Content-Length:响应正文的长度
- Content-Charset:编码格式
- Content-Encoding:数据压缩格式
- Content-Language:语言
- Keep-Alive:保持连接的时间
3.2.3 响应正文
服务器发送给客户端的内容,也就是客户端请求所需要的内容。
4 Ngnix反向代理
反向代理是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端。从外部来看,反向代理服务器就像是原始服务器。
使用反向代理服务器的好处
-
保护了真实的web服务器,使得web服务器对外不可见。外网只能看到反向代理服务器,而反向代理服务器上并没有真实数据,因此保护了web服务器的资源安全。
-
节约了有限的IP地址资源
企业内部所有的网站共享一个在Internet中注册的IP地址,这些服务器分配私有地址,采用虚拟主机的方式对外提供服务。 -
减少web服务器压力,提高响应速度
反向代理就是通常所说的web服务器加速,它是一种通过在繁忙的web服务器和外部网络之间增加一个高速的web缓冲服务器来降低实际的web服务器的负载的一种技术。反向代理服务器会强制将外部网络对要代理的服务器的访问经过它,它会将从源服务器上获取到的静态内容缓存到本地,以便日后再收到同样的信息请求时,直接将本地缓存的内容发给客户端,减少后端web服务器的压力,提高响应速度。 -
其他优点
请求的统一控制,包括设置权限,过滤规则等。
区分动态和静态可缓存内容。
实现负载均衡,内部可以采用多台服务器来组成服务器集群,外部还是可以采用一个地址访问。
解决ajax跨域问题。
作为真实服务器的缓存,解决瞬间负载量大的问题。
Nginx通常会配置这些功能:动静分离、缓存设置、负载均衡、反向代理和虚拟主机功能等。
请求处理
Nginx接收到请求后,进行一些验证,如黑白名单拦截,是否有限流限制,是否有负载均衡设置等。
如果是静态内容的请求,则直接返回缓存结果;如果是动态内容,则将请求转发到web服务器上,获得请求结果后返回给客户端。
参考资料
[1]https://www.jianshu.com/p/558455228c43.
[2]https://blog.csdn.net/hr10230322/article/details/78401475