静态资源压缩(GZIP) 专题

1.开GZIP有什么好处?
答:Gzip开启以后会将输出到用户浏览器的数据进行压缩的处理,这样就会减小通过网络传输的数据量,提高浏览的速度。
Tips:
如果网站的用户分布比较分散,并且静态文件过大,可以将静态文件放到CDN


Spring Boot中进行如下配置即可:

server.compression.enabled=true

73.20 Enable HTTP response compression
HTTP response compression is supported by Jetty, Tomcat, and Undertow. It can be enabled via application.properties:

server.compression.enabled=true
By default, responses must be at least 2048 bytes in length for compression to be performed. This can be configured using the server.compression.min-response-size property.

By default, responses will only be compressed if their content type is one of the following:

text/html
text/xml
text/plain
text/css
This can be configured using the server.compression.mime-types property.

package org.springframework.boot.context.embedded;

/**
 * Simple container-independent abstraction for compression configuration.
 *
 * @author Ivan Sopov
 * @author Andy Wilkinson
 * @since 1.3.0
 */
public class Compression {

    /**
     * If response compression is enabled.
     */
    private boolean enabled = false;

    /**
     * Comma-separated list of MIME types that should be compressed.
     */
    private String[] mimeTypes = new String[] { "text/html", "text/xml", "text/plain",
            "text/css", "text/javascript", "application/javascript" };

http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#how-to-enable-http-response-compression

In application.properties 1.2.2 - <1.3

server.tomcat.compression: on
server.tomcat.compressableMimeTypes=application/json,application/xml,text/html,text/xml,text/plai

Older than 1.2.2:

@Component
public class TomcatCustomizer implements TomcatConnectorCustomizer {

  @Override
  public void customize(Connector connector) {
    connector.setProperty("compression", "on");
    // Add json and xml mime types, as they're not in the mimetype list by default
    connector.setProperty("compressableMimeType", "text/html,text/xml,text/plain,application/json,application/xml");
  }
}

https://stackoverflow.com/questions/21410317/using-gzip-compression-with-spring-boot-mvc-javaconfig-with-restful

Nginx启用gzip

随着nginx的发展,越来越多的网站使用nginx,因此nginx的优化变得越来越重要,今天我们来看看nginx的gzip压缩到底是怎么压缩的呢?
gzip(GNU-ZIP)是一种压缩技术。经过gzip压缩后页面大小可以变为原来的30%甚至更小,这样,用户浏览页面的时候速度会块得多。gzip的压缩页面需要浏览器和服务器双方都支持,实际上就是服务器端压缩,传到浏览器后浏览器解压并解析。浏览器那里不需要我们担心,因为目前的巨大多数浏览器都支持解析gzip过的页面。
Nginx的压缩输出有一组gzip压缩指令来实现。相关指令位于http{….}两个大括号之间。

默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不少带宽,但是会增加服务器CPU的开销哦(与节约带宽相比,宁愿选择节约带宽,节约带宽就是快速响应用户的访问),如下图,
Nginx默认只对text/html进行压缩 ,如果要对html之外的内容进行压缩传输,我们需要手动来调。 开启gzip的指令如下:

1 gzip on;
2 gzip_min_length 1k;
3 gzip_buffers 4 16k;
4 #gzip_http_version 1.0;
5 gzip_comp_level 2;
6 gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
7 gzip_vary off;
8 gzip_disable "MSIE [1-6]\.";

 

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;


    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    #gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript                 application/javascript  text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
   gzip_vary off;
    gzip_disable "MSIE [1-6]\.";


}

 

 

gzip on;

//该指令用于开启或关闭gzip模块(on/off)

gzip_min_length 1k;
不压缩临界值,大于1K的才压缩,一般不用改
//设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。

gzip_buffers 4 16k;
//设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存。

gzip_http_version 1.1;
这个后面有专门介绍
//识别http的协议版本(1.0/1.1)

gzip_comp_level 2;
//gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)

gzip_types text/plain application/x-JavaScript text/css application/xml
//匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
进行压缩的文件类型,缺啥补啥就行了,JavaScript有两种写法,最好都写上吧,总有人抱怨js文件没有压缩,其实多写一种格式就行了

关于gzip_types,如果你想让图片和js文件也开启gzip压缩,那么用以下这段吧:
gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-PHP image/jpeg image/gif image/png;

gzip_vary on;
//和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
跟Squid等缓存服务有关,on的话会在Header里增加"Vary: Accept-Encoding",我不需要这玩意,自己对照情况看着办吧
第8行:IE6对Gzip不怎么友好,不给它Gzip了

注意:
1. 其中的gzip_http_version的设置,它的默认值是1.1,就是说对HTTP/1.1协议的请求才会进行gzip压缩
如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间是用HTTP/1.0协议通信的
This module makes it possible to transfer requests to another server.
It is an HTTP/1.0 proxy without the ability for keep-alive requests yet. (As a result, backend connections are created and destroyed on every request.) Nginx talks HTTP/1.1 to the browser and HTTP/1.0 to the backend server. As such it handles keep-alive to the browser.
如果我们使用nginx通过反向代理做Cache Server,而且前端的nginx没有开启gzip
同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩

2. gzip_disable的设置是禁用IE6的gzip压缩,又是因为杯具的IE6
IE6的某些版本对gzip的压缩支持很不好,会造成页面的假死,今天产品的同学就测试出了这个问题
后来调试后,发现是对img进行gzip后造成IE6的假死,把对img的gzip压缩去掉后就正常了
为了确保其它的IE6版本不出问题,所以就加上了gzip_disable的设置

http://blog.csdn.net/eflyq/article/details/12905215

4、:wq保存退出,重新加载Nginx

/usr/local/nginx/sbin/nginx -s reload

 

5、用curl测试Gzip是否成功开启

curl -I -H "Accept-Encoding: gzip, deflate" "http://www.slyar.com/blog/"

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Sun, 26 Aug 2012 18:13:09 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.2.17p1
X-Pingback: http://www.slyar.com/blog/xmlrpc.php
Content-Encoding: gzip

页面成功压缩

 

curl -I -H "Accept-Encoding: gzip, deflate" "http://www.slyar.com/blog/wp-content/plugins/photonic/include/css/photonic.css"

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Sun, 26 Aug 2012 18:21:25 GMT
Content-Type: text/css
Last-Modified: Sun, 26 Aug 2012 15:17:07 GMT
Connection: keep-alive
Expires: Mon, 27 Aug 2012 06:21:25 GMT
Cache-Control: max-age=43200
Content-Encoding: gzip

css文件成功压缩

curl -I -H "Accept-Encoding: gzip, deflate" "http://www.slyar.com/blog/wp-includes/js/jquery/jquery.js"

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Sun, 26 Aug 2012 18:21:38 GMT
Content-Type: application/x-javascript
Last-Modified: Thu, 12 Jul 2012 17:42:45 GMT
Connection: keep-alive
Expires: Mon, 27 Aug 2012 06:21:38 GMT
Cache-Control: max-age=43200
Content-Encoding: gzip

js文件成功压缩

curl -I -H "Accept-Encoding: gzip, deflate" "http://www.slyar.com/blog/wp-content/uploads/2012/08/2012-08-23_203542.png"

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Sun, 26 Aug 2012 18:22:45 GMT
Content-Type: image/png
Last-Modified: Thu, 23 Aug 2012 13:50:53 GMT
Connection: keep-alive
Expires: Tue, 25 Sep 2012 18:22:45 GMT
Cache-Control: max-age=2592000
Content-Encoding: gzip

图片成功压缩

curl -I -H "Accept-Encoding: gzip, deflate" "http://www.slyar.com/blog/wp-content/plugins/wp-multicollinks/wp-multicollinks.css"

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Sun, 26 Aug 2012 18:23:27 GMT
Content-Type: text/css
Content-Length: 180
Last-Modified: Sat, 02 May 2009 08:46:15 GMT
Connection: keep-alive
Expires: Mon, 27 Aug 2012 06:23:27 GMT
Cache-Control: max-age=43200
Accept-Ranges: bytes

最后来个不到1K的文件,由于我的阈值是1K,所以没压缩

http://www.cnblogs.com/mitang/p/4477220.html

今天这篇文章属于计划之外的更新,源自于白天看到的《一个基于 http 协议的优化》。在这篇文章中,作者描述了这样一个现象:

在移动的 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
于是,对于本文前面提出的情况,HTTP Server 只能要么不压缩,要么不启用持久连接(对于非持久连接,TCP 断开就可以认为 HTTP 报文结束),而 Nginx 默认选择的是前者。

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

在很久以前,我们为了降低服务端的 CPU 压力,往往会把静态资源预先压缩为 .gz 文件,这样 HTTP Server 不需要即时压缩文件,也就不会遇到本文提到的这个问题。但随着时间的推移,现在几乎没人会这么干了,想要了解预先压缩细节的同学可以看下 Nginx 的 ngx_http_gzip_static_module 模块。

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

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

可以看到,尽管我的请求报文中指明了可以接受 GZip,但是返回的内容依然是未压缩的;同时服务端响应了 Content-Length 和 Connection: keep-alive,连接并没有断开。也就是说对于 HTTP/1.0 请求,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 文档或 JSON 接口一般都是用 PHP、Node.js 等服务端语言动态输出,即使不压缩,Nginx 也无法事先得知它的 Content-Length,在 HTTP/1.0 中无论如何都无法启用持久连接,这时还不如启用 GZip 省点流量。

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

而对于图片类静态资源,由于主流图片格式都已经经过高度压缩,实在没必要再浪费服务端 CPU 来开启 GZip,这样也不会对 keep-alive 机制产生影响。

本文先写到这里,欢迎来博客原文进行评论、交流。浏览器的 GZip 其实还有很多有趣的小故事,先卖个关子,以后有空再写。

本文链接:https://imququ.com/post/why-nginx-disable-gzip-in-http10.html

 

在http 的响应头中有时会见到这样的字段:Transfer-Encoding: chunked,这是一种分段传输数据的方式。如果对此格式不了解,直接将响应体以某一编码转换成字符串,就会出现乱码。result = new String(data, "utf-8");data为接受的数据。
分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网
页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

通常,HTTP应答消息中发送的数据是整个发送的,Content-Length消息头字段表示数据的长度。数据的长度很重要,因为客户端需要知道哪里是应答消息的结束,以及后续应答消息的开始。
然而,使用分块传输编码,数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。通常数据块的大小是一致的,但也不总是这种情况。

格式
如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束

每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。

最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。

消息最后以CRLF结尾

例子

编码的应答

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con

8
sequence

0

编码应答的解释
前两个块的数据中包含有显式的\r\n字符。

"This is the data in the first chunk\r\n"      (37 字符 => 十六进制: 0x25)
"and this is the second one\r\n"               (28 字符 => 十六进制: 0x1C)
"con"                                          (3  字符 => 十六进制: 0x03)
"sequence"                                     (8  字符 => 十六进制: 0x08)

应答需要以0长度的块( "0\r\n\r\n".)结束。

解码的数据

This is the data in the first chunk
and this is the second one
consequence

https://zh.wikipedia.org/wiki/%E5%88%86%E5%9D%97%E4%BC%A0%E8%BE%93%E7%BC%96%E7%A0%81






 

 

 

 

如何启用IIS的Gzip压缩功能:
答:首先,如果你需要压缩静态文件(HTML),需要在硬盘上建一个目录,并给它“IUSR_机器名”这个用户的写权限。如果压缩动态文件(PHP,asp,aspx)就不需要了,因为它的页面是每次都动态生成的,压缩完就放弃。然后在IIS管理器中,“网站”上面右键-属性,不是下面的某个站点,而是整个网站。进入“服务”标签,选上启用动态内容压缩,静态内容压缩。然后选中网站下面那个服务器扩展,新建一个服务器扩展。名字无所谓,下面的添加文件的路径是: c:\windows\system32\inetsrv\gzip.dll,然后启用这个扩展。这时候静态内容是可以压缩的,但是对于动态内容,aspx文件却不在压缩范围内。因为默认的可压缩文件并没有这个扩展名。而管理界面中你又找不到可以增加扩展名的地方,这时候只能去修改它的配置文件了。在c:\windows\system32\inetsrv\下面有个MetaBase.xml文件,可以用记事本打开,找到IIsCompressionScheme,有三个相同名字的段,分别是deflate,gzip,Parameters,第三段不用管它,前两段有基本相同的参数,在这两段的参数HcScriptFileExtensions下面都加上一行aspx,如果你有其它的动态程序要压缩,也加在这里。HcDynamicCompressionLevel改成9,(0-10,9是性价比最高的一个)。然后需要重启一下IIS服务,就可以体会到压缩后的速度了。
网站gzip检测:
http://tool.chinaz.com/Gzips/

LNMP一键安装包是什么?

LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RHEL/Fedora/Aliyun/Amazon、Debian/Ubuntu/Raspbian/DeepinServer/Mint Linux VPS或独立主机安装LNMP(Nginx/MySQL/PHP)、LNMPA(Nginx/MySQL/PHP/Apache)、LAMP(Apache/MySQL/PHP)生产环境的Shell程序。
我们为什么需要它?
编译安装需要输入大量的命令,如果是配置生产环境需要耗费大量的时间。
不会Linux的站长或Linux新手想使用Linux作为生产环境……

它有什么优势和功能?
无需一个一个的输入命令,无需值守,编译安装优化编译参数,提高性能,解决不必要的软件间依赖,特别针对配置自动优化。

支持自定义Nginx、PHP编译参数及网站和数据库目录、支持生成LetseEcrypt证书、LNMP模式支持多PHP版本、支持单独安装Nginx/MySQL/MariaDB/Pureftpd服务器,同时提供一些实用的辅助工具如:虚拟主机管理、FTP用户管理、Nginx、MySQL/MariaDB、PHP的升级、常用缓存组件Redis/Xcache等的安装、重置MySQL root密码、502自动重启、日志切割、SSH防护DenyHosts/Fail2Ban、备份等许多实用脚本。

如何获取它?
你可以自由 下载 并使用它在VPS或独立服务器上,做为真正的生产环境或测试环境。

我们为什么采用LNMP这种架构?
采用Linux、PHP、MySQL的优点我们不必多说。

Nginx是一个小巧而高效的Linux下的Web服务器软件,是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,已经在一些俄罗斯的大型网站上运行多年,目前很多国内外的门户网站、行业网站也都在是使用Nginx,相当的稳定。

Nginx相当的稳定、功能丰富、安装配置简单、低系统资源……

https://lnmp.org/

posted @ 2017-07-15 22:19  沧海一滴  阅读(2580)  评论(0编辑  收藏  举报