在移动的 http 请求量和联通不相上下的前提下,移动的 http response 带来的网络流量是联通的 2.5 倍。移动大概有 3 成的请求都没有做压缩,而联通几乎都是经过压缩的。那些没有经过压缩的 http 会话都是走了 1.0 的协议,相反经过压缩的 http 会话都是走了 http1.1 协议。

也就是说在相同的服务端配置下,移动运营商过来的流量中有 30% 走了 HTTP/1.0,而作者所使用的 HTTP Server,不对 HTTP/1.0 响应启用 GZip。

为什么在移动运营商网络下会有这么高比例的 HTTP/1.0 请求,本文按下不表,总之这一定是移动的原因。直接看另外一个问题,也就是本文标题所写:Nginx 为什么默认不压缩 HTTP/1.0?

那篇文章的作者并没有说明他用什么 HTTP Server,我这里直接当成 Nginx 好了。后面会发现这个问题跟 HTTP 协议有关,所有 HTTP Server 都会面临。

在 Nginx 的官网文档中,有这样一个指令:

Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location
Sets the minimum HTTP version of a request required to compress a response.

很明显,这个指令是用来设置 Nginx 启用 GZip 所需的 HTTP 最低版本,默认是 HTTP/1.1。也就是说 Nginx 默认不压缩 HTTP/1.0 是因为这个指令,将它的值改为 1.0 就能解决问题。

对于文本文件,GZip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3。这么好的事情,Nginx 改一下配置就可以支持,为什么它默认不开启?

Nginx 对于满足条件(请求头中有 Accept-Encoding: gzip,响应内容的 Content-Type 存在于 gzip_types 列表)的请求会采用即时压缩(On-The-Fly Compression),整个压缩过程在内存中完成,是流式的。也就是说,Nginx 不会等文件 GZip 完成再返回响应,而是边压缩边响应,这样可以显著提高 TTFB(Time To First Byte,首字节时间,WEB 性能优化重要指标)。这样唯一的问题是,Nginx 开始返回响应时,它无法知道将要传输的文件最终有多大,也就是无法给出 Content-Length 这个响应头部。

我们还知道,HTTP/1.1 默认支持 TCP 持久连接(Persistent Connection),HTTP/1.0 也可以通过显式指定 Connection: keep-alive 来启用持久连接。HTTP 运行在 TCP 连接之上,自然也有着跟 TCP 一样的三次握手、慢启动等特性,为了尽可能的提高 HTTP 性能,使用持久连接就显得尤为重要了。

明白以上两点,问题就水落石出了。对于 TCP 持久连接上的 HTTP 报文,客户端需要一种机制来准确判断结束位置,而在 HTTP/1.0 中,这种机制只有 Content-Length。于是,前面这种情况只能要么不压缩,要么不启用持久连接(对于非持久连接,TCP 断开就可以认为 HTTP 报文结束),而 Nginx 默认选择的是前者。

那么在 HTTP/1.1 中,这个问题解决了吗?当然!我在之前的文章中讲过,HTTP/1.1 新增的 Transfer-Encoding: chunked 所对应的分块传输机制可以完美解决这类问题。

理论知识先写到这里,最后用实践来验证一下:

首先,不启用 Nginx 的 HTTP/1.0 GZip 功能,使用 HTTP/1.0 请求报文测试:

可以看到,尽管我的请求报文中指明了可以接受 GZip,但是返回的内容依然是未压缩的;同时服务端响应了 Content-Length 和 Connection: keep-alive,连接并没有断开。也就是说 Nginx 为了尽可能启用持久连接,放弃了 GZip,这是 Nginx 的默认策略。

然后,启用 Nginx 的 HTTP/1.0 GZip 功能,使用 HTTP/1.0 请求报文测试:

可以看到,这次的请求报文与上次完全一样,但是结果截然不同:虽然返回的内容被压缩了,但是连接也被断开了,服务端返回了 Connection: close。原因就是之前说过的,动态压缩导致无法事先得知响应内容长度,在 HTTP/1.0 中只能依靠断开连接来让客户端知道响应结束了。

最后,使用 HTTP/1.1 请求报文测试:

可以看到,由于请求报文是 HTTP/1.1 的,Nginx 能知道这个客户端可以支持 HTTP/1.1 的 Transfer-Encoding: chunked,于是通过分块传输解决了所有问题:既启用了压缩,也启用了持久连接。

那么,对于 HTTP/1.0 请求,我们是让 Nginx 放弃持久连接好,还是放弃 GZip 好呢?

实际上,由于 HTML 文档一般都是使用 PHP、Node.js 等动态语言输出,即使不压缩,Nginx 也无法事先得知它的 Content-Length,在 HTTP/1.0 中横竖都无法启用持久连接,这时还不如启用 GZip 省点流量。

对于 JS、CSS 等事先可以知道大小的静态文本文件,我的建议是,移动端首次访问把重要的 JS、CSS 都内联在 HTML 中,然后存在 localStorage 里,后续不输出;不重要的 JS、CSS 外链并启用 GZip,牺牲 keep-alive 来达到减少流量的目的。

Nginx-默认不压缩HTTP/1.0与长连接的关系的更多相关文章

  1. Nginx与Tomcat、Client之间请求的长连接配置不一致问题解决[转]

    http://bert82503.iteye.com/blog/2152613 前些天,线上出现“服务端长连接与客户端短连接引起Nginx的Writing.Active连接数过高问题”,这个是由于“服 ...

  2. nginx学习之压缩解压篇(七)

    1.简介 压缩响应可以减少传输数据的大小,节省带宽.但过多的压缩会造成很大的处理开销.在发送给客户端之前,nginx会对响应做压缩,但是如果后端服务器已经 压缩过了,nginx就不再压缩. 2.开启压 ...

  3. nginx反向代理时保持长连接

    ·[场景描述] HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟. 如果我们使用了nginx去作为 ...

  4. Nginx 笔记与总结(13)Nginx 的 gzip 压缩

    使用 FireFox(40.0)访问博客园(http://www.cnblogs.com/),观察 http 头信息 请求头信息: Accept-Encoding gzip, deflate 表示浏览 ...

  5. Nginx 启用gzip压缩

    1. 网页压缩 网页压缩是一项由 WEB 服务器和浏览器之间共同遵守的协议,也就是说 WEB 服务器和浏览器都必须支持该技术,所幸的是现在流行的浏览器都是支持的,包括 IE.FireFox.Opera ...

  6. 开启Nginx的gzip压缩功能详解

    默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不少带宽,但是会增加服务器CPU的开销哦,Nginx默认只对text/html进行压缩 ,如果要对html之外的内容进行 ...

  7. Nginx开启gzip压缩功能

    在Nginx安装完成之后,我们可以开启Gzip压缩功能,这里Nginx默认只能对text/html类型的文件进行压缩.下面的指令为开启Gzip的指令: gzip on; gzip_http_versi ...

  8. Nginx 开启gzip压缩(图片,文件,css)

    1.Vim打开Nginx配置文件 vim /usr/local/nginx/conf/nginx.conf 2.找到如下一段,进行修改 gzip on; gzip_min_length 1k; gzi ...

  9. Nginx 开启gzip 压缩,实现基于域名的虚拟主机。

    一:gzip(GNU-ZIP)是一种压缩技术. 经过gzip压缩后页面大小可以变为原来的30%甚至更小,这样,用户浏览页面的时候速度会块得多. gzip 的压缩页面需要浏览器和服务器双方都支持,实际上 ...

随机推荐

  1. Sprint 2(第一天)

    Sprint 2计划会议: 目标: 1.实现用户模块的权限控制,能够进行用户登录的功能 2.对菜单模块实现增加菜单列表详情,修改菜单列表详情,删除菜单列表详情,查询菜单列表详情的功能 3.实现菜品分类 ...

  2. android assets文件夹浅谈

    ---恢复内容开始--- 最近在研究assets文件夹的一些属性跟使用方法.根据网上一些文章.实例做一下汇总,拿出来跟大家分享下,有不足的地方还请多多指教. 首先了解一下assets是干什么用的,as ...

  3. Linux内核分析——进程描述与创建

    20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验内容 ...

  4. 【笔记】Service的使用

    一.创建Service 1.创建一个myService类,来继承Service.重写其中的方法,包括:onCreate(),onStartCommend(),onDestroy(),onBind()方 ...

  5. mysqlnd cannot connect 连接错误处理方法

    mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. Please use an administra ...

  6. The first day to learn Englisht

    IF you want to go fast,to alone. IF you want to go far,go with others.

  7. html+css知识点总结(田彦霞)

    html部分 html头部声明 DOCTYPE是document type(文档类型)的简写,用来说明你用的XHTML或者HTML是什么版本.DOCTYPE声明必须放在每一个XHTML文档最顶部,在所 ...

  8. PKu 2195

    //PKu 2195 回家 By Loli_con Enail : Loli_con@outlook.com /* 题目叙述 ========= 在一个网格图中,有n个人和n个房子.每一个单位时间,每 ...

  9. 【搬砖】【Python数据分析】Pycharm中plot绘图不能显示出来

    最近在看<Python数据分析>这本书,而自己写代码一直用的是Pycharm,在练习的时候就碰到了plot()绘图不能显示出来的问题.网上翻了一下找到知乎上一篇回答,试了一下好像不行,而且 ...

  10. codeforces 732D(二分)

    题目链接:http://codeforces.com/contest/732/problem/D 题意:有m门需要过的课程,n天的时间可以选择复习.考试(如果的d[i]为0则只能复习),一门课至少要复 ...