问题的开始

我司某产品线有这么一个神奇接口 (https://host/path/customQuery)

该接口在预发或线上缓存正常的情况下TTFB为150ms左右(可以认为服务处理时间差不多就是TTFB),不过相比150ms的TTFB,显然数据资源下载时间过长的问题会更引人注意需要100ms左右(当然这也是网络条优秀的情况下,网络一般的话这个下载时间会更夸张)
customQuery请求一次请求的数据响应大概为2.7MB, 压缩后也有超过300KB
下载时间过长看起来就是因为这个响应实体过大了(100Mb的带宽满速,300KB差不多也需要30ms),通过测试可以发现同样的网络条件同一个应用的其他接口,如果响应压缩后小于1KB,其ContentDownLoad时间可以忽略不计(通常都会小于2ms)
因为代理默认开启了gzip,其实数据已经被压缩了近10倍,但是压缩后的数据还是过大。
分析了customQuery响应实体的数据结构。
发现数据每个list中fields节点大量重复出现。

如上图其中field的描述是完全一致的(按一页50条计算,这些数据重复了50遍)
这些数据field描述数据单个都大小大概是50KB(重复50次可以看到2.7MB的数据几乎都是这些重复的数据)

开始秀了

既然已经明确了这些重复描述数据,服务端的同学很自然想到把这些field描述提取出来重新组装数据可以大幅度减小数据传输的大小。
不过自己恰好曾经“看过”DEFLATE压缩(http的gzip正好使用的是DEFLATE)其中使用到的LZ77是会匹配前文相同短语后面的相同短语都会被替换成“标记”。
那我“秀”的时候又到了,当即表示采用这种数据重组的方式并不会带来明显的实际提升,因为数据实际的信息量没有实际变化,只是手动去除了冗余,而之前冗余的数据其实已经被gzip处理过了,所以仅仅单纯去除重复描述数据片段并不能带来预期的收益。
因为我秀的时候如此自信,对方马上就自己不自信了,表示要回去先验证效果后在做打算。

看起来是失败了

果然后面的结果“居然”是我被打脸了

customQuery接口返回的实体大小直接变成了25kb,解压后189kb(之前是327kb,解压后2.7Mb)

那这差距太大了,实体大小减小到了之前的10%不到,当然下载速度ContentDownLoad也有了大幅度的降低。(基本上就是一个RTT的时间)
不过这完全跟我之前的认知不一样啊,一定是哪里出现了问题。(毕竟是以为自己懂了系列)

试图抢救下

为了挽回颜面,我把这2组原始数据下载下来,本地压缩进行分析(还不想承认自己错了,试图找到产生这种结果的其他解释)

如下图老的数据为customQuery_v1(2.7MB),新的为customQuery_v2(190KB)

分别使用zip,gzip,rar对2组数据进行压缩 (gzip即为http默认使用的压缩算法,MAC上直接使用gzip命令可以对文件进行压缩)
可以发现RAR的压缩结果就与我最开始的想法差不多(即使原始数据差了超过10倍,而压缩的结果是几乎一致的,v1为19kb ;v2为17kb)
不过gzip对2组数据的压缩结果与在浏览器上看到的是一样的。(v1为329kb ;v2为25kb)
既然本地压缩也得到了同样的结果,看来真的是自己Too young too naive (大意了,没有闪,秀的时候应该先在本地验证一下的)

默默面对错误分析原因

但是为什么会有这样的结果,按我的理解压缩结果应该与rar一致才对。要搞清楚还要从压缩的方式入手。
一定是我以为的压缩行为与实际存在差异,gzip的基础是DEFLATE,DEFLATE是LZ77哈夫曼编码的一个组合体( https://tools.ietf.org/html/rfc1951
Huffman Coding 只是单纯的字符编码,编码后的大小与编码前的大小直接正相关,肯定不是产生结果的原因。
那剩下就只有是LZ77,只能是LZ77一开始没有把那些重复的fields压缩掉,而为什么LZ77没有把原始数据里大量重复的描述“标记”起来。
LZ77整体是是使用已经出现过的相应匹配数据信息替换当前数据从而实现压缩功能,为了匹配数据需要用到了“滑动窗口”的概念
细细一品,LZ77并不是全文匹配,数据为了可以边发送边压缩会进行分块压缩。通过查阅RFC文档,大概可以明确块的大小被限制在64k内,最大滑动窗口就是64k/2=32k,并且还要求“标记”的最大长度为256字节(当然标记长度这个问题不大,大不了不多用几个标记)。这里的问题在于使用滑动窗口就要求重复的数据必须要“相邻” 而块大小最大为64K,如果重复的2段数据不能出现在一个窗口内是不能被标记的。但是窗口最多是块大小的一半32Kb(实际也不会用这么大的窗口),而我们之前就计算过我们重复的单个field描述就有50Kb,要出现有2个重复的内容,即使2个描述相邻那也至少上100Kb(他们甚至都无法在同一个块里),实际上窗口最大32Kb,所以LZ77根本不能标记出这些重复的field。

以下引至https://tools.ietf.org/html/rfc1951#section-2

Compressed representation overview

A compressed data set consists of a series of blocks, corresponding
to successive blocks of input data. The block sizes are arbitrary,
except that non-compressible blocks are limited to 65,535 bytes.

Each block is compressed using a combination of the LZ77 algorithm
and Huffman coding. The Huffman trees for each block are independent
of those for previous or subsequent blocks; the LZ77 algorithm may
use a reference to a duplicated string occurring in a previous block,
up to 32K input bytes before.

Each block consists of two parts: a pair of Huffman code trees that
describe the representation of the compressed data part, and a
compressed data part. (The Huffman trees themselves are compressed
using Huffman encoding.) The compressed data consists of a series of
elements of two types: literal bytes (of strings that have not been
detected as duplicated within the previous 32K input bytes), and
pointers to duplicated strings, where a pointer is represented as a
pair <length, backward distance>. The representation used in the
"deflate" format limits distances to 32K bytes and lengths to 258
bytes, but does not limit the size of a block, except for
uncompressible blocks, which are limited as noted above.

Each type of value (literals, distances, and lengths) in the
compressed data is represented using a Huffman code, using one code
tree for literals and lengths and a separate code tree for distances.
The code trees for each block appear in a compact form just before
the compressed data for that block.

总结

最终也还是自己错了,也没有什么好总结的

要是什么都不知道也不出问题,要是知道的很清楚也不会出问题,就是在“以为自己知道”的情况下就各种问题。

 

被自己以为的GZIP秀到了的更多相关文章

  1. Linux常见压缩命令 - gzip,zcat,bzip2,bzcat

    几个常见的压缩文件扩展名 *.Z compress 程序压缩的文件: *.gz gzip 程序压缩的文件: *.bz2 bzip2 程序压缩的文件: *.tar tar 程序打包的数据,并没有压缩过: ...

  2. Android总结之Gzip/Zip压缩

    前言: 做过Android网络开发的都知道,在网络传输中我们一般都会开启GZIP压缩,但是出于刨根问底的天性仅仅知道如何开启就不能满足俺的好奇心的,所以想着写个demo测试一下比较常用的两个数据压缩方 ...

  3. 易企秀微场景2016最新完整版V10.5,小编亲测修复众多错误

    易企秀V10.5更新说明1.修复拨号英文错误2.修复转送场景问题3.修复设置场景密码乱码问题4.修复前台批量删除客户图片5.修复数据收集分页问题6.修复图片分类错乱问题7.修复音乐和特效冲突问题8.修 ...

  4. Android GZIP压缩IO流,优化APP数据传输(一)

    我是小搬运工,今天讲解流的压缩传输 在我们安卓开发中,通常伴随着大量的数据传输,在此,楼主给出一个简单的压缩流的数据进行操作. public void GZIPCpf(String path) { / ...

  5. ASP.NET MVC 3 网站优化总结(一) 使用 Gzip 压缩

    网站开启 Gzip 压缩的好处相信很多人都已经清楚,这样做可以提高网站的性能.那么为什么很多网站没有开启 Gzip 压缩功能呢?原因有4点:防病毒软件.浏览器 bug.网站代理和服务器未配置. 使用 ...

  6. 压缩和解压文件:tar gzip bzip2 compress(转)

    tar[必要参数][选择参数][文件] 压缩:tar -czvf filename.tar.gz targetfile解压:tar -zxvf filename.tar.gz参数说明: -c 建立新的 ...

  7. Linux下的压缩和解压缩命令——gzip/gunzip

    gzip命令 gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后,其名称后面会多处".gz"扩展名. gzip是在Linux系统中经常使用的一个对文件进行压 ...

  8. php关于ob_start('ob_gzhandler')启用GZIP压缩的bug

    如果使用ob_start("ob_gzhandler"); 则ob_clean()后面的输出将不显示,这是个bug,可以用ob_end_clean();ob_start(" ...

  9. 使用HttpClient来异步发送POST请求并解析GZIP回应

    .NET 4.5(C#): 使用HttpClient来异步发送POST请求并解析GZIP回应 在新的C# 5.0和.NET 4.5环境下,微软为C#加入了async/await,同时还加入新的Syst ...

随机推荐

  1. springmvc<一> 一些特殊的Bean

    Special Bean Types        HandlerMapping 基于前置或后置拦截器映射请求到处理器,具体实现方式由子类决定,        两种主要的实现             ...

  2. 跨国合作:Serverless Components 在腾讯云的落地和实践

    导语 | Serverless Components 是 Serverless Framework 推出的最新解决⽅案,具有基础设施编排能⼒,开发者通过使⽤ Serverless Components ...

  3. hugegraph 数据存取数据解析

    hugegraph 是百度开源的图数据库,支持hbase,mysql,rocksdb等作为存储后端.本文以EDGE 存储,hbase为存储后端,来探索是如何hugegraph是如何存取数据的. 存数据 ...

  4. 剑指offer二刷——数组专题——斐波那契数列

    题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1). n<=39 我的想法 斐波那契数列定义:F(0)=0,F(1)=1, ...

  5. js 转为整数之Number()、parseInt()、parseFloat()区别

    一:Number() 如果是Boolean值,true和false值将分别被转换为1和0. 如果是数字值,只是简单的传入和返回. 如果是null值,返回0. 如果是undefined,返回NaN. 如 ...

  6. FHQ简要笔记

    前言 原文写于 XJ 集训day2 2020.1.19. 现在想想那时候连模板都还没写,只是刚刚理解就在那里瞎yy--之前果然还是太幼稚了. 今天刷训练指南发现全是 Treap 和 Splay ,不想 ...

  7. 【笔记】「pj复习」深搜——简单剪枝

    深搜--简单剪枝 说在最前面: 因为马上要 NOIP2020 了,所以菜鸡开始了复习qwq. pj 组 T1 ,T2 肯定要拿到满分的,然后 T3 , T4 拿部分分, T3 拿部分分最常见的做法就是 ...

  8. http请求user_agent字段解析

    浏览器的常见User Agent 各字段的解释 浏览器的User Agent字段令人迷惑,例如:某一版本的Chrome访问网络时,User Agent字段如下: Mozilla/5.0 (Window ...

  9. Robot Framework+adb框架自动化测试Android设备案例⑹——源码地址、测试报告

    一.源码地址 GitHub:https://github.com/xiongye105554598/DVR8010_AutoTest 二.测试报告

  10. CentOS 7.6安装MariaDB10.4.8超详细教程

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品. Cent ...