Постановка задачи
Задача состоит в том, чтобы доработать существующую систему таким образом, чтобы ее было возможно масштабировать путем наращивания аппаратной части (грубо говоря добавляя в стойку новые сервера и делая минимальные настройки). При этом необходимо решить задачу организации доступа к базе данных системы, учитывая требования к безопасности. В итоге требуется решить следующие задачи:
добавить в систему возможность параллельных вычислений характеристик социальных сетей;
разработать протокол обмена данными и управления задачами;
разработать способ организации доступа к базе данных с большого количества вычислительных машин, в перспективе географически удаленных друг от друга.
Использование потоков (threads)
Как уже было сказано, обработка изменений модели социальной сети требует большого количества сложных вычислений. Для того чтобы уменьшить время, необходимое для вычислений было решено производить вычисления параллельно. С этой целью уже проанализированы следующие варианты решений: использование нитей (threads) и использование MPI.
Использование нитей дало возможность на полную мощность использовать многопроцессорные системы (т.е. программа делится на несколько независимых потоков, и каждый поток обрабатывается на одном процессоре или ядре процессора).
Для создания многопоточных программ в языке Python предусмотрен модуль threading. Его класс Thread может быть унаследован (subclassed) для создания потока или нескольких потоков. Метод run должен содержать код, который вы желаете выполнить при выполнении потока. Пример:
import threading
class MyThread(threading.Thread):
def run(self):
print ´Thread executing started´
print ´Thread executing completed´
MyThread().start()
Использование MPI
MPI позволяет достаточно просто реализовать параллельные вычисления на любом количестве машин (при этом требуется что бы во время вычисления машины всегда были доступны). Логика работы программы основанной на MPI аналогична логике работы программы с использованием нитей (потоков). Основное отличие состоит в том, что MPI программы могут выполняться на нескольких машинах. То есть MPI программы распараллелены на несколько машин.
При запуске задачи создается группа из P процессов. Группа идентифицируется целочисленным дескриптором (коммуникатором). Внутри группы процессы нумеруются от 0 до P-1. В ходе решения задачи исходная группа (ей присвоено имя MPI_COMM_WORLD) может делиться на подгруппы, подгруппы могут объединяться в новую группу, имеющую свой коммуникатор. Таким образом, процесс имеет возможность одновременно принадлежать нескольким группам процессов. Каждому процессу доступен свой номер myProc внутри любой группы, членом которой он является.
Поведение всех процессов описывается одной и той же программой. Межпроцессные коммуникации в ней программируются явно с использованием библиотеки MPI, которая и диктует стандарт программирования. Квазиодновременный запуск исходной группы процессов производится средствами операционной системы. При этом P определяется желанием пользователя, а отнюдь не количеством доступных процессоров (или узлов кластера).
Итак, все P процессов асинхронно выполняют одну и ту же программу. Но у каждого из них свой номер myProc.
Поэтому в программе, естественно, будут такие фрагменты:
if (myProc.eq.0) then
< делать что-то одно >
else if (myProc.eq.1) then
< делать что-то другое >
. . .
else
< делать что-то P-e >
endif
Таким образом, в программе "под одной крышей" закодировано поведение всех процессов. В этом и заключена парадигма программирования Single Program - Multiple Data (SPMD).
Обычно поведение процессов одинаково для всех, кроме одного, который выполняет координирующие функции, не отказываясь, впрочем, взять на себя и часть общей работы. В качестве координатора обычно выбирают процесс с номером 0.
Протокол обмена данными и управления задачами
Как уже было отмечено, MPI предоставляет только низкоуровневые инструменты. Это значит, что разработка высокоуровневых инструментов и протоколов ложится на программиста. В нашем случае необходимо разработать протокол обмена данным между узлами, который должен решать следующие задачи:
передачу заданий вычислительным узлам;
передачу управляющих сигналов узлам (перезапустить вычисления, остановить вычисления);
передачу статуса задания управляющему узлу (задание выполняется, задание выполнено, произошла ошибка).
Протокол управления задачами должен обеспечивать следующие возможности:
распределение задач между узлам, в зависимости от их загрузки;
распределение подзадач с учетом зависимости характеристик;
перераспределение задач, на освободившиеся узлы.
Второй пункт требований особенно сложный, потому что требует анализа имеющихся зависимостей характеристик. Сложность заключается в необходимости доработки (или даже правильнее сказать разработки с нуля) существующей системы учета зависимостей. В качестве решения предлагается хранить информацию о зависимостях не в декораторе функции, а базе данных. Сейчас там хранятся такие данные как название характеристики, функция, которая данную характеристику вычисляет. Там же можно хранить и зависимости. Этот подход предполагает большую гибкость, потому что нет необходимости вносить правки в исходные коды системы на этапе отладки новых функций.
Использование SSH туннеля
Ввиду того, что программа становится распределённой, доступ к базе данных и передача обрабатываемых данных осуществляется по изначально не защищённым каналам связи. Это, в свою очередь, противоречит требованиям безопасности систем работающих с личной информацией.
Для решения задачи безопасной передачи данных по сети, была рассмотрена возможность доступа к БД через SSH туннель. Принципиальная схема работы этой связки такова:
создаётся SSH туннель с авторизацией по ключу
по средствам SSH клиента делается перенаправление порта, используемого для доступа к серверу БД, через ССХ туннель (это, например, позволяет OpenSSH клиент под Linux)
в обычном режиме (как при работе с локальной СУБД) передаются запросы и возвращаются ответы на них. SSH клиент сам шифрует данные и передаёт их на удалённый узел
В результате такого подхода обеспечивается шифрование данных с помощью RSA ключа. Этого достаточно, для обеспечения безопасности передаваемых данных, однако требует использования SSH клиента.
В рамках того же метода, был рассмотрен и другой подход. Его суть заключается в наследовании стандартного API доступа к БД, добавления к нему функций передачи сформированных запросов через SSH туннель. Такой подход не требует запуска сторонних SSH клиентов, однако требует изменения имеющейся ORM прослойки, использующейся для доступа к БД. Такой подход делает разрабатываемое приложение самодостаточным, и легко переносимым на другие ОС, для которых реализован интерпретатор Python.
Использование VPN для доступа к БД
Альтернативным способом доступа к БД, является создание VPN соединения с сервером баз данных. Для этого на сервера БД устанавливается и настраивается VPN (PPTP) сервер (ppp если платформой сервера БД является Linux; для поддержки Win клиентов без дополнительных настроек клиентских машин, необходимо также настроить поддержку Microsoft Point-to-Point Encryption - MPPE[1]).
На каждом клиенте также придётся прибегнуть к установке дополнительного ПО, однако этот канал будет более универсальным. Так, весь обмен данными между узлами кластера может осуществляться по этой безопасной сети, и, следовательно, весь обмен будет зашифрован.
Кластерная СУБД
При использовании распределённых вычислений, возникает вопрос о нагрузках на базу данных. Количество запросов в распределённой системе растёт пропорционально количеству вычислительных узлов, и для одного сервера БД эта нагрузка окажется критической при увеличении числа вычислительных узлов. Выбор решения, для данной задачи, должны удовлетворять следующим дополнительным требованиям:
На базе MySQL между существуют два решения: использование репликаций и кластерная версия СУБД.
Схема СУБД с использованием репликаций подразумевает, что имеется несколько серверов, каждый из которых называется Slave, кроме одного - Master. На каждом slave узле сети имеется репликация БД узла master. В рамках решаемой задачи, можно использовать slave узлы для доступа к БД и снижения нагрузки. Следует учесть, что использовать придётся InnoDB engine для таблиц базы данных. Однако даже это не гарантирует, что данные будут идентичными в разных репликациях. Этот недостаток, исключает возможность использования реплицируемой версии для распределённых вычислений с доступом различных вычислителей к различным репликациям. (Всё это обусловлено тем, что реплицируемая версия СУБД разрабатывалась под другого рода требования, такие как отказоустойчивость СУБД или большая территориальная распределённость).
Кластерное решение на базе MySQL является отказоустойчивым, избыточным и масштабируемым решением для баз данных. Использование такой схемы позволяет достигнуть высокой надежности.
Узлы хранилища (ndb узлы) также являются API узлами (то есть предоставляют доступ приложения для доступа к БД при непосредственном к ним обращении), но узел API (api-1) не является хранилищем. Api-1 - полноправный член кластера, но он не хранит никаких данных кластера и его состояние (работает/не работает) не затрагивает целостность или доступность данных. Этот узел можно назвать "клиентом" кластера.
В случае отказа любого из узлов кластера, переключение на другой узел кластера выполняет сама обращающаяся программа (а не MySQL сервер).
Преимущество же над реплицируемой версией СУБД заключается в том, что изменения базы в кластерной версии на всех узлах происходит синхронно, и даже при выходе из строя одного из ndb-узлов, можно быть уверенным, что на других узлах доступна та же самая копия БД. В дополнении к этому, запросы с разных вычислительных узлов могут высылаться на отдельный узел кластерной БД для распределения нагрузки.
Следует, однако, учесть, что кластерная версия MySQL на данный момент доступна не под все платформы
Заключение
В ходе работы были исследованы два способа создания параллельных программ. Выявлены их преимущества и недостатки. Выработаны направления доработки существующей системы и решена задача ее масштабирования, путем наращивания аппаратной части. Была решена проблема доступа к базе данных, путем развертывания VPN соединения между узлами кластера. Так же было предложено использовать кластерную версию СУБД MySQL. Использование кластерной версии СУБД в будущем даст возможность наращивать быстродействие БД путем добавления новых узлов к кластер.