Highload на Java

Для ясности, давайте назовем «Highload» сетевое приложение, которое должно обрабатывать 1000 запросов в секунду. А приложение, обрабатывающее 1 запрос в секунду, соответственно, «не Highload».

Многие фреймворки имеют ограничения на производительность - будьте готовы жить с самописками или искать те немногие решения, которые пройдут нагрузочные тесты под ваше конкретное приложение. Верить в этом деле нельзя никому.

Кеширование, кеширование и еще раз кеширование - Редкая высоконагруженная система обходится без кешей — особенно над СУБД. Правильное кеширование в распределенной системе — это большая и сложная тема, поэтому имеет смысл задуматься сразу о данных: кто и как будет их обновлять и запрашивать, а также где и как можно пожертвовать целостностью или актуальностью данных.

Простота - В целом — чем проще система, тем быстрее она работает. Нужно стремиться к максимальной простоте, часто в ущерб понятности, концептуальности или красоте архитектуры.

Пропускная способность сети имеет пределы - При выборе формата сериализации позаботьтесь заранее умножить средний размер пакета на кол-во пакетов в секунду и сравнить с пропускной способностью вашей сети. В этом плане Json лучше, чем XML, Protobuf лучше, чем JSON, а иногда приходится изобретать свой формат, с лучшей степенью упаковки.

Не забывайте про off-heap - Некоторые объекты в Java требуют дополнительную память для работы, поэтому не нужно рассчитывать, что если -Xmx выставлен, то приложение точно влезет на сервер. Например, каждый поток в Java требует от 256K до 2 мегабайт off-heap памяти для своей работы. При умножении на 1000 получается уже достаточно много, так что следите за кол-вом потоков, используемых вашим приложением.

GC не резиновый - Даже если строгих требований к latency нет, о сборке мусора нужно помнить. Старайтесь ограничивать кол-во аллокаций и, особенно, общий объем выделяемой памяти на каждый запрос. Все необходимые метрики есть в профайлере Java Mission Control.

Аккуратнее с логгированием - Утверждение «приличное приложение всегда должно логгировать входные и выходные данные» — верно, но в высоконагруженном приложении легко станет узким местом вашей системы. Часто приходится вообще не писать логи на диск, а слать их по сети в специализированную систему (и помнить, что сеть тоже не резиновая, ага).

Поведение при нехватке ресурсов - Что делать, если приложению приходит больше запросов, чем оно способно прожевать? Если база внезапно стала отвечать в два раза медленней? Если в сети начались потери пакетов? Хорошее приложение должно не виснуть наглухо, а отвечать «завтра приходи». Мораль — для всех взаимодействий с внешними системами должны быть таймауты, приложение должно ограничивать кол-во параллельно обрабатываемых запросов и клиент должен знать, что делать, если приложение занято или не отвечает.

Сделайте нормальный мониторинг - Еще одна сложная и обширная тема, но вкратце — если приложение наметво повесило машину, то где-то должны остаться графики потребления памяти, свопа, диска, цпу, потоков, системных дескрипторов.

И всегда тестируйте приложение под нагрузкой - Приложение легко может умереть под высокой нагрузкой, вполне прилично себя ведя под низкой. Если оно работало неделями на 1 запросе в секунду, на 1000 оно может умереть из-за ничтожной утечки памяти или ресурсов, перегрузки сети, перегрузки или переполнения диска и еще по 1001 причине. Поэтому — всегда гоняйте билд на полной нагрузке перед релизом на прод.

https://habrahabr.ru/post/270059/