В настоящее время мы перемещаем наше приложение в Spring Boot и сталкиваемся с проблемами производительности во время выполнения при запуске в качестве исполняемого файла WAR
Я создал пример проекта, чтобы легко воспроизвести его
git clone https://github.com/kicktipp/spring-jar-performance
cd spring-jar-performance
./mvnw clean package
java -jar target/spring-jar-performance.war
Теперь приложение работает.
while true; do ab -n 100 http://localhost:8080/ | grep longest; sleep 4; done
Результат выглядит странно:
100% 307 (longest request)
100% 2 (longest request)
100% 305 (longest request)
100% 1 (longest request)
100% 331 (longest request)
100% 2 (longest request)
Производительность довольно хорошая, но каждые несколько секунд один запрос отнимает возраст по сравнению с обычным поведением.Мы профилировали приложение и получили следующий результат:
Таким образом, причина в этой строке в XmlController: (ссылка на Github)
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Я не хочу винить в этом xerces XML Lib.Что происходит, так это то, что Xerces ищет путь к классу, и поэтому WebappClassLoaderBase ищет его в заархивированном файле WAR, который необходимо сначала распаковать.
Эта операция кэшируется, но каждые несколько секунд она повторяется.
Существует несколько сценариев, позволяющих избежать этой проблемы с производительностью.
Мы не можем использовать исполняемый JAR, так как мы все еще используем некоторые JSP-файлы.Мы можем использовать XOM, но это не помогает в другой области:
У нас та же проблема с производительностью, когда проводится оценка JSP EL.При вычислении выражения типа ${myViewObject.name}
происходит такая же загрузка классов.Это лучше как-то кешируется.Мы наблюдаем это только при первом вызове JSP.
Мы уже пытались добавить прекомпиляцию JSP в настройку, но это не помогает (это позволяет избежать времени компиляции, но не упомянутой здесь проблемы)
Поскольку наша WAR в производстве намного больше, чем эта тестовая WAR, для извлечения ZIP-файла и поиска класса в производстве требуется более 2 секунд.Это, конечно, не приемлемо для пользователя.
Это известная проблема для упаковки WAR с пружинной загрузкой?И если да, как мы можем это исправить / избежать?