2015-10-26 2 views
1

У меня есть сервак java boot boot, который работает под Jetty, но имеет проблемы с производительностью при работе под Tomcat, который является нашей целевой средой развертывания.Сценарий весенней загрузки показывает проблемы с производительностью в Tomcat, но не Jetty

  1. JAMAHA unmarshal является узким местом, потому что ServiceLoader тратит много времени на поиск реализации TransformerFactory. (YourKit profiling showing the look up for the TransformerFactory implementation)
  2. Saxon является реализацией преобразования и баночка входят в коте/WebApps/MyApp/WEB-INF/Lib и имеет собственный META-INF/файл службы
  3. Этот вопрос не присутствуют при использовании Jetty в качестве сервлет контейнер
  4. Я подтверждал под управлением как Jetty и Tomcat я получить правильное выполнение для TransformerFactory от правильной баночки
  5. Явного добавив отображение в опцию Tomcat JAVA_OPTS решает проблему:

    -Djavax .xml.transform.TransformerFactory = net.sf.saxon.Transfo rmerFactoryImpl

Отредактировано: выборки/преобразования Наш XML время в Jetty составляет около 5 секунд против 20-х годов под Tomcat, и это напрямую связано с загрузчиком класса поисках нашего TransformerFactory.

Я могу исправить проблему, явно указав TransformerFactory в нашей конфигурации сервлета, но мой вопрос остается: Почему Tomcat требует этого явного setProperty и контейнера Jetty?

public class Application extends SpringBootServletInitializer { 
    @Override 
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
    System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl"); 

    return application.sources(Application.class); 
} 

Извините, если это рудиментарный вопрос, я старый C++ собака обучения Java и веб-приложений/сервлетов фокусы.

+0

Один вопрос до 4: с «при запуске исполняемого файла .jar или .war» вы подразумеваете, что эти файлы используют встроенный причал вместо встроенного tomcat? –

+0

Когда я это сделал, они использовали встроенный Tomcat. Причал всегда был внешним во всех моих тестах. – dleb

+0

Я также прочитал документы о загрузчике классов для Jetty и Tomcat. Из этого я не ожидал бы никакой разницы, потому что оба контейнера должны подчиняться правилам загрузчика классов для установки контейнеров сервлетов в стандарте. – dleb

ответ

0

Если системное свойство JAXP, идентифицирующее завод, не установлено, JAXP ищет путь к классу JAR-файла с информацией об трансформаторных фабриках в файле служб манифеста JAR-файла. Этот поиск может быть довольно дорогостоящим в случае, когда в пути к классам много JAR, и его, безусловно, лучше избегать. Наиболее вероятное объяснение различий производительности, которое вы видите, заключается в том, что ваша конфигурация Tomcat имеет гораздо больше файлов JAR для поиска, чем конфигурация Jetty.

До сих пор самый быстрый способ создания экземпляра Saxon, чтобы делать это непосредственно, и избегать механизмов JAXP полностью:

TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl() 

Это также является более надежным; если ваше приложение протестировано с Saxon, и вы не доверяете ему работать с каким-либо старым процессором XSLT 1.0, который лежит на пути к классам, тогда вы можете использовать жесткий код Saxon в исходном коде приложения. Единственное преимущество механизма JAXP, если вы хотите, чтобы ваше приложение могло работать с различными реализациями XSLT JAXP, с выбором, сделанным во время выполнения.

+0

Спасибо, Майкл. Я считаю, что поддерживает мое решение жесткого кодирования System.setProperty, чтобы определить, какую реализацию мы используем. Предоставляет ли предоставленный вами фрагмент кода фактически установленный TransformerFactory для всего приложения? Я спрашиваю, потому что мы не можем напрямую контролировать, когда/где создается TransformerFactory. В основном я хочу знать, должен ли я заменить свой системный вызов на свой фрагмент кода в моем методе настройки – dleb

+0

Нет, код, заменяющий все, что делает 'TransformerFactory factory = TransformerFactory.newInstance()', и предполагает, что у вас есть доступ к местам в приложение, в котором это делается. Если вы не можете изменить код таким образом, использование системного свойства является вашей лучшей альтернативой, но недостатком является то, что оно применяется ко всему приложению и может изменить механизм XSLT, используемый частями приложения, которые были протестированы только с помощью по умолчанию JDK-движок и перерыв при использовании другого. –