Mam aplikację Spring Boot. Dodałem sporo zależności (niestety, wygląda na to, że potrzebuję ich wszystkich) i czas uruchamiania znacznie się wydłużył. Samo wykonanie SpringApplication.run(source, args)
zajmuje 10 sekund.
Chociaż może to nie być dużo w porównaniu do tego, do czego są „przyzwyczajeni”, jestem niezadowolony, że zajmuje to tyle czasu, głównie dlatego, że przerywa to proces programowania. Sama aplikacja jest w tym momencie raczej mała, więc zakładam, że większość czasu jest związana z dodanymi zależnościami, a nie z samymi klasami aplikacji.
Zakładam, że problemem jest skanowanie ścieżek klas, ale nie wiem, jak:
- Potwierdź, że na tym polega problem (tj. Jak „debugować” Spring Boot)
- Jeśli to naprawdę jest przyczyna, jak mogę to ograniczyć, żeby przyspieszyło? Na przykład, jeśli wiem, że pewna zależność lub pakiet nie zawiera niczego, co powinien skanować Spring, czy istnieje sposób, aby to ograniczyć?
Zakładam, że rozszerzenie Springa, aby miał równoległą inicjalizację fasoli podczas uruchamiania , przyspieszyłoby rzeczy, ale to żądanie ulepszenia jest otwarte od 2011 roku i nie ma żadnego postępu. Widzę inne wysiłki w samym Spring Boot, takie jak ulepszenia prędkości Investigate Tomcat JarScanning , ale jest to specyficzne dla Tomcat i zostało porzucone.
Ten artykuł:
chociaż ma na celu testy integracyjne, sugeruje użycie lazy-init=true
, jednak nie wiem, jak zastosować to do wszystkich fasoli w Spring Boot przy użyciu konfiguracji Java - jakieś wskazówki tutaj?
Wszelkie (inne) sugestie będą mile widziane.
źródło
@ComponentScan
również są skanowane. Inną rzeczą jest upewnienie się, że nie włączyłeś rejestrowania debugowania lub śledzenia, ponieważ ogólnie rejestrowanie jest powolne, bardzo wolne.Odpowiedzi:
Spring Boot wykonuje wiele automatycznych konfiguracji, które mogą nie być potrzebne. Możesz więc zawęzić tylko automatyczną konfigurację potrzebną dla Twojej aplikacji. Aby zobaczyć pełną listę automatycznej konfiguracji, po prostu uruchom logowanie
org.springframework.boot.autoconfigure
w trybie DEBUG (logging.level.org.springframework.boot.autoconfigure=DEBUG
inapplication.properties
). Inną opcją jest uruchomienie aplikacji Spring Boot z--debug
opcją:java -jar myproject-0.0.1-SNAPSHOT.jar --debug
Na wyjściu byłoby coś takiego:
Przejrzyj tę listę i uwzględnij tylko potrzebne autokonfiguracje:
Kod został skopiowany z tego posta na blogu .
źródło
Jak dotąd, najczęściej głosowana odpowiedź nie jest błędna, ale nie jest ona głęboka, którą lubię widzieć i nie dostarcza żadnych dowodów naukowych. Zespół Spring Boot przeszedł ćwiczenie mające na celu skrócenie czasu uruchamiania Boot 2.0, a bilet 11226 zawiera wiele przydatnych informacji. Istnieje również zgłoszenie 7939 umożliwiające dodawanie informacji o czasie do oceny stanu, ale wydaje się, że nie ma on określonego czasu ETA.
Najbardziej przydatne i metodyczne podejście do debugowania uruchamiania podczas rozruchu zostało wykonane przez Dave'a Syera. https://github.com/dsyer/spring-boot-startup-bench
Miałem również podobny przypadek użycia, więc przyjąłem podejście Dave'a do mikro-benchmarkingu z JMH i zacząłem z nim. Rezultatem jest projekt testu porównawczego rozruchu . Zaprojektowałem go w taki sposób, aby można go było wykorzystać do pomiaru czasu uruchamiania dowolnej aplikacji Spring Boot, używając wykonywalnego pliku jar utworzonego przez
bootJar
(wcześniej zwanebootRepackage
w Boot 1.5) zadanie Gradle. Zapraszam do korzystania z niego i przekazywania opinii.Moje ustalenia są następujące:
-XX:TieredStopAtLevel=1
prawdopodobnie spowolniłoby twoją pierwszą prośbę.źródło
minimal
, czy może po prostu słoik być dostarczony? Próbowałem zrobić to pierwsze, ale nie zaszedłem zbyt daleko.-Xverify:none
na produkcji, ponieważ przerywa to weryfikację kodu i możesz wpaść w kłopoty.-XX:TieredStopAtLevel=1
jest OK, jeśli uruchomisz aplikację na krótki czas (kilka sekund), w przeciwnym razie będzie mniej produktywna, ponieważ zapewni JVM długotrwałe optymalizacje.Use of -Xverify:none is unsupported.
co to oznacza?Spring Boot 2.2.M1 ma dodaną funkcję do obsługi Lazy Initialization w Spring Boot.
Domyślnie podczas odświeżania kontekstu aplikacji jest tworzony każdy komponent bean w kontekście, a jego zależności są wstrzykiwane. Z drugiej strony, jeśli definicja fasoli jest skonfigurowana do leniwego inicjowania, nie zostanie utworzona, a jej zależności nie zostaną wstrzyknięte, dopóki nie będą potrzebne.
Włączanie Lazy Initialization Ustawiono
spring.main.lazy-initialization
na trueKiedy włączyć leniwą inicjalizację
leniwa inicjalizacja może zapewnić znaczną poprawę czasu uruchamiania, ale są też pewne istotne wady i ważne jest, aby włączyć ją ostrożnie
Więcej informacji można znaleźć w Doc
źródło
Jak opisano w tym pytaniu / odpowiedzi, myślę, że najlepszym podejściem jest dodanie tylko tych, których Twoim zdaniem potrzebujesz, wykluczenie zależności, o których wiesz, że nie potrzebujesz.
Zobacz: Minimalizuj czas uruchamiania rozruchu sprężynowego
W podsumowaniu:
Możesz zobaczyć, co się dzieje pod okładkami i włączyć rejestrowanie debugowania tak proste, jak określenie --debug podczas uruchamiania aplikacji z wiersza poleceń. Możesz również określić debug = true w pliku application.properties.
Możesz również ustawić poziom rejestrowania w application.properties tak prosto, jak:
logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERROR
Jeśli wykryjesz automatycznie skonfigurowany moduł, którego nie chcesz, możesz go wyłączyć. Dokumentację na ten temat można znaleźć tutaj: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disiring-specific-auto-configuration
Przykład wyglądałby tak:
źródło
Cóż, jest cała lista możliwych działań opisanych tutaj: https://spring.io/blog/2018/12/12/how-fast-is-spring
Najważniejsze notatki umieszczę od strony wiosny (trochę poprawione):
spring.config.location
(argument wiersza poleceń lub właściwość System itp.). Przykład badania ide:spring.config.location=file://./src/main/resources/application.properties
.spring.jmx.enabled=false
(jest to domyślne ustawienie w Spring Boot 2.2)spring.main.lazy-initialization=true
Spring Boot 2.2 pojawiła się nowa flaga (użyjLazyInitBeanFactoryPostProcessor
dla starszej wersji Spring).-noverify
. Rozważ również-XX:TieredStopAtLevel=1
(to spowolni później JIT kosztem zaoszczędzonego czasu uruchamiania).Wspomniane
LazyInitBeanFactoryPostProcessor
(możesz go użyć na wiosnę 1.5, jeśli nie możesz zastosować flagispring.main.lazy-initialization=true
dostępnej od wiosny 2.2):Możesz także użyć (lub napisać własne - to proste) czegoś do analizy czasu inicjalizacji ziaren: https://github.com/lwaddicor/spring-startup-analysis
Mam nadzieję, że to pomoże!
źródło
W moim przypadku było zbyt wiele punktów przerwania. Kiedy kliknąłem „Mute Breakpoints” i ponownie uruchomiłem aplikację w trybie debugowania, aplikacja uruchomiła się 10 razy szybciej.
źródło
Jeśli próbujesz zoptymalizować cykl rozwoju pod kątem testowania ręcznego, zdecydowanie polecam użycie narzędzi devtools .
Po prostu przekompiluj - a serwer uruchomi się ponownie (w przypadku Groovy wystarczy zaktualizować plik źródłowy). jeśli używasz IDE (np. „vscode”), może ono automatycznie skompilować twoje pliki java, więc samo zapisanie pliku java może zainicjować restart serwera, pośrednio - a Java staje się tak samo płynna jak Groovy pod tym względem.
Piękno tego podejścia polega na tym, że przyrostowe ponowne uruchamianie powoduje zwarcie niektórych etapów uruchamiania od zera - dzięki czemu usługa będzie mogła zostać utworzona i uruchomiona znacznie szybciej!
Niestety nie pomaga to w czasie uruchamiania w przypadku wdrażania lub zautomatyzowanych testów jednostkowych.
źródło
OSTRZEŻENIE: Jeśli nie używasz Hibernate DDL do automatycznego generowania schematu bazy danych i nie używasz pamięci podręcznej L2, ta odpowiedź NIE dotyczy Ciebie. Przewiń do przodu.
Moje odkrycie jest takie, że Hibernate znacznie wydłuża czas uruchamiania aplikacji. Wyłączenie pamięci podręcznej L2 i inicjalizacji bazy danych powoduje szybsze uruchamianie aplikacji Spring Boot. Pozostaw pamięć podręczną WŁĄCZONĄ dla produkcji i wyłącz ją dla swojego środowiska programistycznego.
application.yml:
Wyniki testu:
Pamięć podręczna L2 jest WŁĄCZONA i
ddl-auto: update
Pamięć podręczna L2 jest WYŁĄCZONA i
ddl-auto: none
Teraz zastanawiam się, co będę robić z całym tym wolnym czasem
źródło
Wydaje mi się dziwne, że nikt wcześniej nie sugerował tych optymalizacji. Oto kilka ogólnych wskazówek dotyczących optymalizacji kompilacji i uruchamiania projektu podczas tworzenia:
OSTRZEŻENIA
źródło
Wydaje mi się, że używasz złego ustawienia konfiguracji. Zacznij od sprawdzenia myContainer i możliwych konfliktów. Aby określić, kto używa najwięcej zasobów, musisz sprawdzić mapy pamięci (zobacz ilość danych!) Dla każdej zależności naraz - i to również zajmuje dużo czasu ... (i uprawnienia SUDO). Przy okazji: czy zazwyczaj testujesz kod pod kątem zależności?
źródło