Масштабирование нагрузки web-приложений
С ростом популярности web-приложения его поддержка неизбежно начинает требовать всё больших и больших ресурсов. Первое время с нагрузкой можно (и, несомненно, нужно) бороться путём оптимизации алгоритмов и/или архитектуры самого приложения. Однако, что делать, если всё, что можно было оптимизировать, уже оптимизировано, а приложение всё равно не справляется с нагрузкой?
Оптимизация
- оптимальны ли запросы к БД (анализ EXPLAIN, использование индексов)?
- правильно ли хранятся данные (SQL vs NoSQL)?
- используется ли кеширование?
- нет ли излишних запросов к ФС или БД?
- оптимальны ли алгоритмы обработки данных?
- оптимальны ли настройки окружения: Apache/Nginx, MySQL/PostgreSQL, PHP/Python?
Масштабирование
И так, допустим, что оптимизация уже проведена, но приложение всё равно не справляется с нагрузкой. В таком случае решением проблемы, очевидно, может послужить разнесение его по нескольким хостам, с целью увеличения общей производительности приложения за счёт увеличения доступных ресурсов. Такой подход имеет официальное название – «масштабирование» (scale) приложения. Точнее говоря, под «масштабируемостью» (scalability) называется возможность системы увеличивать свою производительность при увеличении количества выделяемых ей ресурсов. Различают два способа масштабирования: вертикальное и горизонтальное. Вертикальное масштабирование подразумевает увеличение производительности приложения при добавлении ресурсов (процессора, памяти, диска) в рамках одного узла (хоста). Горизонтальное масштабирование характерно для распределённых приложений и подразумевает рост производительности приложения при добавлении ещё одного узла (хоста).
Понятно, что самым простым способом будет простое обновление железа (процессора, памяти, диска) – то есть вертикальное масштабирование. Кроме того, этот подход не требует никаких доработок приложения. Однако, вертикальное масштабирование очень быстро достигает своего предела, после чего разработчику и администратору ничего не остаётся кроме как перейти к горизонтальному масштабированию приложения.
Архитектура приложения
Большинство web-приложений априори являются распределёнными, так как в их архитектуре можно выделить минимум три слоя: web-сервер, бизнес-логика (приложение), данные (БД, статика).
Каждый их этих слоёв может быть масштабирован. Поэтому если в вашей системе приложение и БД живут на одном хосте – первым шагом, несомненно, должно стать разнесение их по разным хостам.
Узкое место
Приступая к масштабированию системы, первым делом стоит определить, какой из слоёв является «узким местом» — то есть работает медленнее остальной системы. Для начала можно воспользоваться банальными утилитами типа top (htop) для оценки потребления процессора/памяти и df, iostat для оценки потребления диска. Однако, желательно выделить отдельный хост, с эмуляцией боевой нагрузки (c помощью AB или JMeter), на котором можно будет профилировать работу приложения с помощью таких утилит как xdebug, oprofile и так далее. Для выявления узких запросов к БД можно воспользоваться утилитами типа pgFouine (понятно, что делать это лучше на основе логов с боевого сервера).
Обычно всё зависит от архитектуры приложения, но наиболее вероятными кандидатами на «узкое место» в общем случае являются БД и код. Если ваше приложение работает с большим объёмом пользовательских данных, то «узким местом», соответственно, скорее всего будет хранение статики.
Масштабирование БД
Как уже говорилось выше, зачастую узким местом в современных приложениях является БД. Проблемы с ней делятся, как правило, на два класса: производительность и необходимость хранения большого количества данных.
Снизить нагрузку на БД можно разнеся её на несколько хостов. При этом остро встаёт проблема синхронизации между ними, решить которую можно путём реализации схемы master/slave с синхронной или асинхронной репликацией. В случае с PostgreSQL реализовать синхронную репликацию можно с помощью Slony-I, асинхронную – PgPool-II или WAL (9.0). Решить проблему разделения запросов чтения и записи, а так же балансировки нагрузку между имеющимися slave’ами, можно с помощью настройки специального слоя доступа к БД (PgPool-II).
Проблему хранения большого объёма данных в случае использования реляционных СУБД можно решить с помощью механизма партицирования (“partitioning” в PostgreSQL), либо разворачивая БД на распределённых ФС типа Hadoop DFS.
Однако, для хранения больших объёмов данных лучшим решением будет «шардинг» (sharding) данных, который является встроенным преимуществом большинства NoSQL БД (например, MongoDB).
Кроме того, NoSQL БД в общем работают быстрее своих SQL-братьев за счёт отсутствия overhead’а на разбор/оптимизацию запроса, проверки целостности структуры данных и т.д. Тема сравнения реляционных и NoSQL БД так же довольно обширна и заслуживает отдельной статьи.
Отдельно стоит отметить опыт Facebook, который используют MySQL без JOIN-выборок. Такая стратегия позволяет им значительно легче масштабировать БД, перенося при этом нагрузку с БД на код, который, как будет описано ниже, масштабируется проще БД.
Масштабирование кода
Сложности с масштабированием кода зависят от того, сколько разделяемых ресурсов необходимо хостам для работы вашего приложения. Будут ли это только сессии, или потребуется общий кеш и файлы? В любом случае первым делом нужно запустить копии приложения на нескольких хостах с одинаковым окружением.
Далее необходимо настроить балансировку нагрузки/запросов между этими хостами. Сделать это можно как на уровне TCP (haproxy), так и на HTTP (nginx) или DNS.
Следующим шагом нужно сделать так, что бы файлы статики, cache и сессии web-приложения были доступны на каждом хосте. Для сессий можно использовать сервер, работающий по сети (например, memcached). В качестве сервера кеша вполне разумно использовать тот же memcached, но, естественно, на другом хосте.
Файлы статики можно смонтировать с некого общего файлового хранилища по NFS/CIFS или использовать распределённую ФС (HDFS, GlusterFS, Ceph).
Так же можно хранить файлы в БД (например, Mongo GridFS), решая тем самым проблемы доступности и масштабируемости (с учётом того, что для NoSQL БД проблема масштабируемости решена за счёт шардинга).
Отдельно стоит отметить проблему деплоймента на несколько хостов. Как сделать так, что бы пользователь, нажимая «Обновить», не видел разные версии приложения? Самым простым решением, на мой взгляд, будет исключение из конфига балансировщика нагрузки (web-сервера) не обновлённых хостов, и последовательного их включения по мере обновления. Так же можно привязать пользователей к конкретным хостам по cookie или IP. Если же обновление требует значимых изменений в БД, проще всего, вообще временно закрыть проект.
Масштабирование ФС
При необходимости хранения большого объёма статики можно выделить две проблемы: нехватка места и скорость доступа к данным. Как уже было написано выше, проблему с нехваткой места можно решить как минимум тремя путями: распределённая ФС, хранение данных в БД с поддержкой шардинга и организация шардинга «вручную» на уровне кода.
При этом стоит понимать, что раздача статики тоже не самая простая задача, когда речь идёт о высоких нагрузках. Поэтому в вполне резонно иметь множество серверов предназначенных для раздачи статики. При этом, если мы имеем общее хранилище данных (распределённая ФС или БД), при сохранении файла мы можем сохранять его имя без учёта хоста, а имя хоста подставлять случайным образом при формировании страницы (случайным образом балансирую нагрузку между web-серверами, раздающими статику). В случае, когда шардинг реализуется вручную (то есть, за выбор хоста, на который будут залиты данные, отвечает логика в коде), информация о хосте заливки должна либо вычисляться на основе самого файла, либо генерироваться на основании третьих данных (информация о пользователе, количестве места на дисках-хранилищах) и сохраняться вместе с именем файла в БД.
Мониторинг
Понятно, что большая и сложная система требует постоянного мониторинга. Решение, на мой взгляд, тут стандартное – zabbix, который следит за нагрузкой/работой узлов системы и monit для демонов для подстраховки.
Заключение
Выше кратко рассмотрено множество вариантов решений проблем масштабирования web-приложения. Каждый из них обладает своими достоинствами и недостатками. Не существует некоторого рецепта, как сделать всё хорошо и сразу – для каждой задачи найдётся множество решений со своими плюсами и минусами. Какой из них выбрать – решать вам.
Что такое «масштабируемость»?
Что имеется в виду в контексте программирования, когда, например, говорят, что приложение должно быть масштабируемым? Приведите конкретные примеры для понимания.
- веб-программирование
- терминология
- масштабирование
Отслеживать
13.6k 12 12 золотых знаков 43 43 серебряных знака 73 73 бронзовых знака
задан 30 авг 2021 в 19:19
87 2 2 серебряных знака 8 8 бронзовых знаков
Лёгкость внесения изменений при увеличении какой-то метрики. Чаще всего имеют в виду количество активных соединений и количество запросов в секунду
30 авг 2021 в 19:44
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Обычно под «масштабируемостью» имеют в виду, что решение (это не только сама программа, но и инфраструктура для неё — БД, железо, на котором крутится БД и серверная часть и т.д.) может быть относительно легко (без смены архитектуры) переделано под сильно увеличившееся количество запросов/пользователей/объёмов данных/и т.д. просто количественным добавлением каких-то дополнительных ресурсов.
То есть вот написали люди, например, сайт, который способен обслуживать 5 посетителей одновременно. Скорее всего он справится и с 20 посетителями. А вот «переварит» ли он 100 посетителей или 1000 одновременно?
Если такое изменение посещаемости не приведёт к тому, что сайт станет работать очень медленно или вообще «впадёт в ступор», а он будет продолжать работать эффективно при принятии неких заранее оговоренных мер по достижении некоего порога посещаемости — например, если для этого нужно будет только увеличить оперативную память или перевести сайт на немного более мощный по CPU сервер, то говорят, что такое решение масштабируемо.
А вот если чтобы обслуживать 100 и тем более 1000 пользователей недостаточно будет принять простые меры по увеличению мощностей, а нужно будет переписывать ПО, мигрировать на другую БД, добавлять какие-то новые программные и аппаратные решения, то тогда говорят, что используемое решение не масштабируемо — оно способно работать только в каких-то определённых узких рамках, при выходе за которые это решение нужно будет фактически заново разрабатывать уже под другие количества/объёмы пользователей/данных/и т.д.
Хотя вопрос о том, насколько узкие или широкие должны быть эти рамки, в которых работает конкретное решение, чтобы можно было его назвать маштабируемым или наоборот не масштабируемым — это уже вопрос довольно субъективный. Всё-таки многие вещи имеют определённые пределы, например, оперативную память невозможно наращивать до бесконечности, как и процессорную мощность. Но если решение способно выдержать планируемое увеличение нагрузки на несколько порядков и способно «переварить» нагрузку, запланированную на него бизнесом на несколько лет вперёд — думаю, его можно называть масштабируемым.
Как настроить масштабирование в Windows
Высокое разрешение экрана иногда создает проблемы для операционной системы: нечитаемый текст, размытое изображение, нечеткие схемы и графики. Но существует встроенная функция — масштабирование, — которая поможет это исправить. Давайте разберемся, как ей правильно пользоваться и в каких случаях она может пригодиться.
Что это такое
Масштабирование — это изменение размеров элементов с сохранением пропорций
и исходного разрешения дисплея. В актуальных версиях Windows (10, 8.1 и 7) предусмотрена настройка шкалы масштаба в процентах. Нажмите правой кнопкой мыши на рабочем столе
и выберите «Параметры экрана». Откроется вкладка «Дисплей» системных настроек. Прокрутите вниз, пока не увидите опцию «Масштаб и разметка».
По умолчанию доступна настройка масштаба с шагом в 25 % (100, 125, 150, 175 % и далее). После изменения, возможно, придется перезапустить некоторые программы, а в особо запущенных случаях — даже перезагрузить систему. Приложение предупреждает об этом
в подсказке.
Если у вас Windows 7 или 8.1, кликните правой кнопкой мыши на свободном месте рабочего стола и выберите «Разрешение экрана». В появившемся окне жмите опцию «Изменение размеров текста и других элементов». Появятся аналогичные варианты масштабирования.
В каких случаях понадобится
Функция масштабирования стала актуальной в последнее десятилетие — с появлением 2K-
и 4K-дисплеев. У монитора есть характеристика PPI (англ. pixels per inch) — это количество пикселей на один дюйм экрана или разрешающая способность. Чтобы его посчитать, нужно знать диагональ монитора и исходное разрешение матрицы.
Воспользуемся теоремой Пифагора и узнаем его для 27-дюймового дисплея. Если вам лень вычислять вручную, можете обратиться к онлайн-калькуляторам. При разрешении 1920×1080, получаем 82 пикселя на дюйм. Если у такой же матрицы будет разрешение 2560×1440,
то плотность составит 109 PPI. А при 4K (3840×2160) получаем уже 163 PPI.
В последнем случае из-за высокой плотности изображение на экране будет слишком мелким — можно применить масштаб 175 или 200 %. При этом изменится DPI (англ. dots per inch) — виртуальный параметр, который отражает изменения размера элементов изображения. При масштабе 100 % PPI и DPI совпадают.
Если компьютерные мониторы со сверхвысоким разрешением пока не так популярны,
то подавляющая часть современных телевизоров уже выпускается с 4K-разрешением. Плотность пикселей здесь существенно меньше из-за размеров экрана (например, для 65-дюймового ТВ это будет всего 68 PPI).
Но стоит учитывать, что телевизор вы смотрите не вплотную, а с расстояния в несколько метров. Например, если подключаете его к ПК или ноутбуку как второй монитор, рекомендуем также выставить увеличенный масштаб в диапазоне 175–225 %, чтобы текст на экране был читаемым.
Подводные камни
В Windows 10 был внедрен новый принцип изменения размера приложений. Если раньше
в системе было четыре фиксированных типа DPI (96, 120, 144 и 192), то в «десятке» программа обязана уметь масштабироваться под любой размер виртуального пикселя. Эту идею разработчики из Microsoft подсмотрели у коллег из Google. В системе Android приложения выглядят нормально на любом устройстве (будь то планшет, телефон или умный телевизор).
Прошло уже шесть лет с момента выхода «десятки», и большинство программ поддерживают функции «резинового» масштабирования и легко адаптируются под нужный размер. Проблемы могут возникать только со старыми утилитами, которые не обновлялись много лет.
Мы рекомендуем использовать современное ПО и скачивать последние версии с официальных сайтов разработчиков.
Советы по масштабированию
Если вы все-таки пользуетесь устаревшими программами, рекомендуем заглянуть в подраздел настроек «Дополнительные параметры».
Здесь можно активировать опцию «Исправление масштабирования», которая призвана устранить размытость в классических приложениях. Это так называемый «костыль», который не всегда правильно работает. Если совсем ничего не помогает, уберите масштабирование
в свойствах ярлыка конкретной программы:
Также в этом окне можно задать пользовательское значение DPI, если вас не устраивает стандартный ряд.
Поэкспериментируйте и подберите оптимальный размер изображения конкретно для вас.
При подготовке материала использовались источники:
https://habr.com/ru/articles/113992/
https://ru.stackoverflow.com/questions/1322829/%D0%A7%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C
https://club.dns-shop.ru/blog/t-328-prilojeniya/45790-kak-nastroit-masshtabirovanie-v-windows/