RESTful과 함께 Spring Boot / MVC / JavaConfig와 함께 GZIP 압축 사용


95

일련의 RESTful서비스에 대해 주석 기반 java-config와 함께 Spring Boot / MVC를 사용 HTTP GZIP하고 일부 API 응답에서 스트림 압축 을 선택적으로 활성화하려고합니다 .

내 컨트롤러와에서 수동으로이 작업을 수행 할 수 byte[] @ResponseBody있지만 SpringMVC 인프라 (필터 / 기타)에 의존하고 JSON 변환 및 압축을 자동으로 수행하는 것을 선호합니다 (즉, 메서드가 POJO를 반환 함).

ResponseBody 또는 임베디드 Tomcat 인스턴스에서 GZIP 압축을 활성화하려면 어떻게해야하며 일부 응답 만 선택적으로 압축 할 수 있습니까?

감사!

추신 : 현재 XML 기반 구성이 없습니다.


GzipFilter를 확인해야합니다 .
approxiblue

2
당신이 무슨 일을하는지 알지 못한다면 HTTPS와 HTTP 압축을 사용하지 않는
닐 맥기

답변:


188

이 답변의 나머지 부분은 구식이거나 단순한 IMO (현재 gzip이 얼마나 오래 있었습니까? Java보다 더 길다 ...)에 대해 복잡합니다. 문서에서 :

application.properties 1.3 이상

# 🗜️🗜️🗜️
server.compression.enabled=true
# opt in to content types
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
# not worth the CPU cycles at some point, probably
server.compression.min-response-size=10240 

application.properties 1.2.2-<1.3

server.tomcat.compression=on
server.tomcat.compressableMimeTypes=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css

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");
  }
}

또한 이것은 임베디드 바람둥이를 실행하는 경우에만 작동합니다.

포함되지 않은 Tomcat에 배포하려는 경우 server.xml http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation 에서 활성화해야합니다.

IRL 제작 참고 :

또한이 모든 것을 방지하려면 nginx 및 / 또는 haproxy 또는 이와 유사한 Tomcat 앞에 프록시 /로드 밸런서 설정을 사용하는 것이 좋습니다. 정적 자산을 처리하고 Java / Tomcat의 스레딩 모델보다 훨씬 효율적이고 쉽게 gzip을 처리 할 수 ​​있기 때문입니다.

요청을 처리하는 대신 (또는 AWS 청구서를 실행하는 동안 데이터베이스 IO가 발생하기를 기다리는 동안 스레드 회전 / CPU / 힙을 먹고 있기 때문에 바쁘기 때문에 '고양이를 욕조에 넣고 싶지 않습니다. 왜 전통적인 Java / Tomcat이 당신이하는 일에 따라 시작하는 것이 좋은 생각이 아닐 수 있지만, 나는 탈선합니다 ...)

참조 : https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/howto.html#how-to-enable-http-response-compression

https://github.com/spring-projects/spring-boot/issues/2031


1.2.2 이전 버전에 대한 접근 방식은 Spring Boot가 TomcatConnectorCustomizer애플리케이션 컨텍스트에서 인스턴스를 찾지 않으므로 작동하지 않습니다 . 그들은, 프로그램에 등록 할 필요가TomcatEmbeddedServletContainerFactory
앤디 윌킨슨

알림 주셔서 감사합니다. 정적 / 동적 / tomcat / vs 부팅이 여전히 문제인 것 같아서 포기했습니다. 이것은 생각보다 훨씬 어렵습니다 ... Nginx 역방향 프록시 FTW!
John Culviner

3
SpringBoot에서 새 속성은 server.compression.enabled = true 및 server.compression.mime-types = XXX, YYY github.com/spring-projects/spring-boot/wiki/…입니다.
blacelle

2
스프링 부트의 경우 JSON 응답을 반환하는 여러 개의 나머지 컨트롤러가 있습니다. 일부 컨트롤러에 zip을 선택적으로 적용 할 수 있습니까?

3
압축에 대한 최소 응답 크기 (예 : 10KB)도 언급해야합니다. 그렇지 않으면 서버가 모든 요청 (예 : 0.5KB)을 압축하는 데 오버 헤드가됩니다. server.compression.min-response-size=10240
UsamaAmjad


12

이것은 기본적으로 @ andy-wilkinson이 제공 한 것과 동일한 솔루션이지만 Spring Boot 1.0부터 customize (...) 메서드에는 ConfigurableEmbeddedServletContainer 매개 변수가 있습니다.

언급 할 가치가 또 다른 것은 톰캣 만의 콘텐츠 형식을 압축한다는 것입니다 text/html, text/xml그리고 text/plain기본적으로. 다음은 압축도 지원하는 예입니다 application/json.

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer servletContainer) {
            ((TomcatEmbeddedServletContainerFactory) servletContainer).addConnectorCustomizers(
                    new TomcatConnectorCustomizer() {
                        @Override
                        public void customize(Connector connector) {
                            AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                            httpProtocol.setCompression("on");
                            httpProtocol.setCompressionMinSize(256);
                            String mimeTypes = httpProtocol.getCompressableMimeTypes();
                            String mimeTypesWithJson = mimeTypes + "," + MediaType.APPLICATION_JSON_VALUE;
                            httpProtocol.setCompressableMimeTypes(mimeTypesWithJson);
                        }
                    }
            );
        }
    };
}

이것을 Java 구성에 추가하려고 시도했지만 압축이 전혀 작동하지 않는 것으로 나타났습니다. Tomcat과 함께 Spring Boot를 임베디드 컨테이너로 사용하고 있는데이 구성 외에 설정해야하는 추가 사항이 있는지 궁금합니다.
Michael Coxon

2
Accept-Encoding: gzip,deflatecurl을 사용 하는 경우 헤더 를 지정하여 확인하십시오 .curl -i -H 'Accept-Encoding: gzip,deflate' http://url.to.your.server
matsev

9

Spring Boot 1.4 Javascript HTML Json 모든 압축에 이것을 사용하십시오.

server.compression.enabled: true
server.compression.mime-types: application/json,application/xml,text/html,text/xml,text/plain,text/css,application/javascript

이 압축을 어떻게 확인합니까?
Bhargav

@Bhargav API 응답의 응답 헤더를 참조하십시오. 헤더를 포함해야합니다. Content-Encoding:gzip
Sumit Jha


6

Tomcat에서 GZip을 Enabeling하는 것이 Spring Boot Project에서 작동하지 않습니다. 내가 사용 CompressingFilter가 발견 여기에 .

@Bean
public Filter compressingFilter() {
    CompressingFilter compressingFilter = new CompressingFilter();
    return compressingFilter;
}

@ user1127860 tnx 이것은 작동하지만 어쨌든이 필터를 더 구성하려면? 나는 봄 부팅을 사용하고 web.xml에 수동으로 말한대로 init 매개 변수를 추가 할 수없는 것 같습니다
Spring

5

GZIP 압축을 사용하려면 포함 된 Tomcat 인스턴스의 구성을 수정해야합니다. 이를 위해 EmbeddedServletContainerCustomizerJava 구성에서 Bean 을 선언 한 다음이를 등록 TomcatConnectorCustomizer합니다.

예를 들면 :

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
            ((TomcatEmbeddedServletContainerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
                @Override
                public void customize(Connector connector) {
                    AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                    httpProtocol.setCompression("on");
                    httpProtocol.setCompressionMinSize(64);
                }
            });
        }
    };
}

사용 가능한 다양한 압축 구성 옵션에 대한 자세한 내용 은 Tomcat 문서 를 참조하십시오.

선택적으로 압축을 사용하고 싶다고 말합니다. 선택 기준에 따라 위의 방법으로 충분할 수 있습니다. 요청의 사용자 에이전트, 응답의 크기 및 응답의 MIME 유형별로 압축을 제어 할 수 있습니다.

이것이 당신의 필요를 충족시키지 못한다면 당신은 당신의 컨트롤러에서 압축을 수행하고 gzip 콘텐츠 인코딩 헤더와 함께 byte [] 응답을 반환해야 할 것이라고 믿습니다.


1
application.properties에 설정을 지정하는 옵션에 대한 답변 사이의 차이점은 무엇입니까? server.compression.enabled = true server.compression.mime-types = application / json, application / xml, text / html, text / xml, text / plain, application / javascript, text / css
lukass77

이 답변은 속성 기반 압축 구성을 사용할 수 있기 전에 작성되었습니다. 그것들은 동등하지만 속성 기반 접근 방식이 더 쉽기 때문에 그것을 사용하는 것이 좋습니다.
Andy Wilkinson

내 경우에는 tomcat이 https를 얻고 tomcat에 대한 요청을 http로받는로드 밸런서 뒤에 있다는 것을 공유하고 싶습니다. application.properties 솔루션 응답을 사용할 때 gzip이 아니지만 커넥터에서 프로그래밍 방식 구성 솔루션을 사용할 때 https 요청 LB를 사용한 gzip 응답
lukass77

내가 application.properties 솔루션 ..을 사용하고 8081 및 8082 포트에 더 많은 2 개의 커넥터를 정의하는 경우에 대한 또 다른 질문 .. 압축이 모든 커넥터에 적용됩니까 아니면 8080 커넥터에만 적용됩니까?
lukass77

나는 이것이 확인, compersion은 더 많은 커넥터를 열더라도 포트 8080에만 적용됩니다 .., 나는 버그가 스프링 부팅에 열려야한다고 생각합니다 ?? .., 그래서 나를위한 작업 솔루션은 각 커넥터에 대한 프로그래밍 방식 구성이었습니다. not application.properties
lukass77

0

.NET Framework를 호출 할 때 Spring Boot + Spring Data 프로젝트에 동일한 문제가 발생했습니다 @RepositoryRestResource.

문제는 반환 된 MIME 유형입니다. 입니다 application/hal+json. server.compression.mime-types속성에 추가하면 이 문제가 해결되었습니다.

이것이 다른 사람에게 도움이되기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.