Подтвердить что ты не робот

Ускорение Spring Время загрузки

У меня есть приложение Spring Boot. Я добавил много зависимостей (к сожалению, все они мне нужны), и время запуска сильно возросло. Простое выполнение SpringApplication.run(source, args) занимает 10 секунд.

Хотя это не так уж много по сравнению с тем, к чему "привыкли", я недоволен тем, что это занимает так много, в основном потому, что это нарушает процесс разработки. Само приложение на данный момент довольно маленькое, поэтому я предполагаю, что большую часть времени оно связано с добавленными зависимостями, а не с самими классами приложения.

Я предполагаю, что проблема заключается в сканировании пути к классам, но я не уверен, как:

  • Подтвердите, что это проблема (например, как "отладить" Spring Boot)
  • Если это действительно причина, как я могу ограничить ее, чтобы она стала быстрее? Например, если я знаю, что какая-то зависимость или пакет не содержит ничего, что должен сканировать Spring, есть ли способ ограничить это?

Я предполагаю, что расширение Spring для параллельной инициализации bean-компонента во время запуска ускорит процесс, но этот запрос на усовершенствование был открыт с 2011 года без какого-либо прогресса. Я вижу некоторые другие усилия в самой Spring Boot, такие как Investigate Tomcat JarScanning, повышение скорости, но это специфично для Tomcat и было заброшено.

Эта статья:

Несмотря на то, что он нацелен на интеграционные тесты, предлагает использовать lazy-init=true, однако я не знаю, как применить это ко всем bean-компонентам в Spring Boot с использованием конфигурации Java - есть ли здесь какие-нибудь указатели?

Любые (другие) предложения будут приветствоваться.

4b9b3361

Ответ 1

Spring Загрузка делает много автоматической конфигурации, которая может не понадобиться. Таким образом, вы можете ограничить только автоматическую настройку, необходимую для вашего приложения. Чтобы просмотреть полный список автоконфигурации, просто запустите регистрацию org.springframework.boot.autoconfigure в режиме DEBUG (logging.level.org.springframework.boot.autoconfigure=DEBUG в application.properties). Другой вариант - запустить приложение загрузки spring с опцией --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 {

Код был скопирован из этого сообщения в блоге.

Ответ 2

Пока что голосование с наибольшим количеством голосов не является неправильным, но оно не идет вглубь, которую мне нравится видеть, и не дает никаких научных доказательств. Команда Spring Boot провела упражнение по сокращению времени запуска Boot 2.0, и билет 11226 содержит много полезной информации. Существует также билет 7939, открытый для добавления информации о времени к оценке состояния, но, похоже, у него нет конкретного ETA.

Наиболее полезный и методичный подход к отладке запуска загрузки был сделан Дэйвом Сайером. https://github.com/dsyer/spring-boot-startup-bench

У меня был похожий вариант использования, поэтому я применил подход Дейва к микропроцессорам с JMH и побежал с ним. Результатом является проект начальной загрузки. Я разработал его так, чтобы его можно было использовать для измерения времени запуска любого приложения Spring Boot, используя исполняемый файл jar, созданный bootJar (ранее он назывался bootRepackage в Boot 1.5), задачу Gradle. Не стесняйтесь использовать его и оставить отзыв.

Мои выводы следующие:

  1. ЦП имеет значение. Много.
  2. Запуск JVM с -Xverify: никто не помогает значительно.
  3. Исключение ненужных автоконфигураций помогает.
  4. Дейв рекомендовал аргумент JVM -XX: TieredStopAtLevel = 1, но мои тесты не показали существенного улучшения с этим. Кроме того, -XX:TieredStopAtLevel=1, вероятно, замедлит ваш первый запрос.
  5. Были сообщения о медленном разрешении имени хоста, но я не нашел, что это является проблемой для приложений, которые я тестировал.

Ответ 3

Как описано в этом вопросе/ответе, я считаю, что лучше всего использовать вместо того, чтобы добавлять только те, которые, по вашему мнению, вам нужны, исключают зависимости, которые, как вам известно, вам не нужны.

Смотрите: Свернуть Spring Начальное время загрузки

Вкратце:

Вы можете увидеть, что происходит под обложками, и включить ведение журнала отладки так же просто, как указать --debug при запуске приложения из командной строки. Вы также можете указать debug = true в своих application.properties.

Кроме того, вы можете установить уровень ведения журнала в application.properties так же просто, как:

logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ОШИБКА

Если вы обнаружите модуль с автоматической настройкой, который вам не нужен, его можно отключить. Документы для этого можно найти здесь: 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 {
}

Ответ 4

В Spring Boot 2.2.M1 добавлена функция поддержки отложенной инициализации в Spring Boot.

По умолчанию при обновлении контекста приложения создается каждый компонент в контексте и внедряются его зависимости. Напротив, когда определение bean-компонента сконфигурировано для ленивой инициализации, оно не будет создано, и его зависимости не будут внедряться до тех пор, пока оно не потребуется.

Включение отложенной инициализации Установите для параметра spring.main.lazy-initialization значение true

Для более подробной информации, пожалуйста, проверьте док

Ответ 5

Если вы пытаетесь оптимизировать процесс разработки для ручного тестирования, я настоятельно рекомендую использовать devtools.

Приложения, использующие spring-boot-devtools, будут автоматически перезапускаться всякий раз, когда изменяются файлы в пути к классам.

Просто перекомпилируйте - и сервер перезагрузится сам (для Groovy вам нужно только обновить исходный файл). Если вы используете IDE (например, "vscode"), он может автоматически скомпилировать ваши java файлы, поэтому простое сохранение java файла может инициировать перезапуск сервера косвенно - и Java в этом отношении становится таким же беспроблемным, как Groovy.

Прелесть этого подхода в том, что при инкрементном перезапуске происходит короткое замыкание на некоторых этапах запуска с нуля, поэтому ваша служба будет работать быстрее и быстрее!


К сожалению, это не помогает со временем запуска для развертывания или автоматического модульного тестирования.

Ответ 6

Существует только один гарантированный способ разработки того, что здесь происходит, а именно для профилирования вашего приложения и поиска горячих точек, которые вызывают проблему.

Я рекомендую использовать YourKit. У этого есть очень хорошая интеграция IDE, таким образом Вы можете профилировать свое приложение из Eclipse или что угодно. См. Здесь

https://www.yourkit.com/docs/java/help/local_profiling.jsp

Вы очень быстро сможете узнать, что вызывает проблему, а затем можете отправить сюда для получения возможных решений.

Ответ 7

Вы можете попробовать мою библиотеку FastClasspathScanner. Я не знаю, можете ли вы использовать Spring для работы с ним, но он сканирует путь к классам намного быстрее, чем Spring.

Ответ 8

Я нахожу странным, что никто не предлагал эти оптимизации раньше. Вот несколько общих советов по оптимизации сборки и запуска проекта при разработке:

  • исключить каталоги разработки из антивирусного сканера:
    • каталог проекта
    • построить выходной каталог (если он находится вне каталога проекта)
    • Каталог индексов IDE (например, ~/.IntelliJIdea2018.3)
    • каталог развертывания (веб-приложения в Tomcat)
  • обновить оборудование. используйте более быструю ЦП и ОЗУ, улучшенное интернет-соединение (для загрузки зависимостей) и соединение с базой данных, переключитесь на SSD. видеокарта не имеет значения.

ПРЕДУПРЕЖДЕНИЯ

  1. первый вариант идет по цене сниженной безопасности.
  2. второй вариант стоит денег (очевидно).

Ответ 9

ПРЕДУПРЕЖДЕНИЕ. Если вы не используете Hibernate DDL для автоматической генерации схемы БД и не используете кэш L2, этот ответ к вам НЕ относится. Прокрутите вперед.

Я обнаружил, что Hibernate значительно увеличивает время запуска приложения. Отключение кэша L2 и инициализация базы данных приводит к более быстрому запуску приложения Spring Boot. Оставьте кеш включенным для производства и отключите его для вашей среды разработки.

application.yml:

spring:
  jpa:
    generate-ddl: false
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        cache:
          use_second_level_cache: false
          use_query_cache: false

Результаты теста:

  1. Кэш L2 включен и ddl-auto: update

    INFO 5024 --- [restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 23331 ms
    INFO 5024 --- [restartedMain] b.n.spring.Application : Started Application in 54.251 seconds (JVM running for 63.766)
    
  2. Кэш L2 выключен и ddl-auto: none

    INFO 10288 --- [restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 9863 ms
    INFO 10288 --- [restartedMain] b.n.spring.Application : Started Application in 32.058 seconds (JVM running for 37.625)
    

Теперь интересно, что я буду делать со всем этим свободным временем?

Ответ 10

Мне кажется, что вы используете неправильный параметр конфигурации. Начните с проверки myContainer и возможных конфликтов. Чтобы определить, кто использует большинство ресурсов, вам необходимо проверить карты памяти (см. Количество данных!) Для каждой зависимости за раз - и это занимает много времени... (и привилегии SUDO). Кстати: вы обычно проверяете код на зависимости?