Как стать автором
Обновить

Точки отказа в HighLoad-системах

Уровень сложностиСредний
Время на прочтение11 мин
Количество просмотров6.1K
Всего голосов 14: ↑14 и ↓0+16
Комментарии11

Комментарии 11

Например, когда мы смотрели запросы Хибера профилировщиком, обнаружили, что перед каждым Insert он делает Select. Это нужно, чтобы понять, есть ли в базе эта запись, и действительно ли нужно делать Insert, или достаточно заменить insert командой update. Наверное, это не то, чего вы действительно хотите, ведь в этом случае приложение делает два запроса вместо одного, и время значительно деградирует.

Я от использования Хибера отказался лет 15 назад. По той же причине. Меня категорически не устраивало качество запросов, которые он генерировал. Ситуация похоже не изменилась, что логично.

Много альтернатив перепробовал, в итоге остановился на jOOQ. С одной стороны, по удобству он сопоставим с классическими ОРМ решениями, с другой позволяет жёстко контролировать генерируемые запросы.

И есть ещё одно колоссальное преимущество. Если говорить про Postgres, то в нём есть огромный набор фич, далеко выходящих за рамки ANSI SQL. Я, если честно, уже давно не считаю постгрес исключительно реляционной СУБД. Благодаря этим фичам на нем можно эффективно реализовывать многие нереляционные решения. И все эти возможности поддерживает jOOQ.

Например упомянутую автором операцию insert or update в постгресе можно выполнить одним запросом с условием ON CONFLICT. В jOOQ такой запрос генерируется с помощью ON DUPLICATE KEY UPDATE. Я эту возможность очень часто использую для обеспечения идемпотентности вставки (в качестве первичного ключа использую случайный uuid, генерируемый на клиенте).

И пример, который я здесь привёл, это крохотная часть возможностей, которые предоставляет связка Postgres + jOOQ.

Hibernate требует его знания и мышления в его стиле. Прежде чем на нем писать, про него нужно читать, чтобы потом не было откровением, что при merge Hibernate делает select. В транзакциях объекты достаются один раз из БД и больше в БД приложение за ними не лезет, но вот проектировать эти транзакции нужно аккуратно, знать, например, про OSIV.

Под Hibernate нужно писать и проектировать в определенном стиле, чтобы не возникало ситуации ON CONFLICT. Но банках обычно тебе дают БДшники таблицу и ты уже с ней ковыряешься, т.е. разработка идеи не от Entity к таблицам, а от таблиц к Entity, в результате проще взять JdbcTemplate и абстрактные DTO без relations.

Ну и ещё надо уметь criteria API, иначе выигрыш незначителен.

Короче Hibernate надо уметь готовить, и он не для банков.

По поводу мониторинга соединений. Если вы используете Kubernetes (а вы его наверняка используете), то мониторить нужно не только сами микросервисы, но и куберовские прокси вроде Istio. Нам Istio в своё время массу нервов попортил. У нас жёсткое ограничение по latency в 100 миллисекунд. А в микросервисной архитектуре 90% latency жрёт взаимодействие по HTTP. А самое дорогое удовольствие во взаимодействии по HTTP - это установка соединения. А если у вас сконфигурирован TLS внутри кластера - то это не просто дорого, а адски дорого. TLS Handshake с радостью жрёт все ваши лимиты. Чтобы решить эту проблему, мы вместо стандартных http клиентов попытались использовать пулы соединений, чтобы эти самые соединения не переоткрывать на каждый запрос. И, каково же было наше удивление, когда выяснилось, что переход на пул соединений никак не уменьшил latency. После долгих исследований мы выяснили, что пул держал нам постоянные соединения до Istio. А Istio при каждом запросе переоткрывал HTTP соединение до целевого сервиса. Подкрутили настройки Istio, и проблема была решена.

НЛО прилетело и опубликовало эту надпись здесь

Снимаю шляпу! Я тоже баловался со своим асинхроным транспортным уровнем поверх постоянно открытого TCP сокета. Тоже хорошие результаты получал. Но, к сожалению, это решение не вписывается в наши корпоративные стандарты. Поэтому пришлось шаманить с HTTP.

По поводу кубера тоже согласен - он хорош для high-throughput решений, а для low latency совершенно не годится. Тоже приходится шаманить :)

HTTP очень дорогой для хайлоада, как это не кощунственно звучит,

Я сейчас ещё более кощунственную вещь скажу. Если у вас low latency хайлоад, то там не только http но и микросервисная архитектура в целом слишком дорогое удовольствие. Там, в идеале, нужны старые добрые монолиты.

Но у нас одновременно low latency + high throughput, поэтому без горизонтального масштабирования никак. Вот и приходится проскальзывать между молотом и наковальней. Шаманим :)

Интересная статья! Очень много узких мест) В эту тему не так давно прочитал книгу Цель Голдратта - там интересно описано, что делать для повышения эффективности производства, ещё и в художественном контексте. Может бысть есть что-то похожее для high load систем?)

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Хотел уточнить про раскидывание по конвейерам. Имеется ввиду делать N потоков, обслуживающих M соединений?

Про вынос TCP стека в user space ещё хотел уточнить - ради избавления от context switch, походов в ядро? Благодаря этому будет буст производительности?

НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий