在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前言大家都知道压缩包如果不解压直接查看的话,都是一堆乱码,目前我们使用nginx+lua 对用户请求进行代理时( 客户端-->ngx+lua-->后端服务器 ),发现有些请求返回的数据都是乱码,这就乱码的原因就是直接查看未解压的压缩包 问题表现我们在上线候测试时,发现浏览器某个按钮不能用了,通过F12查看发现这个请求返回内容都是乱码,如下所示: 我又上日志上查看,发现nginx记录的日志也是乱码,如下所示: 排查过程我第一感觉认为是后端服务器返回了乱码数据给我,所以才是乱码的,呵呵。于是找负责人去了,人家说没有动呀。于是我们只能从自己身上找问题。我想了以下可能会出问题的点:
第一点毫无疑问排除后,就准备验证第二点,我通过tcpdump 在服务端(后端服务器)和nginx+lua上抓包,抓包能够分析的更全面所以优先考虑它,然后下载PC机用wireshark 分析,由于是HTTPS传输的,都是加密的内容,wireshark 啥也看不到,如下所示: 我参考网上很多文章尝试去解开这个HTTPS数据流,结果都搞不定,花了半天时间,就放弃了。那怎么去验证?换条路,nginx+lua里面使用的 lua-resty-http(github地址) 模块去构造HTTP请求,那可以很方便查看接受到的数据长度,在日志里面打印出接受的数据长度即可,然后查看后端服务器的nginx日志,看看nginx发送的数据长度有多少。 lua记录接收到的数据长度:
我通过对比发现,nginx+lua收到的数据竟然是510字节,而后端服务器的nginx日志显示发送了1300字节,这个怎么回事呢? 难道真的是因为数据没有收全导致乱码? 带着这些问题,我继续深挖。 我首先翻开lua-resty-http的源代码,基本上把request_uri这个方法的仔细看了一遍,然后在里面各个条件分支上打了日志,发现乱码的请求,都会走到这个条件分支:
这大概找到了前进的方向了,chunked 这个关键字。然后继续往下走,在
我一开始没有想明白这个怎么回事(原谅鄙人才疏学浅),经过查阅相关资料才发现,chunked传输都是16进制的,所以这个长度在这里转了下,需要转为16进制。 ,于是继续往前走 我对比了不乱码的请求和乱码的请求,发现请求的头信息,接口地址都一样,唯一不同的就是GQL语句不一样,我又对比返回来的头信息,发现乱码的头信息多了2字段,他们是
第一个chunked表示数据太长需要进行分片(个人理解,应该没有理解歪曲),第二个gzip表示内容编码 格式为 gzip,其实还有点被我忽略了,前端请求时的头信息有这一段:Accept-Encoding: gzip ,这表明可以返回的数据接受gzip的编码。所以服务器端就进行压缩了。 了解了以上几点,我此时大概可以推断出来。 ngx+lua 接受的数据是510,数据不全的原因那么就有4种情况:
到此,只能是一一排除了。我最开始去验证第二个情况,我把接收到的乱码内容写到磁盘上,再拿到PC机的360解压,发现解压后的内容就是json串。
处理方法显然,我们一下子就碰对了。找到问题了,这个就是后端服务器返回数据的时候,由于数据稍微长点,所以就进行了压缩,导致nginx+lua 接收到的数据是二进制的,需要再解压下才能还原回json串。于是添加以下代码:
至此,添加完这个代码,重启下nginx,问题被解决了。 zlib 的使用方法可以查看官网: https://github.com/brimworks/lua-zlib/ 安装zlib我这里使用apt安装,源码安装比较费劲,所以推荐使用apt-get或yum 。ubuntu系统如下
杂谈问题1为什么会被压缩,我个人认为是 nodejs 发请求时明确了可以接受gzip压缩内容,http头信息里面 Accept-Encoding: gzip 表明了这点,所以后端返回了压缩内容, 问题2奇怪的是,我看所有的请求头信息都有这个字段,但是只有个别请求的内容被压缩了。我个人认为是数据长度太长了。首次发现乱码的请求,返回的数据长度接近2K |
请发表评论