Pull to refresh

Comments 36

Кто-нибудь использует J2EE для хай-лоад проектов? Какая нагрузка, стабильность?
Я честно о таком впервые слышу. Обычные отзывы о J2EE контейнерах перемешаны с кровью, потом и слезами даже на простых проектах. Не слышал об исключениях.
А большая нагрузка — это сколько? У нас 300 запросов в секунду формально на двух серверах, реально на одном и мы не упираемся в производительность.
Обычно принято считать большие нагрузки примерно от 1000 запросов в секунду
«Большая нагрузка» — как «большие данные». С одной стороны баззворд, с другой — для каждого свое понимание. Наверное, как и в случае с большими данными, это когда не помещаешься в один сервер уже по физическим ограничениям (например, совокупный объем передаваемых данных больше гигабитного сетевого канала)

Коллега, работавшая в гугле, написала маленький сервис, который обрабатывал 200 тысяч запросов в секунду на нескольких серверах, и не считала это большой нагрузкой.
Ну вот да, я написал своими руками сервис на EE, который обрабатывает 10000 запросов в секунду на EE платформе на одном сервере. Но сервис-то простой, чего ему не работать?
«Сбербанк Онлайн» — думаю можно считать высоконагруженным.
Уточните заодно сколько серверов обслуживает СБОЛ
Не знаю, а если бы знал не сказал. Зависит от реализации кода самих приложений. Для бэкенда может быть достаточно и двух интеловых серверов.
Кто-нибудь использует J2EE?!
Йа! :) Уже лет 10, а то и больше. Начинал с JBoss 3.
А в каком JBoss до сих пор J2EE?
Гм… вы меня смутили. Возможно я не правильно истолковал «J2EE»?
Возможно. Лучше различать JEE и J2EE, слишком разные платформы.
Что касается пунктов…

Сейчас очень распространены легковесные фреймворки типа Play (со своим шаблонизатором, который компилится в исходный код) и SPA решения…
JSP, конечно, — боль. Но почему сразу сервлеты? У вас же код нечитаемым месивом будет.
И, да, а почему JSP тормозной? Он же в сервлет компилируется.

Совет не писать собственный пул потоков в бд доставило…

Почему вы рассматриваете очереди, deadlocks в этом ключе?
Давно придумали functional, reactive programming, чтобы увести в 0 взаимодействие между потоками. А если взаимодействие есть, то его осуществлять на неблокируемых операциях like CAS.
Подразумевал что java не используется для генерации html, а как бэкенд сервисы. Сервлеты в этом случае не выглядят месивом, но да есть и лучше.
JSP компилится на сервере и не один раз, тормознутость мне кажется зависит от конкретной реализации.
Перекомпилируется при изменении, да и это можно отключить.
Насчёт логгирования — рекомендуют использовать slf4j, который сам и объекты поставит и уровень логгирования проверит.
Оборачивать в .isDebugEnabled() всё равно приходится, если аргументами передаются не просто объекты, у которых вызов toString() выдаст что-то адекватное. Как пример — объект типа массив.

неправильно:
log.debug("myArray: {}", myArray);

правильно:
if (log.isDebugEnabled()(){
  log.debug("myArray: {}", Arrays.toString(myArray));
}
UFO just landed and posted this here
Как минимум, это будет «экономия на спичках» — внутри метода debug так же происходит вызов isDebugEnabled. Но я лучше вызову дважды isDebugEnabled, чем сперва преобразую объекты в нужную для debug-лога форму, а потом только проверю — а надо ли мне выводить в debug-лог что-то?

Для себя использую простые правила для оборачивания кода в if (isDebugEnabled):
0) если не получается передать просто объект(-ы) как параметры в log
1) если подряд идут несколько вызовов log.
В остальных случаях просто вызываю log.debug
Немного своего опыта.

Платформа JEE. Само понятие высоконагруженной системы говорит о том, что стандартные решения не подходят или нуждаются в доработке. Тк готовые решения обычно подходят для всего и ничего не знают про ваш домен, то они вряд ли смогут применить оптимизации, доступные только вам. При разработке подобных систем стоит выбирать несвязанные (опенсорсные) компоненты и включать их в проект. Например, отлично подходит embedded jetty в качестве сервера (его отдельные куски потом можно будет переписать). В качестве IOC контейнера лучше выбрать guice, который решает только одну задачу, чем спринг, который решает сразу все.

Очереди. Время обработки сообщения, попавшего в конец очереди размера x10, будет во много раз меньше чем время ожидания его обработки. Нет смысла заставлять пользователя ждать когда мы при этом ничего не делаем. Очереди должны быть размером x1-x2 и необходимо постоянно мониторить их размер. По хорошему очереди всегда должны быть пустыми. Исключение составляют очереди, которые обрабатываются батчем (например, из-за io).

Логирование. Не нужно стесняться логировать. Чем больше информации в логах, тем потом проще расследовать баги. До тех пор пока мы пишем на диск в отдельном потоке, iostat не показывает критичных спайков, и сброс на диск не забивает очередь логгера, нужно писать все что есть в лог.

Мониторинг. + мониторинг gc, safepoint'ов и прочего в самой java.

И еще немного от себя:

Профилирование. Нужно освоить JMC и периодически просматривать дампы на предмет больших и не нужных аллокаций/промоушенов. Так же в поиске горлышке очень поможет расстановка меток в коде и их последующей визуализации (как это сделано в js профилировщике, например, в ff).

CI нагрузочное тестирование. Если проводить тесты по коммитно, то сразу будет видна деградация производительности.
Про очередь. Согласен, но только при равномерной нагрузке. У меня же, например, получается постоянно 300 запросов в секунду, но каждые 10 секунд приходит сразу 2000. Тут хочешь не хочешь, но запас в очереди должен быть большой.
А еще можно попробовать в качестве IOC юзать Dagger2. Это может помочь для хаилоада, т.к. в нем нет рефлекшина в рантаиме.
Тезис «не нужно стесняться логировать» очень спорный и хорош только для небольших проектов. Когда количество логов начинается измеряться в терабайтах в сутки, то команда отвечающая за спланк (или другой лог агрегатор) заставляет тебя пересмотреть полезность некоторых логов)
про джус странный совет. обычно спринг используют именно ради того, чего у джуса нет )
ну и вообще, скорость работы IoC контейнера важна только если вы создаете и работаете с кучей иньекций в райнтаме, например, на каждый запрос.
Не стоит забывать о том, что спринг создает кучу прокси поверх бинов.
спринг создает прокси только когда его просят создать прокси :) если в проекте не нужны декларативные транзакции и прочая радость, тогда и прокси никто не создает (если не копипастит конфиги с aop:autoproxy)
если в проекте нужно проксить только отдельные классы, то для того и созданы две разные аннотации Service и Component
Согласен, погорячился. Забыл что у меня Spring Boot много лишнего успевает сделать.
Понеслааась…

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

и в итоге все равно получиться чуточку хуже, чем то, как это реализовано в современных JEE серверах.
Всегда задаю вопрос: а что такого особенного реализовано в JEE серверах? Какие супер-пупер технологии? Вебстек, альтернатив которому уже десятки? Наихудшая, непонятная и неудобная модель компоновки и запуска приложения, связанная с запаковкой всего в .Xar? Рудиментарный EJB? CDI? Webservices? JDBC pool? JPA? Все это доступно standalone без особого напряга. Правильный ответ дают лишь немногие: это JTA (distributed transactions). Если Вы не используете JMS и в проекте только одна база данных, можете смело забыть о JEE.

Все промахи всплывут только под реальной нагрузкой, и архитектуру приложения придется переделывать не один раз.
До сих пор всплывали промахи, связанные именно с сервером приложений и стеком JEE. Причем в этом случае архитектуру Вы уже сильно не поменяете.

Java.nio для сети
Не успев полностью сесть на JEE вы уже прикручиваете сбоку какой-то левый велосипед, который и близко не лежал к стеку. Если уж Вы рекомендуете JEE, так используйте его средства: http servlets, JMS, Remote EJB, WS… Либо как белый человек пишите свой resource adapter, согласно спецификации. И уж там можете пользовать хоть java.nio, хоть netty…

Если вы пишете пул сами, а не используете готовый в случае JEE, нужно внимательно расставить тайминги.
Если Вы используете готовый, то нужно еще более внимательно расставить тайминги. Weblogic имеет более 100 настроек для пула. Еще надо найти и включить мониторинг для пула, чтобы время от времени выявлять незакрытые ресурсы и впоследствие ломать голову над тем, где в коде происходит leaking.

Они нужны для взаимодействия между потоками,
В JEE нет такого паттерна как «взаимодействие между потоками». Есть асинхронное выполнение, есть асинхронное взаимодействие посредством JMS. Все остальное синхронно.

Не стоит использовать JSP для высоко нагруженной системы, даже с кэшем он будет медленнее сервлетов.
JSP при использовании скриплетов (теги с процентиками) компилируется в .class и работает с той же скоростью, что и сервлет. Если вы используете различные tag libraries (например JSTL и EL), то перформанс будет немного проседать ввиду того, что приходится интерпретировать теги. Однако, вроде бы есть компилятор для JSTL. Если же вы используете JSF, то перформанс падает значительно. JSF — технология не для hiload.

Лучше собирать и писать в базу эти метрики отдельным софтом или самостоятельно.
Опять велосипед. Коммерческие сервера предлагают свои средства для сбора метрик и мониторинга. Это именно то, за что собирают деньги. А уж если мне нужно свой велосипед для мониторинга, то гораздо проще его будет присобачить без JEE.

Дело в том, что сервер следит за своими потоками и отлавливает deadlock
Полная фигня. Сервер не отлавливает ничего. Сама архитектура JEE предполагает отсутствие дедлоков и правильную блокировку. Просто серверный пул конфигурируется и мониторится сервером. Плюс некоторые сервера могут корректно закрывать некоторые оставленные ресурсы типа connections из пулов. И еще корректно закрываться в случае остановки сервера. Недостаток всех пулов: нельзя использовать ThreadLocal (вернее очень осторожно).
TransactionManager там реализован. И это очень сложно написать самому. JTA вообще сложная штука, если честно. EJB 3 ничем особо не отличается от спринговых бинов. Почему он рудиментарен?
Это CDI ничем не отличается от спринговых бинов — то же, только хуже. А EJB — это более тяжелая технология, которая служит для интеграции с платформой. Почему рудиментарные? Stateless EJB организует пул объектов, которые гарантируют изолированность вызовов, что вобщем-то не требуется, если ваш объект stateless. Statefull вообще непонятно где может использоваться, плюс имеет такую фичу как пассивация объекта через какое-то время и сохранение состояния где-то в дебрях диска. Внезапно происходят exceptions если ваш Stateful не Serializable. Message driven bean до сих пор нет стандартного способа хорошо указать ActivationConfigProperties. Они все vendor-specific. Singleton bean мешает кластеризированию — он, оказывается, всего лишь server instance singleton, а не application singleton. Годная вещь — remote EJB interface. Но она также vendor-specific, и практически всегда непроксируема (только в локальной сетке), поэтому всегда предпочтительней JAX-WS или JAX-RS, чем remote EJB.
И, наконец, очень медленные. Чтобы посмотреть через что проходит ваш простой вызов к EJB, просто сделайте stacktrace…
Насчёт пула стейтлессов — это просто разные подходы. С пулом вы можете огрничить пропускную способность вашего бина сверху. Можете, прошу прощения, сделать в бине синхронайзд метод и всё будет. Стэйтфул — иногда полезно, хотя кейсы редки. Но оно же для JSF (который весьма ублюдочен, да, но иногда используется…) хорошо. Насчёт проксей — у меня для вас грустна новость, даже две. 1 — спринг их тоже создаёт, 2 — это не узкое место. А ещё там на каждом шагу секьюрити манагер, что может и совсем не бесплатно, зато даёт кое какие гарантии.
Прошу прощения, не дочитал ваш тезис. Вы, оказывается сами про JTA написали.
Я ещё добавлю что Wildfly, например, имеет вендор-спцифик валидаторы для коннекшнов к разным БД. Оракла, постгреса и так далее.
Не имел ввиду JEE как набор стандартов/спецификаций, а только как сервер приложений, наверно забыл добавить. То что он умеет EJB, JMS и тд. совпадение — они скорее для удобства чем для лучшей производительности.
А в серверах приложений уже реализовано много для высокой нагрузки, где-то лучше где-то хуже. Но во всех есть правильная работа с сетью через java.nio(причем здесь велосипед я не понял из комментария) и многопоточность и возможность это контролировать и управлять. Писать это самому глупо, когда есть готовое и в том числе опенсорсное с возможностью подкрутить для себя.
Это тоже что использование стороннего фреймворка, вы экономите время и получаете обкатанное решение. И кучу дополнительных проблем с ним же.
WebSphere отлавливает взаимоблокировки, блокировки и зацикливания в потоках. Вы не правы. Configuring the hang detection policy
Остальное совсем не в тему))
Sign up to leave a comment.

Articles