Giter VIP home page Giter VIP logo

karma8-http-file-storage-service's Introduction

Karma8-http-file-storage-service

Software License

Решение тестового задания. [В процессе разработки]

Задача

Вы разрабатываете сервис хранения файлов.

На сервер по HTTP PUT присылают файл, его надо разрезать на 5 равных частей и сохранить на 5 серверах хранения. При запросе HTTP GET нужно достать куски, склеить и отдать файл.

Имеем следующее

  • Один сервер для HTTP-запросов
  • Несколько серверов (>5) для хранения кусков файлов

Ограничения

  • Реализовать тестовый модуль для сервиса, который обеспечит проверку его функционала
  • Сервера для хранения могут добавляться в систему в любой момент, но не могут удаляться из системы
  • Предусмотреть равномерное заполнение серверов хранения
  • Можно задавать вопросы и уточнять условия задачи
  • Код разместить в Github
  • Код может быть несовершенным — нам важно понять образ вашего мышления и подходов к решению задачи

Проработка решения

Термины, определения и сокращения

Inode - индексный дескриптор, который хранит метаданные о файлах, каталогах и других объектах файловой системы. В рамках файловой системы существует ограниченное количество inode.

UUID (англ. universally unique identifier) - универсальный уникальный идентификатор.

Архитектурный скетч

karma8-http-file-storate-service-v1.drawio.svg

Сервисы

Сервис Описание
karma8 gw Принимает запросы от пользователей, проверяет доступ и делит файлы на части. При запросе файла собирает файл из частей полученных от сервиса karma8 storage
karma8 discovery Хранит мета-информацию о файлах, список активных серверов хранения и пространства для хранения файлов
karma8 storage Хранит части файлов. Ничего не знает про содержимое файлов. Ничего не знает о других частях файла.

Note

Сервис karma8 discovery добавлен по следующим соображениям:

  1. Более строгое разделение задач между сервисами
  2. Облегчение сервиса karma8 gw
  3. Возможность работы с сервисом karma8 discovery внутри более защищённого периметра для сервисных задач (таких как регистрация новых инстансов сервиса karma8 storage)

Сервис Karma8 Gateway

  • Принимает запросы от пользователя
  • Проверяет доступ на чтение файла во время запроса клиента (опционально)
  • Проверяет доступ на запись файла во время запроса клиента (опционально)
  • Делит входящие файлы на части для последующего сохранения в инстансах сервиса karma8 storage
  • При запросе собирает файл из частей доступных на инстансах сервиса karma8 storage

Note

Сервис не содержит реализации проверки прав доступа через IAM (Identity and Access Management), но для примера содержит пример доступности namespaces и files для доступа пользователям.

Команда для запуска

karma8 gw --config=./config.yml

Команда для получения справки

karma8 gw --help

Правила разделения данных по нескольким серверам

Engine Описание
raid0 Чередование серверов хранения
raid1 Зеркалирование серверов хранения

Алгоритм при использовании raid0

Система источник Система получатель Описание действия
1 Клиент karma8 gw Пользователь подключился к серверу по HTTP, передал заголовки и начал отправку файла
2 karma8 gw karma8 discovery GW сервис запросил информацию о пространстве для хранения файла, если пространство отсутствует или выключено - возвращает ошибку пользователю
3 karma8 gw karma8 discovery GW сервис зарегистрировал новый файл, получив в ответ список серверов для хранения (порядок серверов важен)
4 karma8 gw karma8 discovery GW сервис получил информацию о тех серверах хранения к которым ещё не подключен
5 karma8 gw karma8 storage's GW сервис подключился к серверам хранения (или переиспользовал ранее созданные соединения)
6 karma8 gw karma8 storage's GW сервис сформировал io.Writer (на основе engine.Raid0 ссылающегося на список соединений с серверами хранения) и начал копировать в него файл
7 karma8 storage file system Сервис хранения запишет поток данных в файл по адресу %namespace%/%name% где %name% это uid файла из базы данных karma8 discovery

Что произойдёт если сервер хранения не сможет сохранить свою часть файла

  • Сервис karma8 storage вернёт ошибку записи
  • Сервис karma8 gw не отметит файл в karma8 discovery как закачанным полностью
  • Сервис karma8 gw вернёт ошибку пользователю

Что произойдёт если все сервера хранения смогут корректно записать свои части файла

  • Сервисы karma8 storage вернут nil сервису karma8 gw
  • Сервис karma8 gw дождётся ответа от всех сервисов karma8 storage и пометит файл как полностью записанным путём отправки события в сервис karma8 discovery
  • Сервис karma8 discovery проставит дату финализации файла в своей базе данных
  • Пользователь получит в качестве ответа от сервиса nil

Сервис Karma8 Discovery

  • Хранит мета-информацию о файлах и их частях
  • Хранит перечень серверов хранения
  • Хранит информацию о пространствах пользователя

Note

Namespace выступают в качестве примера. В реальном продакшине вы, вероятно, захотите добавить такие объекты как customer, project и прочие, здесь же считаем что один customer это один namespace.

Команда для запуска

karma8 discovery --config=./config.yml

Команда для получения справки

karma8 discovery --help

Сервис Karma8 Storage

  • Хранит части файлов
  • Ничего не знает о содержании файлов и алгоритме их разделения на части
  • За хранение информации о том как файл был разделён и где находятся остальные части отвечает другой сервис - ]karma8 discovery]

Команда для запуска

karma8 storage --config=./config.yml

Команда для получения справки

karma8 storage --help

Проблемы при хранении файлов

Сервис хранения файлов имеет следующую специфику:

  • Огромное количество файлов
  • Часто файлы не одинакового размера, либо слишком маленькие (меньше одного блока) или очень большие
  • Заранее не известно какой размер файлов будет самым востребованным

В связи с этим надо отдельно поговорить о том как файлы будут храниться.

Простое решение - хранить каждый файл в отдельности.

Это приведёт к следующим проблемам:

  • Ошибка "No space left on device" когда количество задействованных inode для описания файлов превысит ограничение файловой системы
  • Ошибка "No space left on device" так же может появиться при огромном количестве файлов в одном каталоге т.к. это приводит к возникновению колизий в хеш-функции индекса каталога
  • Так же не контролируемый рост количества файлов в одном каталоге приведёт к не возможности пользоваться каталогом по прямому назначению - читать файлы, просматривать список файлов и другое.

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

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

Тогда адрес файла можно представить как набор вложеных каталогов следующим образом:

Адрес файла
Было 78d720f3-d989-481a-815f-8fa315a54c65/55076ddf-7e29-48f0-b605-4d41a3146f66
Стало 78d720f3/d989/481a/815f/8fa315a54c65/55076ddf/7e29/48f0/b605/4d41a3146f66

Note

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

Note

Так же надо заметить что создание подкатологов увеличит количество используемых inode - по одному на каждый новый вложенный каталог

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

Что бы невилировать проблему с количеством inode мы можем сгруппировать файлы по какому-то принципу в один большой файл.

Варианты как это сделать:

  • Создать архив с файлами в глубине последнего каталога - потребуется архиватор поддерживающий два свойства: 1. хранение заголовков в начале файла 2. хранение содержимого без обязательного сжатия
  • Создать формат хранения каталога в файле самостоятельно
  • Выбрать готовое решение в виде базы данных
  • Написать файловую систему для хранения файлов непосредственно на устройстве (hdd, ssd и прочие) - безусловно трудозатратный вариант, но и самый низкоуровневый

Для целей решения тестовой задачи:

Будем хранить файлы как есть, но применим вариант с вложенными каталогами.

Вариант с объединением файлов внутри каталога можно добавить в последствии при необходимости и включать соответствующим флагом.

Author

Oleg Shevelev

karma8-http-file-storage-service's People

Contributors

mantyr avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.