我的项目使用Spring Boot 1.5.10.RELEASE,但Gzip压缩无法正常工作。

14

我正在使用Spring Boot 1.5.10.RELEASE版本,但Gzip压缩不起作用。

http://localhost:9000 --> http://localhost:8080/api/..

Angularjs和rest api在不同的端口上。启用CrossOrigin以接受来自angularjs ui的请求。

使用嵌入式tomcat服务器部署spring boot应用程序。 未使用http2属性,即server.http2.enabled=true

Angualrjs调用rest api。以下是$http服务:

$http({
  method: method,
  url: url,
  params: params,
  data: body,
  headers: {
    Authorization: token,
    "Content-type": 'application/json'
  }
});

Rest API响应大小约为25 MB,因此我想压缩响应。

我已经在 application.properties 中添加了一个著名的属性来应用gzip压缩。 Spring Boot 1.5.10支持的属性

# Enable response compression
server.compression.enabled=true

# The comma-separated list of mime types that should be compressed
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json

# Compress the response only if the response size is at least 1KB
server.compression.min-response-size=1024

我观察了网络选项卡,没有在响应头中观察到Content-Encoding: gzip

请求

Request URL: http://localhost:9081/employee
Request Method: GET
Status Code: 200 
Remote Address: [::1]:9081
Referrer Policy: no-referrer-when-downgrade

响应头

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:7000
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Sun, 28 Jun 2020 18:15:17 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: JSESSIONID=6E7C07874D0329E18A0C07E5E303F005; Path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Origin
X-Application-Context: application
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

请求头

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer eyJhbGciOiJIUzINiJ9.eyJyb2xlIjiU0VDVE9SSEVBRCIsImxldmVsRG93biI6IkVENzA0MTI7TU04MzcyNDtKTDgzNTwO0RNNDAwNzE7Skc3MzA0NjtFQzM0NjEzO05OMTY5Nzk7QUs2MDYzNztTVDE4NTg4O0FTMjczNTE7Q0I4MTg3OTtWQTc4MTk5O0NNOTM3MDA7QVkyMzYzNztKUzcwMDY4O0NCMTc2NzE7TksyMTU2MDtMUzg4OTg0O0FQNTg3MDg7VFcyjk0NTtKSzI1Nzc3O01TNDk5MjE7SkI4OTcyOTtNSDAyMTI3O01CMTUwODk7SU0xMjgwODtNQzcxOTc2O1JSMjAzMDI7TFM1ODk4MiIsImxldmVsVXAiOm51bGwsImRlbGVnYXRlZCI6bnVsbCwic29lSWQiOiJTUjQ0MTg1I0.*************
Cache-Control: no-cache
Connection: keep-alive
Content-type: application/json
Host: localhost:9081
Origin: http://localhost:7000
Pragma: no-cache
Referer: http://localhost:7000/build/standalone.html
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36

我在响应头中没有获得以下预期的标头

Content-Encoding: gzip
Vary: Accept-Encoding

有任何更改需要在客户端/服务器端进行吗?

--- [编辑-1] ------------- 尝试在个别项目中使用gzip是有效的,但在我的项目中无效。

从浏览器调用rest api时以下是响应标头

Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Sun, 28 Jun 2020 18:12:29 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding

-----[Edit-2]-----Ziplet----

使用ziplet依赖项,我能够压缩响应,但我希望使用Spring Boot gzip压缩。

响应头 - 当使用Ziplet时

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:7000
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Mon, 06 Jul 2020 18:31:07 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: JSESSIONID=8465D2E81A1A9CE146255B6C545FBE30; Path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Accept-Encoding
Vary: Origin
X-Application-Context: application
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

使用Ziplet时 - 我可以看到 CompressingFilter:CompressingFilter已初始化

在使用Spring Boot gzip压缩时,没有观察到任何可以假定启用了gzip压缩的地方。

有没有用于调试嵌入式Tomcat的Spring Boot gzip压缩的属性? 例如:logging.level.org.eclipse.jetty.server.handler.gzip=TRACE

如何验证server.compression.enabled?

我的项目中需要在客户端/服务器端进行任何更改吗?

提前致谢。


将您的代码存储库放入测试中。 - Anish B.
2
那是使用过滤器而不是依赖于Tomcat支持(如果我正确理解了你的问题),因此你基本上在比较两种不同的机制。 - M. Deinum
@JamesMead 我正在使用嵌入式Tomcat。我已经在问题中更新了更多信息。 - StackOverFlow
我们在Spring Boot应用程序中处理gzip的方式是使用压缩过滤器。当接收到一个带有Accept-Encoding gzip的请求时,我们将响应头Content-Encoding设置为gzip,并将响应对象包装成CompressionResponseWrapper传递给过滤器链。当然,如果请求没有带有该头,则不进行包装并按原样传递。由于限制,我无法分享代码,但可以给您一些互联网上的示例参考。 - Vivek
Accept-Encoding头是否传递到Spring Boot?您在Angular和Spring Boot之间使用代理,请确保不会过滤掉任何内容。尝试直接调用Spring Boot而不是通过代理(例如使用Postman)。 - M. Deinum
显示剩余7条评论
2个回答

3
根据您的问题,您正在使用Spring Boot 1.5.10.RELEASE版本。该框架版本中,类TomcatEmbeddedServletContainerFactory负责启动嵌入式Tomcat容器。该类和版本的源代码可以在此处找到:https://github.com/spring-projects/spring-boot/blob/v1.5.10.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java。在这个类中,您可以找到方法customizeCompression:
private void customizeCompression(Connector connector) {
  ProtocolHandler handler = connector.getProtocolHandler();
  if (handler instanceof AbstractHttp11Protocol) {
    AbstractHttp11Protocol<?> protocol = (AbstractHttp11Protocol<?>) handler;
    Compression compression = getCompression();
    protocol.setCompression("on");
    protocol.setCompressionMinSize(compression.getMinResponseSize());
    configureCompressibleMimeTypes(protocol, compression);
    if (getCompression().getExcludedUserAgents() != null) {
      protocol.setNoCompressionUserAgents(
          StringUtils.arrayToCommaDelimitedString(
              getCompression().getExcludedUserAgents()));
    }
  }
}

尝试在此方法上设置断点并调试您的应用程序,以查看是否实际启用了压缩。

如果没有启用,则很可能是项目中的某种错误配置。

如果它有效,则表示您的配置正确,并且问题不同。

如果是这种情况,在查看其他内容之前,可能适合尝试另一个服务器,例如 Jetty 或 Undertow,它们也支持此压缩功能,并查看是否在那里一切正常。

例如,要配置 Undertow 而不是 Tomcat,可以使用以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

您也可以编写代码配置Tomcat压缩,具体请参见matsev在stackoverflow问题的回答:Using GZIP compression with Spring Boot/MVC/JavaConfig with RESTful

-1

你需要在Spring Boot属性中启用http2支持

  server.http2.enabled=true

然后尝试


2
这更像是一条评论而不是答案。您能详细说明为什么gzip压缩需要http2吗?我相信早在http2出现之前就已经有gzip压缩了,所以这一点并不清楚。 - Edwin Dalorzo
哦,我的错,我误读了,我以为问题中提到要使用http2。 - Vishal Varshney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接