被自己以为的GZIP秀到了
问题的开始

我司某产品线有这么一个神奇接口 (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 Each block is compressed using a combination of the LZ77 algorithm Each block consists of two parts: a pair of Huffman code trees that Each type of value (literals, distances, and lengths) in the |
总结
最终也还是自己错了,也没有什么好总结的
要是什么都不知道也不出问题,要是知道的很清楚也不会出问题,就是在“以为自己知道”的情况下就各种问题。
被自己以为的GZIP秀到了的更多相关文章
- Linux常见压缩命令 - gzip,zcat,bzip2,bzcat
几个常见的压缩文件扩展名 *.Z compress 程序压缩的文件: *.gz gzip 程序压缩的文件: *.bz2 bzip2 程序压缩的文件: *.tar tar 程序打包的数据,并没有压缩过: ...
- Android总结之Gzip/Zip压缩
前言: 做过Android网络开发的都知道,在网络传输中我们一般都会开启GZIP压缩,但是出于刨根问底的天性仅仅知道如何开启就不能满足俺的好奇心的,所以想着写个demo测试一下比较常用的两个数据压缩方 ...
- 易企秀微场景2016最新完整版V10.5,小编亲测修复众多错误
易企秀V10.5更新说明1.修复拨号英文错误2.修复转送场景问题3.修复设置场景密码乱码问题4.修复前台批量删除客户图片5.修复数据收集分页问题6.修复图片分类错乱问题7.修复音乐和特效冲突问题8.修 ...
- Android GZIP压缩IO流,优化APP数据传输(一)
我是小搬运工,今天讲解流的压缩传输 在我们安卓开发中,通常伴随着大量的数据传输,在此,楼主给出一个简单的压缩流的数据进行操作. public void GZIPCpf(String path) { / ...
- ASP.NET MVC 3 网站优化总结(一) 使用 Gzip 压缩
网站开启 Gzip 压缩的好处相信很多人都已经清楚,这样做可以提高网站的性能.那么为什么很多网站没有开启 Gzip 压缩功能呢?原因有4点:防病毒软件.浏览器 bug.网站代理和服务器未配置. 使用 ...
- 压缩和解压文件:tar gzip bzip2 compress(转)
tar[必要参数][选择参数][文件] 压缩:tar -czvf filename.tar.gz targetfile解压:tar -zxvf filename.tar.gz参数说明: -c 建立新的 ...
- Linux下的压缩和解压缩命令——gzip/gunzip
gzip命令 gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后,其名称后面会多处".gz"扩展名. gzip是在Linux系统中经常使用的一个对文件进行压 ...
- php关于ob_start('ob_gzhandler')启用GZIP压缩的bug
如果使用ob_start("ob_gzhandler"); 则ob_clean()后面的输出将不显示,这是个bug,可以用ob_end_clean();ob_start(" ...
- 使用HttpClient来异步发送POST请求并解析GZIP回应
.NET 4.5(C#): 使用HttpClient来异步发送POST请求并解析GZIP回应 在新的C# 5.0和.NET 4.5环境下,微软为C#加入了async/await,同时还加入新的Syst ...
随机推荐
- java并发编程实战《七》安全性、活跃性以及性能问题
安全性.活跃性以及性能问题 安全性问题 那什么是线程安全呢?其实本质上就是正确性,而正确性的含义就是程序按照我们期望的执行,不要让我们感到意外. 存在共享数据并且该数据会发生变化,通俗地讲就是有多个线 ...
- RabbitMQ Go客户端教程5——topic
本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第五篇--topic. 这些教程涵盖了使用RabbitMQ创建消息传递 ...
- PyQt(Python+Qt)学习随笔:QMainWindow的addDockWidget方法增加QDockWidget停靠窗到主窗口
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 DockWidget除了放在QMainWindow窗口内外,也可以放在 ...
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的快捷菜单策略(contextMenuPolicy)取值及含义
在Qt Designer中可以设置部件的快捷菜单策略,快捷菜单通过在部件上点击鼠标右键触发. 快捷菜单策略通过枚举类型Qt.ContextMenuPolicy来定义,对应枚举类型取值及含义如下: 通过 ...
- Github 美化设置个人主页
起因是发现自己follow的大师傅个人主页跟普通的不太一样: 猜测应该是Github啥时候出现的新功能,查了一下,发现可以通过创建同名仓库来实现个人主页的美化设置 首先在 GitHub 上建立一个与自 ...
- CTF写脚本
今天总结一下CTF如何写脚本快速得分....(比较菜,能力有限,大佬勿喷) 所谓的写脚本得分,就是利用了 python爬虫的思想,如果之前没有听说过的话,可以去爬虫的相关语法.如果是看网上的视频的话, ...
- python调用jar包
工作项目中用jmeter做接口测试,想尝试用python写接口测试(练习下python), 接口中好多字段都需要加密,而加密方法是java开发写的,打的jar包,这就需要考虑python调用java: ...
- PostgreSQL 如何忽略事务中错误
在 PostgreSQL 的事务中:执行的SQL遇到错误(书写,约束限制):该事务的已经执行的SQL都会进行rollback.那如何忽略其中的错误.将SQL执行到底?在事务中设置 ON_ERROR_R ...
- sql server的bcp指令
有时需要允许bcp指令 -- 允许配置高级选项EXEC sp_configure 'show advanced options', 1GO-- 重新配置RECONFIGUREGO-- 启用xp_cmd ...
- PHP字符串你不知道的事
PHP常见的定义字符串的方式有那些? 1.单引号 在单引号中,任何特殊字符都会按原样输出[除\.\'将会被转义输出],不是什么都不解析的,这是很多人的误解 echo 'this is a var!'. ...