느린 첫 번째 호출을 피하기 위해 Java 클래스를 예열하는 방법은 무엇입니까?


13

모든 API 호출이 1 초 미만이어야하는 프로젝트를 수행하고 있지만 다음 경로보다 느린 각 경로에 대한 첫 번째 호출에 문제가 있습니다.

현재 / login에 대한 첫 번째 호출은 3.6 초가 걸리고 다음 호출은 다른 모든 경로에 대해 170ms가 걸립니다.

-XX:+TraceClassLoading첫 번째 호출에서이를 사용하여 클래스가 메모리에로드되어 성능 문제가 발생한다는 것을 알았습니다 .

그러나 시작할 때 모든 클래스를 쉽게로드 할 수있는 방법을 찾지 못했고 새로운 서비스마다 ApplicationRunner에서 워밍업 호출을 추가해야합니다.

누구나 SpringBoot 응용 프로그램의 클래스를 자동으로로드하거나 모든 경로를 예열하는 솔루션이 있습니까?


더 자세한 내용을 추가 할 수 있습니까? 애플리케이션이 컨트롤러를 인스턴스화하고 있습니까? 아니면 다른 서비스를 부르고 있습니까? 다른 서비스를 어떻게 부르십니까?
Menios

Spring Boot는 클래스 스캔을 집중적으로 사용하므로 데스크탑 응용 프로그램과 같은 것을 '따뜻하게'할 필요가 없습니다. 이 긴 초기로드는 페이지 템플리트로드와 같은 자원 검색의 결과 일 수 있습니다.
Alex Chernyshev

약간의 간접 접근 방식 : 엔드 포인트에 대한 100 % 단위 테스트 적용 범위가있는 경우이를 사용할 수 있습니다. 엔드 포인트 당 코드를 작성해야하지만 무언가를 얻을 수 있습니다.
Marged

1
수행중인 프로젝트에 따라 이상적이지는 않지만 응용 프로그램이로드 될 때 내부적으로 엔드 포인트를 호출 할 수 있습니다.
omoshiroiii

@omoshiroiii 그것에 아무런 문제가 없습니다 . 우리는 그것을한다. 생산에서. 그 이유는 사용하는 일부 동적 라이브러리 invokedynamic와 관련이 있으며 우리 는 첫 번째 호출에서 해상도가 느리다는 것을 알고 있습니다 (우리는 첫 번째 호출이 없으면 수십 초까지 누적되는 그러한 호출은 수만 건입니다).
유진

답변:


1

자바의 클래스 로딩은 게으르다. 이것은 클래스가 필요할 때 그리고 필요할 때만 JVM에 의해로드된다는 것을 의미합니다.

클래스를 열심히로드하도록 강요하려면 클래스를 참조하면됩니다. 이를 수행하는 한 가지 방법은 jar 컨텐츠 또는 클래스 파일을 반복하여 클래스 이름을 얻은 다음이를 사용하여 호출하는 것 Class.forName(className)입니다.

또한 시작 시간과 성능이 사용 사례에 매우 중요한 경우 GraalVM 과 같은 사전 컴파일 솔루션을 살펴 보거나 JIT의 컴파일 임계 값을 줄이려고 할 수 있습니다 ( -XX:CompileThreshold).


이들 중 어느 것도 OP의 문제를 해결할 수 없습니다. 로딩은 여전히 ​​GraalVM에서 게으 르며 첫 번째 호출에서는 JIT의미가 없습니다 .
유진

또한 GraalVM좋지만 github에있는 문제의 수를 살펴보십시오. 샌드 박스 프로젝트에서 더 큰 것으로 이동하자마자 (주로 반사를보고 있습니다) 약간의 고통을 겪을 것입니다. 적어도. 내 요점은 : GraalVM으로 바꾸는 것은 간단한 손가락 스냅이 아닙니다.
유진

항아리에 클래스를로드하는 것에 대해 생각했지만 그것을 수행하는 방법을 찾지 못했습니다. 예가 있습니까?
Ybri

@Eugene 내 대답을 읽으면 GraalVM 또는 JIT 임계 값이 클래스 로딩의 게으름을 바꿀 것이라고 말하지 않았 음을 알 수 있습니다. 게으름에 대한 OP의 질문에 대한 답변은 그 이전의 단락입니다. 마지막 단락은 OP가 클래스 로딩을 넘어서 시작 시간 / 성능을 더욱 최적화해야하는 경우에 대한 추가 팁입니다.
andresp

1
그 답변에 다른 질문은 여기에 예를 들어,이 @Ybri 있습니다 stackoverflow.com/questions/2370867/...
andresp

0

나에게 유일하게 가능한 옵션은 JEP 310 , JEP 341JEP 350에class data sharing 퍼져 있지만 java-13이 가장 필요할 것입니다. 우리는 이것을 내 작업장 (대부분은 거짓말을하지 않고 재미를 위해)에서 내부적으로 테스트하고 있으며 결과는 지금까지는 좋아 보입니다.

다른 옵션은 애플리케이션이 시작될 때 엔드 포인트를 호출하는 것입니다 (옵션 인 경우). 다시, 이다 예를 들어 우리를 위해 우리가 코드를 따뜻하게 더미 데이터로의 수백 배의 몇 가지를 호출합니다. 그러나 동시에 우리는 이것이 불가능한 서비스를 제공하고 CDS있습니다.


프로덕션 데이터베이스에서 데이터가 생성되지 않도록 인증 및 사후 엔드 포인트를 어떻게 처리합니까?
Ybri

@Ybri 정확히 내가 왜 말했는지, 일부에게는 불가능 합니다.
유진
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.