Nginx系列:数据压缩

2020-08-20 22:20:36 浏览数 (1)

【Nginx系列:Nginx源码安装】中源码安装Nginx时,讲到需要安装zlib和zlib-devel是因为两个库提供了压缩功能,而Nginx的ngx_http_gzip_module模块就是使用这两个库进行数据压缩的。

gzip是nginx服务器的ngx_http_gzip_module模块提供的在线实时数据压缩功能。通过开启gzip功能,可对服务器响应的数据进行压缩处理,变成体积更小的二进制文件。在高PV的网站应用中,可以节省海量的带宽。

如图所示,客户端浏览器发出的请求头中声明了支持gzip类型的压缩文件,若服务器端开启了gzip压缩功能,那么响应数据会经过压缩后再返回客户端,由客户端负责解压缩后再进行数据渲染。

0x01:Nginx压缩相关参数

  • gzip on | off;

  Nginx支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文件大小将比源文件显著变小,有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相应的CPU资源。

代码语言:javascript复制
gzip on; 

参数来启用压缩,默认是关闭的。

  • gzip_comp_level lenvel;

  压缩比例由低到高从1到9,默认为1。但需要注意的是压缩比设置的越高就会越消耗CPU的资源,因此在生产环境中我们会设置该参数的值在3~5之间,最好不要超过5,因为随着压缩比的增大的确会降低传输的带宽成本但发送数据前会占用更多的CPU时间分片。

  具体设置级别为多少,得运维人员对CPU的利用率做一个监控,如果CPU利用率过低则不会使用,可以酌情将压缩级别参数调大,当然调大后依旧需要观察一段业务高峰期时间CPU的利用率,最终会找到一个适合的压缩比例。

  • gzip_disable "MSIE [1-6].";

禁用IE6 gzip功能。

  • gzip_min_length 1k;

gzip压缩的最小文件,小于设置值的文件将不会压缩

  • gzip_http_version 1.0|1.1;

  启用压缩功能时,协议的最小版本,默认HTTP/1.1

  • gzip_buffers number size;

  指定Nginx服务需要向服务器申请的缓存空间的个数*大小,默认32 4k|16 8k;

  • gzip_types mine-type ...;

text/html外,还对指定的MIME类型启用响应的压缩。特殊值“ *”匹配任何MIME类型(0.8.29)。text/html类型的响应始终被压缩。

  • gzip_vary on| off;

  如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,建议开启该参数,让用户知道服务端是支持压缩功能。

推荐查看官网说明

代码语言:javascript复制
https://nginx.org/en/docs/http/ngx_http_gzip_module.html

0x02:SpringBoot项目准备

在进行Nginx负载均衡配置前,先搭建一个简单的后端应用项目:nginx-upstream

  • pom.xml文文件
代码语言:javascript复制
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sentinel</groupId>
    <artifactId>nginx-upstream</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <name>nginx-upstream</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>
  • 控制器controller

该控制器返回一个txt文件里的数据,其中这个文件的大小如下图

代码语言:javascript复制
package com.olive.controller;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/getUser")
    public Map<String, Object> getUser() {
        Map<String, Object> result = new HashMap<>();
        result.put("code", "000000");
        result.put("message", "ok");
        try {
            FileInputStream in = new FileInputStream("d:/a.txt");
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int len =-1;
            byte[] b = new byte[1024];
            while((len=in.read(b))!=-1){
                out.write(b, 0, len);
            }
            result.put("body", new  String(out.toByteArray()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
  • application.yml配置文件
代码语言:javascript复制
server:
  port: 8866

spring:
  application:
    name: nginx-upstream
  • SpringBoot启动类
代码语言:javascript复制
package com.olive;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

启动项目,验证是否搭建成功

0x03:配置Nginx

先把上篇的8867这台服务器注释,因为本篇只开启了8866这台服务器。

在没有开启压缩时,即配置项为

代码语言:javascript复制
gzip off;

访问Nginx,返回的数据的大小跟直接访问Springboot项目的8866端口的大小是一模一样的。

开启Nginx的压缩功能,在Nginx的配置文件nginx.conf添加如下配置项

代码语言:javascript复制
    # 在http上下文中添加gzip配置
    gzip  on;
    gzip_buffers 32 4K;
    gzip_comp_level 6;
    gzip_min_length 200;
    gzip_types application/json;

重启Nginx,再次访问Nginx

可以看到开启压缩后,返回数据的大小仅有8.7K,比没有开启压缩的数据大小1.4M,小了非常大。

附录:

【Nginx系列:负载均衡】文件少了Controller部分代码,具体代码如下

代码语言:javascript复制
package com.olive.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/getUser")
    public Map<String, Object> getUser() {
        Map<String, Object> result = new HashMap<>();
        result.put("code", "000000");
        result.put("message", "ok");
        result.put("body", "我是服务器8866");
//        result.put("body", "我是服务器8867");
        return result;
    }
}

0 人点赞