- 使用高效的数据交换格式 - 为客户端与服务器之间传输的数据选择高效的编码.
- 在可能的情况下使用预先压缩的数据 - 使用专用算法对诸如音频、视频和图像进行压缩或按比较缩放以适应通道与设备
- 压缩每一个请求与响应负载 - 压缩文本负载以减少带宽, 同时又不太影响服务器与客户端代码
实际上, 可以通过压缩服务器响应或是客户端请求为非媒体负载开启负载压缩.
1. 响应压缩
响应负载压缩是最简单的一种 HTTP 负载压缩形式. HTTP 响应由返回给客户端的用于响应上一个 HTTP 请求的响应头与响应体构成. 响应压缩会对响应体应用数据压缩算法, 但不会操纵 HTTP 头
在 iOS HTTP 负载中, 默认情况下, 所有的 HTTP NSURLConnection 请求都是开启压缩的. 接收到的负载会自动解压缩并以最初的格式呈现在代码中. 解压缩的计算代码要比传输 10 倍字节的通信代价低; 因此, 激活响应压缩几乎总是有益无害的
在默认请况下, NSURLConnection 会向每个请求添加好下 HTTP 头:
Accept-Encoding: gzip, deflate
Accept-Encoding 头告诉服务器, 客户端可以接收使用 gzip 或 DEFLATE 压缩的负载, 不过服务器可以自己选择是否压缩响应. 这样, 通过响应负载压缩来提升性能的关键就在于配置服务器以支持压缩
有些浏览器无法正确处理 DEFLATE 压缩, 因此最常用的压缩其实是 gzip
比如, 配置 Apache Web 服务器的过程涉及加载压缩模块并针对特定的文档类型激活输出过滤器
LoadModulefilter_module library-path/mod_filter.so
LoadModuledeflate_module library-path/mod_deflate.solibrary-path 的值会根据 Apache 的安装位置而发生变化
filter_module 是个常用的模块, 并且可能已经被加载了. deflate_module 则不太常用, 不过也是 Linux、OSX 与 Windows 上标准 Apache 安装的组成部分
deflate_module 支持的是 gzip 而非 DEFLATE 压缩
为那些能够从压缩中获益的内容类型添加输出过滤器(非图片、音频和视频)
禁用负载压缩, 可以通过清除自动设定的 Accept-Encoding 头来实现
对请求的响应不会再被服务器压缩. 响应压缩是优化应用网络带宽使用的一种简单手段, 只需要对服务层做很小的修改即可实现
2. 请求压缩
与响应压缩不同, 请求压缩的实现更为复杂, 因为它既需要客户端与服务端的协调实现.
模式一:
iOS 应用首先查询服务器来判断是否支持压缩, 然后根据服务器的响应来调整其行为请求压缩会为移动应用带来很大的好处, 因为广域无线传输速率是非对称的, 为发送给设备的数据提供了更大的带宽, 而对设备发出的数据则提供了很小的带宽. 之所以使用这种非对称的带宽, 原因在于大多数 Web 流量都是非对称的. 如果应用定义了标准的非对称模式, 那么你绝对应该考虑使用请求压缩. 比如, 如果应用上传到服务器, 那么应用就会通过上传负载的压缩而获益(传输到服务器以及回传给设备时就会消耗 80KB 的带宽, 在请求与响应开启了压缩, 那么同样一次往返, 数据只会消耗 12KB 的带宽)
要想创建请求压缩, 首先需要在 Web 服务器上定义好输入过滤器
Apache 并不会在通过 PHP 或 mod_jk 模块等资源过滤器发送数据前对其解压缩, 因此, 如果通过资源过滤器向 Web 应用传递了压缩数据, 那么目标 Web 应用就要负责负载的解压缩
与响应压缩一样, 客户端应用不应该将 CPU 时间浪费在压缩诸如 PDF、加密数据、图像、音频及视频等已经压缩的内容上. 然而, 代表预先压缩的数据的 Base64 数据常常会从请求压缩中获益, 比如, 如果要以 Base64 格式上传 JPEG 文件, 那么可以对 Base64 数据进行压缩, 相较于未压缩的 Base64 数据, 压缩后的数据体积会降低 30% 左右
在 Apache 中, 用于响应压缩的模块也可以执行请求压缩. 如下配置片段会加载所需模块:
接下来需要为 DEFLATE 模块定义输入过滤器
如果带有 Content-Encoding:gzip 头的请求到达 HTTP 服务器, HTTP 服务器就会尝试解压缩请求体并将其传给过滤器链中的下一个过滤器. 出于说明的目的, 这个示例请求压缩应用带有一段简单的 Perl脚本, 它会将接收到的响应体负载回显出来, 脚本并不关心接收到的负载是不是压缩过的
接下来, 为 iOS 应用添加压缩代码. 需要压缩负载并向请求添加 Content-Encoding 头. 示例压缩代码使用了 libz.dylib 框架, 这需要项目在编译任何压缩代码前行先链接到该框架
示例应用实现了压缩并提供了一种方式以执行多个请求(包含了针对你所选择的 URL 的示例负载). 除了请求所消耗的平均时间与总时间外, 还会显示出负载的大小. 时间包含了计算出的压缩所需的时间.
通过 DSL 可以看到收益, 因为 DSL 连接对于上下游的速率来说通常是非对称的. 值得注意的是, 在 Edge 网络上要 10 秒钟才能完成的请求, 如果对请求和响应进行了压缩, 处理时间会降到 3 秒以下