一、HTTP的数据类型
常见的数据类型
- text: 文本类型
- text/html: 超文本文档类型
- text/plain: 纯文本类型
- text/css: 样式表
- image: 图像文件
- image/gif
- image/jpeg
- image/png 等
- audio/video: 音频,视频数据
- audio/mpeg
- video/mp4等
- application: 不固定的数据格式
- application/json
- application/javascript
- application/pdf
- application/octet-stream等
- 数据体积比较大时, 还有不同的压缩格式
- gzip: GNU zip 压缩格式
- deflate: zlib压缩格式
- br: 一种为HTTP优化的压缩算法
客户端和服务器通过 Accept 和 Content2个字段来约定数据格式相关的内容. 如:
// 客户端告诉服务器我可以接受的数据类型
Accept: text/html,image/webp,image/png
// 服务器告诉客户端我发送的数据类型
Content-Type: text/html
Content-Type: application/json
// 客户端 -> 压缩格式
Accept-Encoding: gzip
// 服务器 -> 压缩格式
Content-Encding: gzip
// 客户端 -> 语言种类
Accept-Language: zh-CN,en
// 服务器 -> 语言种类
Content-Language: en
// 客户端 -> 字符集
Accept-Charset: gbk, utf-8
// 服务器 -> 字符集 (服务器的字符集是跟在Content-Type后的)
Content-Type: text/html; charset=utf-8
这2个字段中参数的个数可以是多个, 另外再 Accept 和 Content 字段中, 可以通过 q 参数来设定不同参数的优先级
如:
Accept: text/plain, application/xml;q=0.9, */*;q=0.8
// 表示最优先接受 text/plain, 0.9的权重接受 application/xml, 0.8权重接受其他类型
复制代码
二、HTTP大文件传输
我们知道HTTP在发展过程中, 可以传输的数据变得多种多样, 数据大小也变得越来越大, 几百K的图片, 几G的视频都有可能. 那么HTTP是怎么保证高效的传输的?
- 数据压缩: 通过对gzip等压缩算法对数据进行压缩, 通过减少数据体积在达到加速的效果
- 分块传输(Transfer-Encoding: chunked): 通过将数据分块, 每次只传输一小块, 这样就可以将内存,带宽等资源节省下来.
- 范围请求: 分块传输的同时, 客户端也可以申请请求数据的具体范围, 比如 0~99字节等, 对应的服务器会在享有字段添加Content-Range 来告诉当前数据的实际偏移和总大小
三、HTTP的连接管理
- 短链接
HTTP最初是采用 “请求-应答”的方式来进行数据传输. 在收到响应报文以后, 就会断开连接. 即无法保持与服务器的长时间连接状态, 所以我们成为短链接.
短链接的缺点十分明显: 在TCP中, 建立链接和关闭连接会非常的占用资源. 短链接的方式会频繁的建立/断开连接造成非常多的资源浪费.
- 长连接
因为短链接的缺点, HTTP协议提出了”长连接”的概念. 也就是再一次连接断开的过程中, 进行多次数据传输. 这样就可以减少建立断开连接的次数
- 如果进行长连接?
我们可以在请求头中 通过 Connection: Keep-alive
来明确要求使用长连接. 当然服务器如果支持长连接的话, 不管客户端是否要求, 他总会在响应报文中 添加Connection: Keep-alive
来告诉客户端我是支持长连接的
- 长连接如何关闭?
可以在客户端的请求头中添加Connection: close
来告诉服务器, 这次请求完成后就关闭连接. 服务器收到以后, 会在响应报文添加同样的字段, 并且发送后关闭连接
- 服务器通常不会自己关闭连接, 不过也可以通过配置一定的策略来关闭, 以Nginx为例, 比如
keepalive_timeout
指令, 设置长连接的超时时间, 如果一段时间内没有任何数据通信, 就会关闭连接keepalive_requests
指令, 可以设置长连接中请求的最大次数. 当处理了这么多请求后, 就会自动关闭
- 什么是队头阻塞?
队头阻塞与长连接/短链接无关, 主要与HTTP的”请求-应答” 模型有关. 因为HTTP规定报文必须是 一收一发
, 这就行程了先进先出的串行队列. 如果队头的请求因为处理的太慢耽误了时间, 那么队列中的其他请求都会在一起等待. 这就是队头阻塞.
- 另外,如果不改变HTTP的
请求-应答
模式(也很难改变),队头阻塞是无法解决的, 只能进行优化.
-
并发连接: HTTP的就是来优化这个问题. 同时对一个域名发起多个长连接, 用多个队列来处理, 达到优化的目的
-
域名分片: 同样是用数量来解决问题, 我们多开几个域名, 但是都指向同一个服务器, 这样实际的长连接数量也就增加了
Dos攻击: 如果每个客户端都想让自己变快, 就建立很多链接(并发连接), 那么总连接数就会变得巨大, 服务器就会认为是恶意攻击,
拒绝访问(Denial Of Service)
.
HTTP的重定向和跳转
- 重定向的过程
在浏览器发一起次请求, 服务器返回30x重定向时, 浏览器会发起第二个请求重定向到新的地址.
- 为何会自动跳转
我们通过浏览器的开发者模式可以看到, 在浏览器返回302的响应报文中, 还包含了 Location: xxxx
的字段, 这个字段就是为浏览器重新跳转的地址
- 可以在query 参数中添加
dst=xxx
来指定重定向的地址- Location的使用: 如果是站内跳转, 可以直接写相对路径, 如果是站外跳转则需要写完整的URI
- 重定向的作用:
- 一些资源如果失效, 可以通过重定向跳转到有效的资源
- 将一些临时地址跳转到一个统一的地址
- 重定向会发生的问题:
- 性能消耗: 多一次跳转, 就会多一次性能的消耗
- 如果跳转不当, 会发生循环重定向. 如 A -> B -> C -> A