一、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)
.
- 域名分片: 同样是用数量来解决问题, 我们多开几个域名, 但是都指向同一个服务器, 这样实际的长连接数量也就增加了