MyDataSpace задумывался как универсальный облачная платформа для небольших проектов. Со временем мы сосредоточили внимание на публикации открытых данных.
Ниже описан процесс развития сервиса с технической стороны.
Версия 1
Изначально сервис состоял из NodeJS-сервера и нескольких серверов MySQL (1 мастер и несколько репликаций).
Картинки раздавались NGINX'ом и кешировались Cloudfare'ом для быстрой доставки (CDN).
Версия 2
Когда одного мастера стало не хватать, мы разделили данные на несколько серверов по принципу описанному в этой статье.
Версия 3
Потом мы добавили возможность выполнять пользовательский код (JavaScript) на серверной стороне. Но не как вздумается пользователю, а по расписанию: раз в час, раз в сутки, раз в неделю и раз в месяц. Длительность выполнения скрипта ограничена несколькими минутами. Если скрипт не успевает выполниться, он прерывается с ошибкой.
Версия 4
Изначально полнотекстовый поиск был реализован средствами MySQL. Но с увеличением количества данных, стало понято что MySQL не справляется. И мы перевели его на ElasticSearch. Заодно добавили фасеты, Geohash, фильтрацию по гео-координатам и многое другое на базе ElasticSearch.
Версия 5
Как было сказано в начале, в определенный момент мы сосредоточились на открытых данных. Для того чтобы проще было импортировать существующие данные из разных государственных источников, мы интегрировали OpenRefine. OpenRefine позволяет импортировать файлы XLS, XLSX, CSV, XML, JSON и файлы многих других форматов.
Версия 6
У нас оставалось 1 узкое горлышко в виде сервера NodeJS. Сервер был один с несколькими процессами NodeJS. Процессы обменивались между собой событиями об изменении данных. Для этого использовался встроенный NodeJS'овский механизм. По-этому нельзя было просто разнести процессы на несколько серверов.
Для того чтобы решить эту проблему, мы разделили наше серверное приложение на 2:
- Webserver — принимает запросы пользователя через HTTP и удерживают подключения по WebSocket.
- Accessor — принимают запросы от Webserver, осуществляет доступ к данным и отправляют им уведомления в случае изменения данных.
Accessor'ы не взаимодействуют между собой, а только с Webserver'ами. Webserver'ы выступают как прокси и просто перенаправляют запросы на Accessor'ы. Те в свою очередь делают всю работу и отправляют результат Webserver'ам.
Accessor'ы, так как они stateless, легко масштабируются путем добавления/убавления серверов.
Webserver'а же статичны, но так как нагрузка на них незначительна, то это не влияет на масштабируемость.