天下无难试之HTTP协议面试刁难大全(上)

10,423 阅读7分钟

小编是一个非典型面试官,对于HTTP协议的第一个问题,一般人会问常用的状态码有哪些。小编不这么问,小编的问题是HTTP的全称是什么,把英语给我说出来!

HTTP的全称是什么?

超文本传输协议,HyperText Transfer Protocol,这几个单词可别发走音了。所谓的超文本就是带标记的文本,刚开始的时候是指HTML。现在HTTP协议传输的东西可不只是HTML了,什么表单啊JSON啊XML啊文件啊都可以传输。

HTTP常用的状态码有哪些?

大部分同学都知道200、404、500、302状态码。如果连404都不知道,是要被小编鄙视的。500错误为什么这么常见呢,因为在开发的时候老是出bug,一个大异常抛出来,浏览器就500了。500表示InternalServerError,也就是内部服务器错误,如果不是bug,一般就是数据库挂了。

再多问几个状态码很多人就不知道了,因为大多数公司的软件服务没有走标准的HTTP状态码,很多状态码从来就不会出现,同学们自然也不会知道。

400 Bad Request 用于参数验证,少了一个参数或者参数类型错误之类的。

502 Bad Gateway 后端服务挂掉或者压力过大的时候, Nginx接到的请求无法及时传递给后端的服务进行处理,这个时候就会出现502错误。这个也非常常见,知乎豆瓣网站经常开小差的时候发生的错误就是这个。

304 Not Modified 极少人知道这个状态码,因为大部分后端开发者的前端Javascript开发经验都严重不足。当你用Chrome打开一个经常访问的网站,看看Network传输的静态资源就可以看到很多304状态码。它表示该资源被浏览器缓存了不需要重新请求服务器。

401 Unauthorized 权限不足,这个很好理解,就是资源存在但是不让你访问。

403 Forbidden 资源禁止访问,如果你的IP列为黑名单了,就会发生这种错误。

其实还有很多状态码,小编也没去好好研究了,因为实在不会在工作中用到。感兴趣的请继续阅读维基百科

HTTP有哪些Method?

GET 不解释,如果读者不知道,建议别在IT圈混了。

POST 一般用于创建或者修改资源,在RESTFUL规范里面POST只用来创建资源,并返回201 Created状态码表示创建成功。不过大多数网站都不遵循严格的RESTFUL规范,POST拿来做修改资源的事也是非常常见的。

PUT 对应于POST表示创建资源,PUT用于修改资源,PUT的参数必须是对象的全部属性,修改是覆盖式全部修改。

PATCH 对应于PUT的参数是对象的全部属性,PATCH的参数是部分属性,修改是局部字段修改。

DELETE 用于删除资源。

HEAD 不常用,跟GET差不多,区别就是不返回Body内容,只返回HTTP头信息。一般用于获取资源的元信息,比如长度,修改时间等

OPTIONS 跨域相关,后面再讲。

TRACE 小编没用过。

CONNECT 小编没用过。

后面三个感兴趣的去阅读一下RPC规范。小编大概看了一下,表示没怎么看懂,你行你上去挑战一下。

HTTP协议格式是怎样的?

HTTP的请求和响应的消息协议是一样的,分为三个部分,起始行、消息头和消息体。这三个部分以CRLF作为分隔符。最后一个消息头有两个CRLF,用来表示消息头部的结束。

HTTP请求的起始行称为请求行,形如GET /index.html HTTP/1.1

HTTP响应的起始行称为状态行,形如200 ok

消息头部有很多键值对组成,多个键值对之间使用CRLF作为分隔符,也可以完全没有键值对。形如Content-Encoding: gzip

消息体是一个字符串,字符串的长度是由消息头部的Content-Length键指定的。如果没有Content-Length字段说明没有消息体,譬如GET请求就是没有消息体的,POST请求的消息体一般用来放置表单数据。GET请求的响应返回的页面内容也是放在消息体里面的。我们平时调用API返回的JSON内容都是放在消息体里面的。

什么是分块传送?

当浏览器向服务器请求一个资源时,这个资源是一个动态资源,服务器无法提前预知资源的大小,这个时候就可以使用分块传输。

服务器先生成一个thunk,发送这个chunk,再生成一个chunk,再发送一个chunk,直到全部资源传送完成。

分块传送需要在请求头增加一个特殊的键值对transfer-encoding: thunked,那么消息体的内容便是分块传送的。

chunked传输格式如图所示,由一段一段的分块组合而成,每个块由一个长度行和一个分块体组成,最后一个分块长度为0表示结束。

持久连接的机制是怎样的?

HTTP早期版本中每个请求都会发起一个连接,一个网页除了页面的HTML之外还会有很多静态资源以及诸多的API调用,如果每个请求都一个连接,势必网页的一次加载就会和服务器创建多次连接,这是非常浪费服务器资源的,同时也让客户端的访问速度慢了不少。HTTP1.0之后引入了Keep-Alive持久连接,在HTTP1.1版本中成为默认选项。它使得HTTP的一个连接可以连续服务多个请求,有效节省了资源,增加了客户端页面的加载速度。

持久连接也不宜一直保持,毕竟每个连接都会占用服务器资源,如果打开网页的人太多,那服务器资源也会紧张,所以一般服务器都会配置一个KeepAlive Timeout参数和KeepAlive Requests参数限制单个连接持续时长和最多服务的请求次数。

如果服务器设置的timeout时长为0,就退化到非持久连接。非持久连接会在响应头部增加一个头信息Connection: Close通知客户端在接受完当前响应后连接需要立即关闭。

同样浏览器也不会因为服务器将KeepAlive Timeout配置了无限长就不管不问一直持续保持连接。每个浏览器都有它自己的内置限制,具体限制浏览器厂商各有不同。

什么叫Pipeline管线化?

HTTP1.0不支持管线化,同一个连接处理请求的顺序是逐个应答模式,处理一个请求就需要耗费一个TTL,也就是客户端到服务器的往返时间,处理N个请求就是N个TTL时长。当页面的请求非常多时,页面加载速度就会非常缓慢。

从HTTP1.1开始要求服务器支持管线化,可以同时将多个请求发送到服务器,然后逐个读取响应。这个管线化和Redis的管线化原理是一样的,响应的顺序必须和请求的顺序保持一致。

如何理解HTTP协议的无状态性?

所谓HTTP协议的无状态性是指服务器的协议层无需为不同的请求之间建立任何相关关系,它特指的是协议层的无状态性。但是这并不代表建立在HTTP协议之上的应用程序就无法维持状态。应用层可以通过会话Session来跟踪用户请求之间的相关性,服务器会为每个会话对象绑定一个唯一的会话ID,浏览器可以将会话ID记录在本地缓存LocalStorage或者Cookie,在后续的请求都带上这个会话ID,服务器就可以为每个请求找到相应的会话状态。

阅读相关文章,关注公众号【码洞】