Ваше приложение J2EE работает медленно? Смогут ли они противостоять растущему трафику? В этой статье описывается технология оптимизации производительности для разработки высокопроизводительных, высокоэластичных страниц JSP и сервлетов. Идея состоит в том, чтобы строить как можно быстрее и адаптироваться к растущему числу пользователей и их запросам. В этой статье я познакомлю вас с практическими и проверенными методами настройки производительности, которые значительно улучшат производительность ваших сервлетов и страниц JSP, тем самым улучшая производительность J2EE. Некоторые из этих технологий используются на этапах разработки, например, на этапах проектирования и кодирования. Другая часть технологии связана с настройкой.
Техника 1. Кэширование данных в методе HttpServletinit()
Сервер вызывает метод init() сервлета после создания экземпляра сервлета и до того, как сервлет обработает какие-либо запросы. Этот метод вызывается только один раз за жизненный цикл сервлета. Чтобы повысить производительность, кэшируйте статические данные в init() или выполняйте дорогостоящие операции, которые необходимо выполнить во время инициализации. Например, рекомендуется использовать пул соединений JDBC, реализующий интерфейс javax.sql.DataSource.
DataSource получается из дерева JNDI. Использование JNDI для поиска источника данных при каждом вызове SQL обходится очень дорого, и это серьезно влияет на производительность приложения. Метод init() сервлета можно использовать для получения источника данных и его кэширования для последующего повторного использования:
publicclassControllerServletextendsHttpServlet
{
Privatejavax.sql.DataSourcetestDS = null;
publicvoidinit(ServletConfigconfig)throwsServletException;
{
super.init(конфигурация);
Контекстктх = ноль;
пытаться
{
ctx=newInitialContext();
testDS=(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
поймать (исключение именования)
{
ne.printStackTrace();
}
улов (исключение)
{
е.printStackTrace();
}
}
publicjavax.sql.DataSourcegetTestDS()
{
возвраттестдс;
}
...
...
}
Метод 2: Отключите функцию автоматической загрузки сервлетов и JSP
. Вам придется перезапускать сервер каждый раз, когда вы изменяете сервлет/JSP. Поскольку функция автозагрузки сокращает время разработки, эта функция считается очень полезной на этапе разработки. Однако на этапе выполнения это очень дорого; сервлет/JSP приводит к снижению производительности из-за ненужной загрузки и увеличения нагрузки на загрузчик классов. Опять же, это может привести к странным конфликтам в вашем приложении, поскольку классы, загруженные определенным загрузчиком классов, не могут взаимодействовать с классами, загруженными текущим загрузчиком классов. Поэтому, чтобы добиться более высокой производительности в работающей среде, отключите функцию автоматической загрузки сервлета/JSP.
Техника 3: Управление HttpSession
Многим приложениям требуется серия клиентских запросов, чтобы они могли быть связаны друг с другом. Поскольку протокол HTTP не сохраняет состояние, веб-приложения должны нести ответственность за поддержание такого состояния, называемого сеансом. Для поддержки приложений, которые должны поддерживать состояние, технология Javaservlet предоставляет API, которые управляют сеансами и позволяют использовать несколько механизмов для реализации сеансов. Объект HttpSession действует как сеанс, но за его использование приходится платить. Всякий раз, когда HttpSession используется и переопределяется, он читается сервлетом. Вы можете улучшить производительность, используя следующие методы:
lНе создавайте HttpSession по умолчанию на странице JSP: по умолчанию страница JSP создает HttpSession. Если вы не используете HttpSession на своей странице JSP, чтобы снизить нагрузку на производительность, используйте следующие инструкции на странице, чтобы избежать автоматического создания объектов HttpSession:
< %@pagesession="false"% >
1) Не храните большие графы объектов в HttpSession: если вы храните данные в HttpSession как большой граф объектов, серверу приложений придется каждый раз обрабатывать весь объект HttpSession. Это приведет к принудительной сериализации Java и увеличению вычислительных затрат. Из-за накладных расходов на сериализацию пропускная способность системы будет снижаться по мере увеличения объектов данных, хранящихся в объекте HttpSession.
2) Освободите HttpSession после использования. Когда HttpSession больше не используется, используйте метод HttpSession.invalidate(), чтобы сделать сеанс недействительным.
3) Установите значение тайм-аута: механизм сервлетов имеет значение тайм-аута по умолчанию. Если вы не удалите сеанс или продолжите использовать его до истечения времени ожидания, механизм сервлетов удалит сеанс из памяти. Из-за накладных расходов на память и сборку мусора, чем больше значение тайм-аута сеанса, тем сильнее оно влияет на отказоустойчивость и производительность системы. Постарайтесь установить как можно меньшее значение таймаута сеанса.
Техника 4. Используйте сжатие gzip.
Сжатие — это метод удаления избыточной информации и ее описания в минимально возможном объеме. Использование gzip (GNUzip) для сжатия документов может эффективно сократить время загрузки HTML-файлов. Чем меньше ваши сообщения, тем быстрее они отправляются. Следовательно, если вы сжимаете контент, создаваемый вашим веб-приложением, тем быстрее он достигает пользователя и отображается на экране пользователя. Не каждый браузер поддерживает сжатие gzip, но легко проверить, поддерживает ли браузер его, и отправить в браузер содержимое, сжатое с помощью gzip. Фрагмент кода ниже показывает, как отправлять сжатый контент.
publicvoiddoGet (HttpServletRequestrequest, HttpServletResponseresponse)
бросаетIOException, ServletException
{
OutputStreamout = null
// Проверьте заголовок Accepting-Encodingheader from theHTTPrequest.
//Если заголовок содержит gzip, выберите GZIP.
//Если заголовок содержит сжатие, выберите ZIP.
//В противном случае выберите
nocompression.Stringencoding=request.getHeader("Accept-Encoding");
if(encoding!=null&&encoding.indexOf("gzip")!=-1)
{
response.setHeader("Кодирование контента","gzip");
out = newGZIPOutputStream(response.getOutputStream());
}
elseif(encoding!=null&&encoding.indexOf("сжать")!=-1)
{
response.setHeader("Кодирование контента","сжать");
out = newZIPOutputStream(response.getOutputStream());
}
еще
{
out=response.getOutputStream()
;
...
...
}
Техника 5: Не используйте SingleThreadModel.
SingleThreadModel гарантирует, что сервлет обрабатывает только один запрос за раз. Если сервлет реализует этот интерфейс, механизм сервлета будет создавать отдельный экземпляр сервлета для каждого нового запроса, что приведет к большим нагрузкам на систему. Если вам нужно решить проблемы с потокобезопасностью, используйте другие методы вместо этого интерфейса. Использование SingleThreadModel больше не рекомендуется в Servlet2.4.
Техника 6. Используйте
механизм сервлетов пула потоков, чтобы создать отдельный поток для каждого запроса, назначьте поток методу service(), а затем удалите поток после выполнения метода service(). По умолчанию механизм сервлетов может создавать новый поток для каждого запроса. Поскольку создание и удаление потоков требует больших затрат, такое поведение по умолчанию снижает производительность системы. Мы можем использовать пул потоков для повышения производительности. В соответствии с ожидаемым количеством одновременных пользователей настройте пул потоков и установите минимальное и максимальное количество потоков в пуле потоков, а также минимальное и максимальное значения роста. Первоначально механизм сервлетов создает пул потоков с количеством потоков, равным минимальному количеству потоков в конфигурации. Затем механизм сервлетов назначает поток из пула запросу вместо того, чтобы каждый раз создавать новый поток. После завершения операции механизм сервлетов помещает поток обратно в пул потоков. Используя пулы потоков, можно значительно повысить производительность. При необходимости можно создать больше потоков в зависимости от максимального количества потоков и количества роста.
Техника 7. Выберите правильный механизм включения
. На страницах JSP существует два способа включения файлов: инструкции включения (< %@includefile="test.jsp"% >) и действия включения (<jsp:includepage="test.jsp " флеш="истина"/>). Директива include включает содержимое указанного файла на этапе компиляции, например, когда страница компилируется в сервлет; Действие включения включает в себя включение содержимого файла на этапе запроса, например, когда пользователь запрашивает страницу; Включение инструкций выполняется быстрее, чем включение действий. Поэтому, если включенные файлы не меняются часто, вы сможете повысить производительность, используя директиву include.
Техника 8. Используйте соответствующие области действия в действиях useBean.
Один из наиболее мощных способов использования страниц JSP — это работа с компонентами JavaBean. JavaBeans можно встраивать в страницы JSP с помощью тега <jsp:useBean>. Синтаксис следующий:
<jsp:useBeanid="name"scope="page|request|session|application"class=
"package.className"type="typeName">
</jsp:useBean>
Атрибут области описывает видимую область действия компонента. Значением атрибута области по умолчанию является страница. Вам следует выбрать правильный диапазон в зависимости от потребностей вашего приложения, иначе это повлияет на производительность вашего приложения.
Например, если вам нужен объект, специфичный для какого-либо запроса, но вы установили область сеанса, этот объект останется в памяти после завершения запроса. Он останется в памяти, пока вы явно не удалите его из памяти, не сделаете сеанс недействительным или не истечет время сеанса. Если вы не выберете правильный атрибут области, это повлияет на производительность из-за затрат памяти и сбора мусора. Поэтому установите подходящую область для объектов и удалите их, как только закончите с ними.
Различные методы
1) Избегайте конкатенации строк: поскольку объекты String являются неизменяемыми объектами, использование оператора «+» приведет к созданию большого количества объектов с нулевым временем. Чем больше «+» вы используете, тем больше объектов с нулевым временем будет создано, что повлияет на производительность. Если вам нужно объединить строки, используйте StringBuffer вместо операции «+».
2) Избегайте использования System.out.println: System.out.println синхронно обрабатывает дисковый ввод/вывод, что значительно снижает пропускную способность системы. По возможности избегайте использования System.out.println. Хотя существует множество зрелых инструментов отладки, иногда System.out.println по-прежнему полезен для целей отслеживания или отладки. Вам следует настроить System.out.println так, чтобы он открывался только на этапах ошибок и отладки. При использовании переменной FinalBoolean, если для нее задано значение false, проверки оптимизации и выходные данные трассировки выполнения выполняются на этапе компиляции.
3) Сравнение ServletOutputStream и PrintWriter: из-за потока вывода символов и кодирования данных в байты использование PrintWriter приводит к небольшому снижению производительности. Поэтому PrintWriter следует использовать после того, как все преобразования наборов символов выполнены правильно. С другой стороны, если вы знаете, что ваш сервлет будет возвращать только двоичные данные, используйте ServletOutputStream, поскольку контейнер сервлета не кодирует двоичные данные, поэтому вы устраняете накладные расходы на преобразование набора символов.
Резюме
Цель этой статьи — показать вам некоторые практические и проверенные методы оптимизации производительности для улучшения производительности сервлетов и JSP, что улучшит общую производительность ваших приложений J2EE. Следующим шагом должно стать наблюдение за настройкой производительности других связанных технологий, таких как EJB, JMS и JDBC.