воскресенье, 16 ноября 2008 г.

О масштабируемости систем(ч.3)

Асинхронное взаимодействие
Еще один ключевой момент при потстроении хорошо масштабируемых систем - это асинхронность. Например, если компонент А обращается к компоненту Б посредством синхронного вызова, то А и Б являются тесно связанными, а значит, если нужно будет масштабировать А, то тоже самое придется делать и с Б. Точно так же дело обстоит и с доступностью - если выйдет из строя Б, то А тоже не сможет функционировать нормально. 

Но если организовать взаимодействие между ними посредством асинхронных вызовов и организовать взаимодействие, напрмер, через очередь, то масштабировать их можно будет уже независимо друг от друга. Более того, теперь у них будут независимые характеристики доступности - отказ одного из них вовсе не будет означать отказ другого, поскольку такого тесного взаимодействия, как при синхронных вызовах, у них больше нет.

Такой подход имеет отражение в некоторых научных работах, в частности SEDA(Stage Event-Driven Architecture for highly concurrent server applications). 

Из этого следует, что как можно большую часть бизнес-процессов следует реализовывать именно асинхронным образом, поскольку в системах, где время реакции ситсемы на запрос критично, это может существенно снизить время ответа системы. Например, в e-commerce системах время получения ответа пользователем намного важнее, чем время, за которое время запрос будет реально обработан системой. Это позволит пользователю не терять время на ожидание ответа системы, а заняться другими делами, в то время как его запрос будет поставлен в очередь на обслуживание и обработан. В подобных системах нужно придерживаться принципа - "все, что может подождать - должно подождать".

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

Создание необходимых уровней абстракции
Не буду подробно на этом останавливаться, и так понятно, что все функциональные слои должны иметь свои уровни абстракции - то есть например, работа с БД должна производиться при помощи ORM или иного интерфейса, который возьмет на себя все функции по взаимодействию с БД, распределению нагрузки между серверами БД(в случае распределенных серверов БД, какие были описаны выше) и т.д. Абстрагирование резко упростит жизнь при последующем масштабировании системы, поскольку будет отсутствовать жесткая привязка к конкретным типам системных ресурсов, а так же можно на соответсвующем уровне абстракции организовать управление физическими ресурсами.

Правильный выбор кэшируемых данных
Это очень важный момент, поскольку кэширование в определенных случаях способно существенно повысить производительность, а в других - сильно осложнить жизнь. Здесь трудно найти общую закономерность, и принятие решения о том, что следует кэшировать, зависит от конкретного use case. 

Вообще, эффективность кэширования определяется как максимальное cache hit ratio при ограничениях на объем кэшируемой информации, ее доступность и определенным уровнем толерантности к неактуальной информации.

Чаще всего кэшируются по большей части read-only или редко модифицируемые данные, такие как: метаданные, конфиги, словари и т.д. Гораздо более сложными в плане кэширования являются часто обновляемые и часто читаемые данные, поэтому следует хорошо подумать, прежде чем их кэшировать.

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

На днях наткнулся на интересную white-paper, в ней описывается, как снизить нагрузку на сервер БД при использовании Hibernate. Используется технология под названием Terracotta, достаточно известная в настоящее время.

Комментариев нет: