[java] Spring Boot 시작 시간 단축

Spring Boot 애플리케이션이 있습니다. 나는 많은 의존성을 추가했고 (불행히도 그것들이 모두 필요해 보인다) 시작 시간이 상당히 증가했다. 하는 것만으로도 SpringApplication.run(source, args)10 초가 걸립니다.

그것이 “사용 된”것에 비하면 그다지 많지 않을 수도 있지만, 대부분 개발 흐름을 깨뜨리기 때문에 그렇게 많이 걸리는 것이 불행합니다. 이 시점에서 애플리케이션 자체는 다소 작기 때문에 대부분의 시간이 앱 클래스 자체가 아니라 추가 된 종속성과 관련이 있다고 가정합니다.

문제가 클래스 경로 스캔이라고 가정하지만 다음 방법을 잘 모르겠습니다.

  • 문제인지 확인 (예 : Spring Boot를 “디버그”하는 방법)
  • 그것이 정말로 원인이라면 어떻게 제한 할 수 있습니까? 예를 들어 일부 종속성 또는 패키지에 Spring이 스캔해야하는 내용이 포함되어 있지 않다는 것을 알고 있다면이를 제한하는 방법이 있습니까?

나는 시작하는 동안 병렬 빈 초기화를 갖도록 Spring을 강화 하면 속도가 빨라질 것이라고 가정 하지만 그 향상 요청은 2011 년부터 진행되지 않고 열려 있습니다. Investigate Tomcat JarScanning 속도 향상 과 같은 Spring Boot 자체의 다른 노력이 있지만 Tomcat에 국한되어 포기되었습니다.

이 기사 :

통합 테스트를 겨냥했지만을 사용 lazy-init=true하는 것이 좋지만 Java 구성을 사용하여 Spring Boot의 모든 Bean에 이것을 적용하는 방법을 모르겠습니다-여기에 포인터가 있습니까?

(기타) 제안을 환영합니다.



답변

Spring Boot는 필요하지 않을 수있는 많은 자동 구성을 수행합니다. 따라서 앱에 필요한 자동 구성 만 좁힐 수 있습니다. 포함 된 자동 구성의 전체 목록을 보려면 org.springframework.boot.autoconfigureDEBUG 모드 ( logging.level.org.springframework.boot.autoconfigure=DEBUGin application.properties) 에서 로깅을 실행하십시오 . 또 다른 옵션은 옵션을 사용하여 스프링 부트 애플리케이션을 실행하는 --debug것입니다.java -jar myproject-0.0.1-SNAPSHOT.jar --debug

출력에는 다음과 같은 내용이 있습니다.

=========================
AUTO-CONFIGURATION REPORT
=========================

이 목록을 검사하고 필요한 자동 구성 만 포함하십시오.

@Configuration
@Import({
        DispatcherServletAutoConfiguration.class,
        EmbeddedServletContainerAutoConfiguration.class,
        ErrorMvcAutoConfiguration.class,
        HttpEncodingAutoConfiguration.class,
        HttpMessageConvertersAutoConfiguration.class,
        JacksonAutoConfiguration.class,
        ServerPropertiesAutoConfiguration.class,
        PropertyPlaceholderAutoConfiguration.class,
        ThymeleafAutoConfiguration.class,
        WebMvcAutoConfiguration.class,
        WebSocketAutoConfiguration.class,
})
public class SampleWebUiApplication {

이 블로그 게시물 에서 코드를 복사 했습니다 .


답변

지금까지 가장 많이 득표 한 답변은 틀린 것은 아니지만 내가보고 싶은 깊이에 이르지 않으며 과학적 증거를 제공하지 않습니다. Spring Boot 팀은 Boot 2.0의 시작 시간을 줄이기위한 연습을 진행했으며 티켓 11226 에는 많은 유용한 정보가 포함되어 있습니다. 조건 평가에 타이밍 정보를 추가 할 수 있는 티켓 7939 도 있지만 특정 ETA가없는 것 같습니다.

부팅 시작 디버깅을위한 가장 유용하고 체계적인 접근 방식은 Dave Syer에 의해 수행되었습니다. https://github.com/dsyer/spring-boot-startup-bench

저도 비슷한 사용 사례를 가지고 있었기 때문에 JMH로 마이크로 벤치마킹에 대한 Dave의 접근 방식을 취해 실행했습니다. 결과는 boot-benchmark 프로젝트입니다. 나는 의해 생성 된 실행 항아리 사용하여 임의의 봄 부팅 응용 프로그램의 시작 시간을 측정 할 수는 있도록 설계 bootJar(이전이라고 bootRepackage부팅 1.5) Gradle을 작업. 자유롭게 사용하고 피드백을 제공하십시오.

내 결과는 다음과 같습니다.

  1. CPU가 중요합니다. 많이.
  2. -Xverify : none으로 JVM을 시작 하면 큰 도움이됩니다.
  3. 불필요한 자동 구성을 제외하면 도움이됩니다.
  4. Dave는 JVM 인수 -XX : TieredStopAtLevel = 1을 권장 했지만 내 테스트는 그와 관련하여 크게 개선되지 않았습니다. 또한 -XX:TieredStopAtLevel=1첫 번째 요청이 느려질 것입니다.
  5. 가 있었다 보고서 호스트 이름 확인이 느린되는,하지만 난 그것이 내가 테스트 응용 프로그램에 대한 문제 찾지 못했습니다.

답변

Spring Boot 2.2.M1 은 Spring Boot에서 Lazy Initialization을 지원하는 기능을 추가했습니다.

기본적으로 애플리케이션 컨텍스트가 새로 고쳐질 때 컨텍스트의 모든 Bean이 작성되고 해당 종속성이 삽입됩니다. 대조적으로 빈 정의가 느리게 초기화되도록 구성되면 생성되지 않으며 필요할 때까지 종속성이 주입되지 않습니다.

지연 초기화 활성화spring.main.lazy-initializationtrue로 설정

지연 초기화를 활성화해야하는 경우
지연 초기화는 시작 시간을 크게 향상시킬 수 있지만 몇 가지 눈에 띄는 단점도 있으며주의해서 활성화하는 것이 중요합니다.

자세한 내용은 Doc을 확인하십시오.


답변

이 질문 / 답변에서 설명했듯이 가장 좋은 방법은 필요하다고 생각하는 것만 추가하는 대신 필요하지 않다는 것을 알고있는 종속성을 제외하는 것입니다.

참조 : Spring Boot 시작 시간 최소화

요약해서 말하자면:

명령 줄에서 애플리케이션을 시작할 때 –debug를 지정하는 것처럼 간단하게 진행중인 작업을 확인하고 디버그 로깅을 활성화 할 수 있습니다. application.properties에서 debug = true를 지정할 수도 있습니다.

또한 application.properties의 로깅 수준을 다음과 같이 간단하게 설정할 수 있습니다.

logging.level.org.springframework.web : DEBUG logging.level.org.hibernate : ERROR

원하지 않는 자동 구성 모듈을 감지하면 비활성화 할 수 있습니다. 이에 대한 문서는 http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration 에서 찾을 수 있습니다.

예는 다음과 같습니다.

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}


답변

여기에 설명 된 가능한 작업의 전체 목록이 있습니다. https://spring.io/blog/2018/12/12/how-fast-is-spring

Spring 측에서 가장 중요한 메모를 넣을 것입니다 (조금 조정 됨).

  • Spring Boot 웹 스타터의 클래스 경로 제외 :
    • Hibernate Validator
    • Jackson (그러나 Spring Boot 액추에이터는 그것에 의존합니다). JSON 렌더링이 필요한 경우 Gson을 사용하십시오 (기본적으로 MVC에서만 작동).
    • Logback : 대신 slf4j-jdk14 사용
  • spring-context-indexer를 사용하십시오. 많은 것을 추가하지는 않지만 모든 작은 것이 도움이됩니다.
  • 여유가 없다면 액추에이터를 사용하지 마십시오.
  • Spring Boot 2.1 및 Spring 5.1을 사용하십시오. 가능한 경우 2.2 및 5.2로 전환하십시오.
  • spring.config.location(명령 줄 인수 또는 시스템 속성 등) 을 사용하여 Spring Boot 구성 파일의 위치를 ​​수정합니다 . IDE에서 테스트하기위한 예 : spring.config.location=file://./src/main/resources/application.properties.
  • 필요하지 않은 경우 JMX를 끕니다 spring.jmx.enabled=false(Spring Boot 2.2의 기본값).
  • 기본적으로 빈 정의를 지연시킵니다. spring.main.lazy-initialization=trueSpring Boot 2.2에 새로운 플래그가 있습니다 ( LazyInitBeanFactoryPostProcessor이전 Spring에 사용).
  • fat jar의 압축을 풀고 명시적인 클래스 경로로 실행하십시오.
  • .NET을 사용하여 JVM을 실행합니다 -noverify. 또한 고려하십시오 -XX:TieredStopAtLevel=1(그러면 나중에 시작 시간이 절약되는 대신 JIT 속도가 느려짐).

언급 한 것 LazyInitBeanFactoryPostProcessor( spring.main.lazy-initialization=trueSpring 2.2에서 사용 가능한 플래그를 적용 할 수없는 경우 Spring 1.5 에서 사용할 수 있음) :

public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
      for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
        definition.setLazyInit(true);
      }
  }
}

또한 빈 초기화 시간을 분석하기 위해 무언가를 사용하거나 직접 작성할 수 있습니다. https://github.com/lwaddicor/spring-startup-analysis

도움이 되었기를 바랍니다.


답변

제 경우에는 너무 많은 중단 점이있었습니다. “Mute Breakpoints”를 클릭하고 디버그 모드에서 응용 프로그램을 다시 시작하면 응용 프로그램이 10 배 빠르게 시작되었습니다.


답변

수동 테스트를 위해 개발 턴어라운드를 최적화하려는 경우 다음을 사용하는 것이 좋습니다. devtools .

spring-boot-devtools를 사용하는 애플리케이션은 클래스 경로의 파일이 변경 될 때마다 자동으로 다시 시작됩니다.

다시 컴파일하면 서버가 자동으로 다시 시작됩니다 (Groovy의 경우 소스 파일 만 업데이트하면 됨). IDE (예 : ‘vscode’)를 사용하는 경우 Java 파일을 자동으로 컴파일 할 수 있으므로 Java 파일을 저장하는 것만으로도 간접적으로 서버를 다시 시작할 수 있으며 Java는 이와 관련하여 Groovy만큼 매끄럽게됩니다.

이 접근 방식의 장점은 증분 재시작이 처음부터 시작하는 일부 시작 단계를 단락시켜 서비스가 훨씬 더 빠르게 백업되고 실행된다는 것입니다.


불행히도 이것은 배포 또는 자동화 된 단위 테스트를위한 시작 시간에 도움이되지 않습니다.