Мы испытываем огромные различия во времени отклика в устаревшем веб-приложении J2EE, работающем на Weblogic 10.3. Система состоит из двух экземпляров сервера Weblogic (внешнего и внутреннего), которые работают на одном физическом сервере, и базы данных Oracle, работающей на отдельном хосте. Внешний инструмент измерения предупреждает нас каждый раз, когда вход в систему занимает более четырех секунд. В последнее время эти предупреждения были частыми. Просмотр журнала, написанного сервлетом, обрабатывающим запросы на вход, показывает, что время, потраченное на вызов EJB от внешнего интерфейса к внутреннему.
Пример измеренного времени:
time ms
8:40:43 25
8:42:14 26
8:44:04 26
8:44:25 26
8:44:47 26
8:46:06 26
8:46:41 7744
8:47:00 27
8:47:37 27
8:49:00 26
8:49:37 26
8:50:03 8213
8:50:57 27
8:51:04 26
8:51:06 25
8:57:26 2545
8:58:13 26
9:00:06 5195
Как видно, большинство запросов (70%, взятых из более крупной выборки) выполняются своевременно, но значительная их часть занимает очень много времени.
Шаги, выполняемые в течение измеренного времени, следующие:
- Поиск JNDI сессионного компонента, предлагающего интерфейс аутентификации (внешний интерфейс)
- Вызов метода аутентификации сессионного компонента (frontend-> backend)
- Резервирование JDBC-соединения из пула соединений (бэкэнд)
- Выполнение запроса к пользовательской базе данных (размер таблицы очень умеренный, и таблица должна быть правильно проиндексирована) (бэкэнд)
- Чтение набора результатов, создание пользовательского объекта POJO (бэкэнд)
- Возвращение объекта пользователя POJO (backend-> frontend)
Нагрузка на серверную машину очень мала (99% простоя), а количество пользователей очень умеренное. Количество свободной памяти, сообщаемое Weblogic, варьируется от 60% до 90% на обоих серверах. Сборка мусора записана. Основные коллекции редки и заканчиваются за 2-3 секунды, когда они появляются. Кроме того, основные явления ГХ, по-видимому, не происходят одновременно с длительным временем отклика. Длительное время отклика происходит в часы занятости и в нерабочее время. Максимальный размер пула соединений JDBC в настоящее время установлен равным 80, что превышает количество одновременных пользователей.
Обновление:
Получено разрешение на перезагрузку системы с добавлением дополнительной регистрации производительности. Журнал ясно показывает, что поиск JNDI - это та часть, где тратится время:
03:01:23.977 PERFORMANCE: looking up foo.bar.Bar from JNDI took 6 ms
03:14:47.179 PERFORMANCE: looking up foo.bar.Bar from JNDI took 2332 ms
03:15:55.040 PERFORMANCE: looking up foo.bar.Bar from JNDI took 1585 ms
03:29:25.548 PERFORMANCE: looking up foo.bar.Bar from JNDI took 7 ms
03:31:09.010 PERFORMANCE: looking up foo.bar.Bar from JNDI took 6 ms
03:44:25.587 PERFORMANCE: looking up foo.bar.Bar from JNDI took 6 ms
03:46:00.289 PERFORMANCE: looking up foo.bar.Bar from JNDI took 7 ms
03:59:28.028 PERFORMANCE: looking up foo.bar.Bar from JNDI took 2052 ms
Просмотр журналов GC внешнего и внутреннего интерфейсов показывает, что GC не выполняется, когда происходит медленный поиск JNDI.
Контекст создается следующим образом при создании сеанса:
Hashtable ht = new Hashtable();
ht.put(Context.PROVIDER_URL, url);
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
jndiContext = new InitialContext(ht);
где url
- это URL-адрес t3, указывающий на DNS-имя и порт внутреннего сервера. Это должно быть хорошо, верно?
Первое, что нужно вспомнить, - это кэшировать ссылки, полученные из JNDI, по крайней мере, это был предпочтительный путь 10 лет назад ... Но разве реализация InitialContext в Weblogic уже не выполняет это кэширование, или она действительно извлекается ссылка с внутреннего сервера на каждый звонок?
Что может быть причиной частых медленных поисков JNDI? Есть ли обходной путь для этого (например, поможет ли кэширование ссылок)?