Performance

Введение
На сегодняшний день сервисы, использующие данные о местоположении(Location Based Services) получили большое распространение. Это вызвано следующими факторами. Во-первых, число устройств поддерживающих различные типы определения местоположения растет с каждым годом. Согласно прогнозу на 2013 год, сделанному агентством RNCOS E-Services Private Limited рынок устройств с поддержкой GPS ждет 24% рост в 2013 году [1]. Во-вторых, точность определения местоположения с помощью GPS также растет [2].

LBS-платформа – ПО для организации работы Location Based сервисов. LBS-платформа Geo2Tag [3] позволяет упростить разработку сервисов данного типа, путем предоставления программных интерфейсов для хранения, обработки и редактирования геоданных.

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

Цель работы: максимизация производительности LBS-платформы Geo2Tag и выработка рекомендаций по ее горизонтальному масштабированию. Для достижения поставленной цели необходимо решить следующие задачи:
 * Исследовать существующие методы оценки производительности и балансировки нагрузки для информационных систем;
 * Измерить производительность системы;
 * Сформировать требования к улучшению производительности системы;
 * Обосновать выбор методики улучшения производительности;
 * Сравнить измерения производительности до и после оптимизации;
 * Проанализировать методы балансировки нагрузки для  исследуемой системы;
 * Построение математической модели показателей производительности после применения горизонтального масштабирования.

Объект исследования - LBS-платформа.

Предмет исследования - методы оптимизации производительности и балансировки нагрузки LBS-платформы.

Практическая значимость: оптимизация производительности позволит увеличить конкурентное  преимущество LBS-платформы, повысить лояльность пользователей к ней  и снизить требования к аппаратному обеспечению путем ускорения ее работы. Балансировка нагрузки позволит увеличить число одновременно обслуживаемых пользователей и повысит доступность LBS-платформы.

Математическая модель
Постановка задачи. Составить математическую модель работы клиентского приложения позволяющую делать выводы о наиболее часто предпринимаемых запросах к платформе при различных сценариях ее использования.

Решение. Рассмотрим модель взаимодействия клиентского приложения location client на уровне запросов протокола Geo2Tag для определения частоты использования различных запросов. Location client использует следующие запросы к LBS-платформе: login, subscribeChannel, unsubscribeChannel, subscribedChannels, loadTags, writeTag, applyChannel. Будем считать, что каждый запрос соответствует одному состоянию цепи Маркова и что существует дополнительное поглощающее состояние, соответствующее выходу из программы. Пусть также сценарий использования приложения не меняется со временем. Используя в качестве источника сведений статью [18], составим однородную стохастическую матрицу системы:



где - вероятность перехода из состояния i в состояние j. Состояния с 1 по 7 соответствуют выполнению одного из запросов «Авторизация» (login), «Подписка на канал» (subscribeChanne), «Удалить подписку на канал» (unsubscribeChannel), «Список подписанных каналов» (subscribedChannels), «Ближайшие геотеги» (loadTags), «Добавить геотег» (writeTag), «Добавить канал» (applyChannel),  а последнее состояние  соответствует закрытию программы.

По матрице переходов системы в классе цепей Маркова можно оценить среднее количество пребываний в заданном наперед состоянии используя следующую формулу:



где M – число не поглощающих состояний системы; матрица E – единичная матрица порядка М; Q – матрица переходов, из которой исключили строки и столбцы соответствующие поглощающим состояниям; - среднее количество пребываний в состоянии j, если начальным состоянием было i. Кроме того, по матрице переходов можно найти матрицу дисперсий:



где - матрица, полученная из  T  обнулением всех элементов, не лежащих на главной диагонали;   - матрица, полученная из T возведением каждого элемента в квадрат;  - дисперсия количества пребываний в состоянии j, если начальным состоянием было i.

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

где к – количество в ненулевых вероятностей в i-ой строке, без учета элементов в шестом и восьмом столбцах.
 * Вероятность перехода из любого непоглощающего состояния в состояние соответствующее закрытию программы и выполнению запроса writeTag не зависит от исходного состояния:
 * Прочие ненулевые вероятности рассчитываются по формуле:

Построим зависимость минимального среднего арифметического и дисперсии для каждого вида запросов от : Примем вероятность закрытия программы достаточно малой, для определенности будем использовать значение. Моделирование производилось с помощью программного кода Matlab, приведенного в Приложении 1. В результате были получены следующие зависимости:

Рис. 1. Зависимость минимального среднего числа исполнений запросов от.

Рис. 2. Зависимость минимальной дисперсии числа исполнений запросов от.

Данный эксперимент моделирует ситуацию роста количества активных пользователей платформы. По графикам видно, что в таком случае наиболее часто исполняемыми запросами будут запросы writeTag и loadTags.

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

Рис. 3. Зависимость минимального среднего числа исполнений запросов от  при.

Рис. 4. Зависимость минимальной дисперсии числа исполнений запросов от  при.

Рис. 5. Зависимость минимальной дисперсии числа исполнений запросов от  при.

Рис. 6. Зависимость минимальной дисперсии числа исполнений запросов от  при.

По графикам видно, что с уменьшением величины   среднее арифметическое и дисперсия количества выполнения различных запросов уменьшаются, однако при этом запросы loadTags и writeTag остаются наиболее используемыми. Это позволяет сделать вывод о том, что именно эти запросы платформа получает чаще всего.

Тестирование производительности запроса loadTags
Проведем измерение производительности запроса loadTags. Его основной характеристикой будет зависимость времени обработки от количества геотегов в БД -. Поскольку работа системы подвержена влиянию большого количества случайных факторов, то практический интерес представляют следующие характеристики  - минимальное и максимальное время обработки запроса; выборочное среднее и выборочная дисперсия времени обработки запроса. Выборочное среднее и дисперсия рассчитываются по следующим формулам:



где n – размер выборки, – i-ий элемент выборки.

Описание эксперимента
Данный эксперимент состоит из следующих этапов:
 * 1) Очистка БД исследуемой системы;
 * 2) Выполнение m запросов loadTags к системе, сохранение времени выполнения каждого запроса в отдельный файл, соответствующий текущему значению Eqn033.gif ;
 * 3) Выполнение  n запросов writeTag к системе;
 * 4) Если Eqn035.gif то переход к шагу 2, иначе остановка.

Запросы к системе выполняются на том же узле, где работает система. Это необходимо для исключения случайных погрешностей, связанных с задержкой в канале связи. Параметры были выбраны следующим образом n=10000, m=1000, r=54. После окончания эксперимента будет получено r текстовых файлов, каждый из которых содержит n времен обработки запроса loadTags. Тестирование производилось с помощью сценария командной оболочки Bash testLoadTags, исходный код которого приведен в Приложении 2.

Результаты эксперимента
Обработка результатов эксперимента производилась с помощью программы для среды Matlab, приведенной в Приложении 3. Построим графики зависимостей максимального, минимального и среднего времени обработки запроса в зависимости от :

Рис. 7. Зависимость времени обработки запроса loadTags от.

Рис. 8. Зависимость дисперсии времени обработки запроса loadTags от.

По рис. 7. видно, что среднее, максимальное и минимальное время обработки запроса время возрастают с ростом. Кроме того, с ростом   разница между средним и минимальным временем также растет. По рис. 16. видно, что дисперсия времени обработки запроса loadTags также пропорциональна.

Описание эксперимента
Данный эксперимент состоит из следующих этапов:
 * 1) Очистка БД исследуемой системы;
 * 2) Последовательное выполнение запросов writeTag к системе, с сохранением времени выполнения каждого запроса и кода ошибки в файл, до момента, пока в систему не будет добавлено m новых геотегов.

Измерения производятся на одном узле с запущенной платформой для исключения влияния задержки в канале связи. Тестирование производилось с помощью сценария командной оболочки Bash testWriteTag, исходный код которого приведен в Приложении 3. После окончания измерений будет получен файл, содержащий последовательности Номер запроса, Время обработки, Код ошибки.

Результаты эксперимента
Для проведения эксперимента количество добавляемых геотегов было выбрано как m=12000. В результате данного эксперимента был получены следующие зависимости – «Номер запроса – Время обработки», «Номер запроса – код ошибки». С помощью функций пакета Matlab были вычислены интересующие параметры выборки:

Таблица 1. Характеристики производительности запроса writeTag для исходной системы.

По данной таблице можно сделать вывод о том, что время обработки запроса writeTag лежит в широком интервале и обработка каждого десятого запроса сопровождается ошибкой.

Подготовка к измерениям
Для измерения времени работы отдельных участков исходного кода был создан заголовочный файл PerformanceCounter.h (исходный код приведен в Приложении 6) содержащий класс PerformanceCounter. Для фиксации моментов начала и конца выполнения профилируемого участка данный класс использует системный вызов ОС Linux gettimeofday(..), возвращающий текущее время с точностью до микросекунд. Результаты измерений времени работы выводятся в стандартный журнал событий syslog с указанием идентификатора профилируемого участка.

Экземпляр класса PerformanceCounter был размещено в следующих участках исходного кода:
 * в методе process(..) класса DbObjectsCollection, для измерения полного времени генерации ответа на запрос;
 * в каждом из методов класса QueryExecutor, для измерения времени потраченного на взаимодействие с БД.

Результаты профилирования
Эксперимент проводился для каждого из запросов на запись (AddUser, AddChannel, DeleteUser, RegisterUser, SubscribeChannel, WriteTag, UnsubscribeChannel). Каждый запрос выполнялся одинаковое количество раз (в данном эксперименте 20), после чего результаты профилирования извлекались из системного журнала в файл. Для ряда запросов эксперимент был совмещен, например для AddUser и DeleteUser результат выполнения первого запроса использовался для выполнения второго запроса.

Для каждого из запросов было получено два временных ряда – время полной обработки запроса в секундах и время взаимодействия с БД. Для данных временных рядов были вычислены средние значения, их сопоставление можно увидеть на следующем рисунке:

Рис. 9. Результаты профилирования запросов на запись.

Рис. 9 показывает, что практически все время обработки запросов на запись вне зависимости от их типа затрачивается на взаимодействие с БД. Следовательно, увеличения производительности можно добиться либо путем ускорения работы СУБД, либо путем использования отложенной записи в БД.

Оптимизация многопоточной синхронизации
Рассмотрим зависимость времени обработки конкретных запросов writeTag от количества запросов, полученную во время тестирования производительности данного запроса:

Рис. 10. Зависимость времени обработки запроса writeTag от количества выполненных запросов.

По графику видно, что время обработки запроса writeTag можно представить как сумму двух процессов – апериодического и периодического (процесс показан кружками на графике). Периодический процесс характеризуется амплитудой, растущей пропорционально количеству выполненных запросов.

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

Для того чтобы определить какой именно участок кода синхронизации создает задержку, было проведено профилирование синхронизации с БД. С помощью класса PerformanceCounter было произведено измерение длительности работы каждой строчки метода UpdateThread::run. Измерения производились для платформы с большим числом добавленных геотегов для того, чтобы влияние периодического процесса было максимальным.

Результаты профилирования показали, что дольше всего выполняется синхронизация объекта m_dataChannelsMap. Синхронизация представляет собой добавление новых элементов контейнера m_tagsContainer в контейнер m_dataChannelsMap. Ключевым моментом является то, что данный участок кода блокируется полностью, в том числе и для случаев, когда ни одного геотега не будет добавлено в m_dataChannelsMap.

Рис. 11. Алгоритм обновления m_dataChannelsMap: до оптимизации (слева) и после оптимизации (справа).

В качестве решения в исходном коде были сделаны следующие изменения:
 * Убрана блокировка записи в поток во время процесса синхронизации m_dataChannelsMap;
 * Блокировка записи в поток устанавливается только на время записи новых геотегов в m_dataChannelsMap.

Оптимизация структуры БД
В предыдущем разделе было показано, что время выполнения всех запросов изменяющих состояние системы полностью определяется временем выполнения соответствующих им запросов к БД. Рассмотрим, как можно оптимизировать структуру БД для более быстрого выполнения запросов, на примере запроса writeTag.

При обработке запроса writeTag платформа взаимодействует с БД следующим образом. В таблицу tag добавляется подробная информация о геотеге – координаты, время, идентификатор пользователя и ссылка на контент с помощью следующего SQL запроса:

insert into tag (altitude, latitude, longitude, label, description, url, user_id, time, id) values (:altitude,:latitude,:longitude,:label,:description,:url,:user_id,:time,:id);

После успешного выполнения данного запроса, в таблицу tags добавляется запись, связывающая геотег и канал:

insert into tags (tag_id,channel_id) values(:tag_id,:channel_id);

Данные запросы выполняются в рамках одной транзакции, для поддержания целостности данных.

Кроме обработки запроса writeTag, платформа взаимодействует с данными таблицами также в процессе синхронизации с БД. Для обновления информации о геотегах используются два метода – loadTags(…) и updateReflections(…). Первый метод синхронизирует содержимое таблицы tag, второй метод синхронизирует содержимое таблицы tags.

Рассмотрим следующие изменения структуры БД, за счет которых можно ускорить обработку запросов writeTag:
 * Удалить отношение tags;
 * Добавить атрибут channel_id в отношение tag, являющийся внешним ключом по отношению к channel.

Рис. 12. Диаграмма БД до (слева) и после (справа).

Изменения в структуре БД потребуют следующих корректировок в исходном коде:
 * Метод QueryExecutor::insertNewDataMark(…), добавляющий геотег в БД вместо двух SQL запросов будет использовать один запрос следующего вида:

insert into tag (altitude, latitude, longitude, label, description, url, user_id, time, id, channel_id) values(:altitude,:latitude,:longitude,:label,:description,:url,:user_id,:time,:id, :channel_id);


 * Связывание геотегов и каналов в процессе синхронизации будет перемещено из метода UpdateThread::updateReflections(…) в метод UpdateThread::loadTags(…), так как данная информация будет храниться в таблице tag.

Данные изменения ускорят обработку запроса writeTag за счет выполнения только одного SQL запроса вместо двух, и обработку прочих запросов за счет того, что синхронизация геотегов потребует выполнения меньшего количества запросов к БД.

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

Для принятия решения о необходимости проведения синхронизации будем вести учет количества выполненных платформой SQL-запросов, изменяющих содержимое таблиц (INSERT,DELETE,UPDATE). Решение о необходимости синхронизации будет приниматься путем сравнения счетчика платформы и счетчика запросов, который ведет сама СУБД PostgreSQL. Статистика СУБД доступна через служебное представление pg_stat_database [20], предоставляющее информацию о количестве транзакций выполненных для каждой БД.

Алгоритм принятия решений будет иметь следующий вид: Данная проверка проводится с задаваемой периодичностью (DB_SYNC_INTERVAL).
 * 1) Выборка числа транзакций из представления pg_stat_database;
 * 2) Вычисление разницы (m_diff) между полученным значением (factTransactionCount) и счетчиком платформы (m_transactionCount);
 * 3) Если m_diff превышает наперед заданное значение из конфигурационного файла (TRANSACTION_DIFF), то  и производится синхронизация;
 * 4) Иначе синхронизация не производится.

Рис. 13. Алгоритм принятия решения о начале синхронизации с БД.

Проверка необходимости синхронизации позволяет существенно снизить использование процессора и как следствие – повысить скорость обработки запросов платформой. Параметры TRANSACTION_DIFF и DB_SYNC_INTERVAL позволяют регулировать отношение «производительность/актуальность данных» для платформы – небольшой интервал DB_SYNC_INTERVAL и нулевое значение TRANSACTION_DIFF сделает синхронизацию более частой и за счет этого снизит производительность, но при этом данные в памяти будут всегда актуальны. Альтернативная конфигурация, когда DB_SYNC_INTERVAL и TRANSACTION_DIFF имеют большие значения, соответствует ситуации, когда данные платформы не являются критически важными и их актуальностью можно пожертвовать в пользу производительности.

Сравнение результатов для запроса loadTags
Проведем эксперимент по измерению производительности запроса loadTags для оптимизированной системы аналогично описанному в разделе 1.2. Результатом данного эксперимента будут графики зависимостей времени обработки запроса и его дисперсии от количества геотегов в БД.

Рис. 14. Зависимость времени обработки запроса loadTags от для оптимизированной системы.

Для оценки изменения производительности, построим графики невязки показателей производительности исходной системы относительно системы после оптимизации:

Рис. 15. Невязка максимального времени обработки запроса для различных значений.

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

Рис. 16. Невязка среднего времени обработки запроса для различных значений.

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

Рис. 17. Невязка минимального времени обработки запроса для различных значений.

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

На основе результатов численных экспериментов можно сделать вывод о частичном увеличении производительности обработки запроса loadTags.

Сравнение результатов для запроса writeTag
Для того чтобы оценить прирост производительности при обработке запроса writeTag проведем эксперимент описанный в разделе 1.3 для оптимизированной системы.

Таблица 2. Сравнение характеристик производительности запроса writeTag для исходной и оптимизированной системы.

Данное сравнение показывает увеличение производительности и надежности обработки запроса writeTag относительно исходной системы – среднее время обработки запроса уменьшилось на 45.5%, дисперсия времени обработки уменьшилась на три порядка, максимальное время обработки уменьшилось на порядок, число ошибок стало нулевым.

Для того чтобы иметь представление о наиболее вероятных значениях времени обработки данного запроса сравним выборочные функции распределений [27] для обеих систем. Построение производилось с помощью функции ecdf пакета Matlab.

Рис. 18. Выборочная функция распределения времени обработки запроса writeTag для оптимизированной и не оптимизированной системы.

На графиках черными точками показаны границы интервалов, в которых лежит 90% и 95% точек выборки для обеих систем. Видно, что для этих уровней разница между показателями систем до и после оптимизации составляет 17 мс в пользу оптимизированной системы. Следовательно, наиболее вероятные значения времени выполнения запроса в оптимизированной системе ограничены меньшим значением времени, чем для исходной системы.

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

Масштабирование обработки запросов
Используемый платформой веб-сервер lighttpd содержит встроенный балансировщик нагрузки для FastCGI приложений[21]. Он позволяет равномерно распределять поступающие запросы между экземплярами управляющей программы. Управляющая программа может быть запущена локально или на удаленных серверах, так как спецификация FastCGI позволяет приложению взаимодействовать с веб-сервером, используя сетевое соединение[8].

Для принятия решения о том, какой экземпляр приложения должен обработать поступивший запрос, используется следующий алгоритм: , где IP, port, unix-socket – указывают узел, на котором запущен экземпляр приложения; is-local – указание на то, что приложение запущено локально; state – текущее состояние экземпляра; load – количество запросов, которые обрабатываются экземпляром приложения в данный момент;
 * 1) После запуска веб-сервера формируется список, состоящий из следующих записей:
 * 1) При поступлении HTTP-запроса адресованного FastCGI-приложению:
 * 2) Веб-сервер находит в списке запись с наименьшим значением поля load и перенаправляет запрос приложению, указанному в записи;
 * 3) Значение load увеличивается на единицу для данной записи, список сортируется по полю load;
 * 4) После того как обработка запроса завершена, веб-сервер уменьшает load на единицу для ранее выбранного узла и повторно сортирует список по полю load.

Список серверов, на которых запущены экземпляры приложения, хранится в конфигурационном файле приложения. Возможна «горячая» (без остановки сервера) замена конфигурационного файла. Для запуска экземпляра приложения на узле без веб-сервера используется утилита с открытым исходным кодом spawn-fcgi.

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

Масштабирование СУБД PostgreSQL
В предыдущих разделах было показано, что взаимодействие с СУБД является узким местом приложения. Горизонтальное масштабирование позволяет ускорить обработку SQL запросов платформы и повысить пропускную способность СУБД.

В случае запуска в кластере, СУБД имеет следующую архитектуру. На каждом узле кластера расположена копия БД, называемая репликой. Запросы к СУБД поступают на выделенный узел или несколько узлов, занимающихся координацией выполнения запросов. Запросы на чтение адресуются одной из реплик, запросы на запись могут адресоваться одной или нескольким репликам. В первом случае возникает необходимость репликации – распространения изменений на другие узлы. Рассмотрим два основных вида репликации – синхронная и асинхронная репликация [22].

Синхронная репликация – транзакция считается успешной, если она успешно завершилась на всех репликах [23]. Данный тип репликации гарантирует наличие только одной версии данных, однако его отличает сравнительно высокая задержка, связанная с применением изменений на всех репликах.

Асинхронная репликация – транзакция считается успешной, если она завершилась успешно на реплике, которой адресовал запрос балансировщик нагрузки. После того, как результат первой транзакции доставлен пользователю, изменения распространяются на остальные реплики. Данный тип репликации характеризуется высоким быстродействием, однако имеет меньшую надежность – в промежуток времени между отправкой ответа пользователю и выполнением транзакции на всех репликах в системе, возможно существование двух версий данных.

При распределенной архитектуре БД время обработки снижается не только благодаря балансировке нагрузки, но и за счет использования различных технических  приемов. Рассмотрим подробнее два из них - разделение запросов (Query Partitioning) и использование пула соединений (Connection Pooling).

Разделение запросов представляет собой деление запроса на подзапросы, которые выполняются параллельно на разных репликах БД, после чего объединенные результаты выполнения подзапросов возвращаются пользователю.

Пул соединений представляет собой набор предварительно открытых соединений с СУБД, предоставляемых по требованию пользователю. Это позволяет добиться выигрыша по времени, если соединения открываются очень часто.

В [23-25] приведено сравнение различных инструментов для горизонтального масштабирования СУБД PostgreSQL. Наиболее подходящим к специфике решаемой задачи является pgpool-II, так как он включает в себя все три способа увеличения пропускной способности БД (балансировка нагрузки, пул соединений, разделение запросов) и обеспечивает синхронную репликацию, благодаря которой повышается доступность данных [24]. Данное решение работает как связующее ПО (middleware). Веб-приложение связывается с pgpool-II через интерфейсы взаимодействия с сервером СУБД и со стороны приложения взаимодействие ничем не отличается от взаимодействия с настоящим сервером PostgreSQL. В свою очередь pgpool-II подключается к серверам СУБД и взаимодействует с ними, используя клиентские интерфейсы.

Поскольку взаимодействие с pgpool-II является прозрачным на всех этапах, то исходный код управляющей программы не требует изменений, а это означает, что горизонтальное масштабирование СУБД PostgreSQL требует только настройки самой СУБД и pgpool-II.

Использование noSQL баз данных
Кроме рассмотренных в предыдущем разделе средств репликации СУБД PostgreSQL существуют также и другие решения для горизонтального масштабирования СУБД в распределенных системах. В данном разделе будут рассмотрен класс СУБД, ставший популярным в последнее время – noSQL СУБД. Под термином noSQL подразумевается СУБД с нереляционной моделью данных, открытым исходным кодом и практически линейной горизонтальной масштабируемостью [25].

Рассмотрим в качестве примера noSQL СУБД Apache Cassandra. Данное решение обеспечивает хранение данных в виде семейств столбцов. К достоинствам данной СУБД можно отнести:
 * Линейная масштабируемость – производительность растет линейно с ростом числа узлов;
 * Повышенная устойчивость к сбоям – данные автоматически реплицируются на все узлы кластера;
 * Все узлы равноправны – система будет работать, пока доступен хотя бы один узел кластера;
 * Добавление узлов и установка обновлений системы без перезапуска СУБД или каких-либо дополнительных действий пользователя;
 * Настраиваемые стратегии репликации;
 * Настраиваемая производительность – настройки производительности для каждой из операций манипуляции данными.

Рассмотрим также последовательность действий по переходу LBS-платформы на использование Apache Cassandra:
 * Разработка и тестирование структуры БД с учетом особенностей используемой СУБД;
 * Изменение классов, взаимодействующих с БД (QueryExecutor и UpdateThread);
 * Тестирование и отладка всех запросов платформы;
 * Изменение и проверка процедур развертывания платформы.

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

Теоретические оценки улучшения производительности при горизонтальном масштабировании
Постановка задачи: построить математическую модель, связывающую пропускную способность горизонтально масштабированной LBS-платформы c интенсивностью работы отдельных узлов, интенсивностью поступающих запросов и числом узлов. Пропускная способность (bandwidth) – количество запросов обработанных в единицу времени. Решение: Рассмотрим модель работы LBS-платформы как системы массового обслуживания с простейшим потоком событий и бесконечной очередью. В начале, рассмотрим модель системы до применения горизонтального масштабирования (скалярная система). Будем считать, что запущен только один экземпляр управляющей программы, и он получает запросы напрямую от веб-сервера:

Рис. 19. Модель LBS-платформы в классе систем массового обслуживания.

В данном случае λ – интенсивность входного простейшего потока событий (запросов протокола Geo2Tag), µ – интенсивность обработки поступающих запросов. Для данного типа систем среднее время нахождения заявки в системе вычисляется по формуле [26]:



Теперь рассмотрим модель системы, использующей балансировку нагрузки. В данном случае поток запросов от веб-серевера поступает сначала в балансировщик нагрузки, который перенаправляет его кластеру из m серверов с постоянной задержкой, на каждом из которых запущена управляющая программа. Узлы кластера обрабатывают запросы и возвращают результат обработки веб-серверу.

Рис. 20. Модель LBS-платформы, использующей балансировку нагрузки, в классе систем массового обслуживания.

Первый блок представляет модель балансировщика нагрузки как линии задержки (время задержки dt), λ – интенсивность входного простейшего потока событий (запросов протокола Geo2Tag).

Второй блок представляет модель кластера из m обработчиков запросов в классе систем массового обслуживания M/M/m. Параметры: λ  –  интенсивность входного потока событий, формируемого балансировщиком нагрузки; µ – интенсивность обработки запросов одним экземпляром управляющей программы. Для подобной системы среднее время нахождения заявки в кластере находится по следующей формуле [27]:



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

Из формулы (1.9) следует, что среднее время обработки запроса кластером ограничено снизу величиной , то есть даже при низкой интенсивности поступающих запросов каждый запрос не может быть обработан кластером быстрее, чем в случае скалярной системы.

Общее время пребывания запросов в системе будет складываться из задержки, создаваемой балансировщиком нагрузки, и времени  обработки запроса:



Формула (1.10) показывает, что нижняя оценка времени обработки одного запроса системой с балансировкой нагрузки складывается из быстродействия балансировщика нагрузки и отдельного узла кластера.

Проведем численный эксперимент для определения того, как увеличение пропускной способности при использовании балансировки нагрузки зависит от числа параллельно работающих серверов. Пропускная способность обоих систем – величина, обратная среднему времени обработки запроса для каждой из них:



Увеличение пропускной способности при использовании балансировки нагрузки относительно скалярной системы будет определяться следующим образом:



Для определенности выберем неизменяемые параметры обоих систем следующими:



Будем рассматривать следующие значения количества узлов в кластере балансировки нагрузки –. Вычисления и построения графиков производились с помощью программного кода для среды Matlab, изложенного в Приложении 5. Полученный график для данного набора параметров:

Рис. 21. Увеличение пропускной способности системы при различных значениях интенсивности потока запросов и количества параллельно работающих узлов и dt=0,001.

По графику можно сделать следующие выводы: Рассмотрим, как изменится зависимость прироста пропускной способности, если увеличить значение задержки в балансировщике нагрузки до dt=0,01.
 * Эффект от распараллеливания ограничен, начиная с некоторого числа узлов дальнейшее увеличение их количества не даст увеличения пропускной способности;
 * Увеличение пропускной способности зависит от интенсивности запросов, для низких интенсивностей наблюдается снижение пропускной способности.

Рис. 22. Увеличение пропускной способности системы при различных значениях интенсивности потока запросов и количества параллельно работающих узлов и dt=0,01.

Рассмотрим также случай, когда балансировщик работает с такой скоростью, что его задержку можно положить равной нулю:

Рис. 23. Увеличение пропускной способности системы при различных значениях интенсивности потока запросов и количества параллельно работающих узлов и dt=0,0.

Сравнивая рисунки 21-23 видно, что величина задержки в балансировщике нагрузки снижает максимальный эффект от распараллеливания обработки запросов. Кроме того, даже в случае идеальной параллельной системы (если балансировщик работает мгновенно), прирост пропускной способности системы также будет ограничен.

Рассмотрим пропускную способность системы как функцию интенсивности входного потока. Будем исследовать систему со следующими параметрами:



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



Результат моделирования:

Рис. 24. Пропускная способность системы при различных значениях интенсивности потока запросов.

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

Заключение
В результате выполнения выпускной работы бакалавра были решены следующие задачи и достигнуты результаты:
 * Исследованы методы оптимизации производительности ПО;
 * Составлена математическая модель клиентского приложения LBS-платформы, с помощью численного эксперимента определены наиболее часто используемые запросы LBS-платформы;
 * Измерена производительность обработки запросов LBS-платформой;
 * Составлены требования к улучшению производительности LBS-платформы;
 * Произведена оптимизация производительности LBS-платформы;
 * Проведено сравнение показателей производительности исходной и оптимизированной LBS-платформы, показано улучшение показателей для оптимизированной системы;
 * Исследованы методы балансировки нагрузки для LBS-платформы и используемой ей СУБД;
 * Сформированы рекомендации для горизонтального масштабирования LBS-платформы;
 * Составлена математическая модель производительности LBS-платформы, использующей балансировку нагрузки.

Это позволяет сделать вывод, что была выполнена основная цель данной работы – разработаны методы оптимизации производительности и балансировки нагрузки LBS-платформы.

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

Литература

 * 1) World GPS Market Forecast to 2013 // Research and markets - Market Research Reports. URL: http://www.researchandmarkets.com/reports/836704/world_gps_market_forecast_to_2013
 * 2) GPS Accuracy // Official U.S. Government information about  the global positioning system (GPS). URL: http://www.gps.gov/systems/gps/performance/accuracy/
 * 3) Geo2Tag // Geo2Tag – Open Source Location Services Platform. URL: http://geo2tag.org/
 * 4) André, B. Bondi Characteristics of scalability and their impact on performance // Proceedings of the 2nd international workshop on Software and performance, Ottawa, Ontario, Canada, 2000, ISBN 1-58113-195-X, P.  195–203.
 * 5) Виды Тестирования Программного Обеспечения // Про Тестинг . URL: http://www.protesting.ru/testing/testtypes.html
 * 6) Профилировка программ // Техника оптимизации программ, Эффективное использование памяти. URL: http://citforum.ru/book/optimize/chapter1.shtml
 * 7) Касьянов, В. Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. — 336 с.
 * 8) FastCGI // FastCGI. URL: http://www.fastcgi.com/
 * 9) Алексеев В. Б. От метода Карацубы для быстрого умножения чисел к быстрым алгоритмам для дискретных функций // Тр. МИАН. — 1997. — Т. 218. — С. 20–27
 * 10) Bloom, Burton H. Space/time trade-offs in hash coding with allowable errors // Communications of the ACM Т. 13 (7)  —  1970 — P. 422–426.
 * 11) Amdahl, Gene (1967). "Validity of the Single Processor Approach to Achieving Large-Scale Computing Capabilities". AFIPS Conference Proceedings (30): 483–485.
 * 12) Дейт, К. Дж.  Введение в системы баз данных  — 7-е изд. — М.: Вильямс, 2001. — С. 1072. — ISBN 5-8459-0138-3
 * 13) HTTP // Википедия – свободная энциклопедия. URL: http://ru.wikipedia.org/wiki/HTTP/
 * 14) QtSql Module // Qt Developer Network. URL: http://qt-project.org/doc/qt-4.8/qtsql.html
 * 15) JSON // [сайт стандарта]. URL: http://www.json.org/
 * 16) OSLL/Geo2Tag // Github. URL: https://github.com/OSLL/geo2tag
 * 17) [Abstract, Demo] I. Bezyazuchnyy, K.Krinkin Geo2tag client: Doctor Search / The 11th Conference of Open Innovations Association FRUCT. Saint-Petersburg, Russia 23-27 April 2012
 * 18) R. Dorohova, S. Kassaye ThereAndHere Project / The 11th Conference of Open Innovations Association FRUCT. Saint-Petersburg, Russia 23-27 April 2012
 * 19) MAN gettimeofday (2) // Проект OpenNet. URL: http://www.opennet.ru/man.shtml?topic=gettimeofday&category=2&russian=0
 * 20) Documentation // PostgreSQL documentation. URL: http://www.postgresql.org/docs/8.3/static/monitoring-stats.html
 * 21) ModFastCGI // Lighttpd –lighty labs. URL: http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModFastCGI
 * 22) Shui Yu, Wanlei Zhou  A Novel Middleware Based Web Database Model // Proceedings of the IEEE/WIC/ACM International Conference on Web Intelligence (WI’04)
 * 23) J. Salas, R. Jim´enez-Peris, M. Pati˜no-Mart´ınez « Lightweight Reflection for Middleware-based Database Replication» 25th IEEE Symposium on Reliable Distributed Systems (SRDS'06)
 * 24) Zhiyuan Shao, Hai Jin « Middleware Based High Performance and High Available Database Cluster» Proceedings of the Fifth International Conference on Grid and Cooperative Computing (GCC'06)
 * 25) L´asaro Camargos, Fernando Pedone, Alex Pilchin, Marcin Wieloch « On-Demand Recovery in Middleware Storage Systems» 2010 29th IEEE International Symposium on Reliable Distributed Systems
 * 26) Replication, Clustering, and Connection Pooling // PostgreSQL Wiki. URL: http://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling
 * 27) Bourke, Tony Server Load Balancing. —   O'Reilly, 2001 —  194 p.,  ISBN 0-596-00050-2
 * 28) Pgpool wiki // Pgpool. URL: http://www.pgpool.net/
 * 29) NOSQL Database. URL: http://nosql-database.org/
 * 30) Козлов В.Н., Кисоржевский В.Ф. Теория информационных систем. Учебное пособие. СПб.: Издательство Политехнического ун-та 2008. 464 с.
 * 31) Клейнрок Л. Теория массового обслуживания. — М.: Машиностроение, 1979. — С. 432.
 * 32) Sedgewick, R. Algorithms // Addison-Wesley, 1st ed.  —  1983. ISBN 0-201-06672-6.