habrahabr

Система удаленного файлового доступа Cage

  • суббота, 10 августа 2019 г. в 00:20:04
https://habr.com/ru/post/463085/
  • Python
  • IT-инфраструктура
  • Параллельное программирование
  • Хранение данных


Назначение системы


Поддержка удаленного доступа к файлам на компьютерах в сети. Система «виртуально» поддерживает все основные файловые операции (создание, удаление, чтение, запись и др.) путём обмена транзакциями (сообщениями) по протоколу ТСР.


Области применения


Функционал системы эффективен в следующих случаях:

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

Структура


Система Cage (имеется реализация — beta-версия на Python 3.7 в ОС Windows) включает две основные части:

  1. Cageserver — программа файл-сервера (пакет функций), которая запускается на компьютерах в сети, к файлам которых необходим удаленный доступ;
  2. класс Cage с библиотекой методов для клиентского ПО, упрощающее кодирование взаимодействия с серверами.

Использование системы на стороне клиентов


Методы класса Cage заменяют обычные, «рутинные» операции файловой системы: создание, открытие, закрытие, удаление файлов, а также чтение/запись данных в бинарном формате (с указанием позиции и размера данных). Концептуально эти методы приближены к файловым функциям языка C, где открытие/закрытие файлов производится «на каналах» ввода-вывода.


Иными словами, программист работает не с методами «файловых» объектов (класса _io в Python), а с методами класса Cage.


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


Система повышает быстродействие чтения/записи на основе буферизации часто используемых фрагментов файлов у клиентских программ в кэше (буфере) оперативной памяти.
Клиентское ПО может использовать любое число объектов Cage с различными настройками (объем буферной памяти, размер блоков при обмене с сервером и др.).


Один объект Cage может обмениваться данными с несколькими файлами на нескольких серверах. Параметры для связи (IP-адрес или DNS сервера, основной порт для авторизации, путь и имя файла) задаются при создании объекта.


Так как каждый объект Cage может одновременно работать с множеством файлов, для буферизации используется общее пространство памяти. Размер кэша – количество страниц и их размер, задается динамически при создании объекта Cage. Например, кэш в 1 Гбайт — это 1000 страниц по 1 Мбайт, или 10 тыс. страниц по 100 Кбайт, или 1 млн. страниц по 1 Кбайт. Выбор размера и количества страниц – это конкретная задача для каждого прикладного случая.


Можно одновременно использовать несколько объектов Cage, чтобы определить различные настройки буферной памяти в зависимости от особенностей доступа к информации в различных файлах. Как базовый применяется простейший алгоритм буферизации: после исчерпания заданного объема памяти новые страницы вытесняют старые по принципу выбытия с минимальным числом обращений. Буферизация особенно эффективна в случае неравномерного (в статистическом смысле) совместного доступа, во-первых, к различным файлам, и, во-вторых, к фрагментам каждого файла.


Класс Cage поддерживает ввод/вывод не только по адресам данных (с указанием позиции и длины массива, «заменяя» операции файловой системы), но и на более низком, «физическом» уровне — по номерам страниц в буферной памяти.


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


Cage — это около 3600 строк кода.


Принципы построения серверов


Файл-серверы Cageserver можно запускать с произвольным числом портов, один из которых («основной») используется только для авторизации всех клиентов, остальные — для обмена данными. Для программы сервера Cage требуется только Python. Параллельно компьютер с файл-сервером может выполнять любую другую работу.


Сервер запускается вначале как совокупность двух основных процессов:

  1. «Соединения» – процесс для выполнения операций установления связи с клиентами и ее прекращения по инициативе сервера;
  2. «Операции» – процесс для выполнения заданий (операций) клиентов по работе с файлами, а также для закрытия сеансов связи по командам клиентов.

Оба процесса не синхронизированы и организованы как бесконечные циклы приема и отправки сообщений на основе мультипроцессных очередей, прокси-объектов, замков и сокетов.
Процесс «Соединения» выделяет каждому клиенту порт для приема-передачи данных. Количество портов задается при запуске сервера. Соответствие между портами и клиентами хранится в разделяемой между процессами прокси-памяти.


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

Обработка команд на создание/удаление /открытие/закрытие файлов на сервере производится в самом процессе «Операции» строго последовательно с использованием файловой подсистемы ОС сервера.


Для общего ускорения чтения/записи эти операции осуществляются в потоках (threads), порождаемых процессом «Операции». Число потоков, как правило, равно количеству открытых файлов. Задания на чтение/запись от клиентов подаются в общую очередь и первый освободившийся поток забирает задание из ее головы. Специальная логика позволяет исключить операции перезаписи данных в оперативной памяти сервера.


Процесс «Операции» следит за активностью клиентов и прекращает их обслуживание как по их командам, так и при превышении таймаута неактивности.


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


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


Cageserver — это около 3100 строк кода.


image

Запуск программы файл-сервера Cageserver


При запуске в диалоге надо определить:
— основной порт для авторизации;
— количество портов для обмена транзакциями с авторизованными клиентами (от 1-го и более, пул номеров начинается с следующего за номером основного порта).


Использование класса Cage


class cage.Cage( cage_name="", pagesize=0, numpages=0, maxstrlen=0, server_ip={}, wait=0, awake=False, cache_file="" )


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


Параметры


  • cage_name(str) — условное имя объекта, которое используется при идентификации клиентов на стороне сервера
  • pagesize(int) — размер одной страницы буферной памяти (в байтах)
  • numpages(int) — количество страниц буферной памяти
  • maxstrlen(int) — максимальная длина байтовой строки в операциях записи и чтения
  • server_ip(dict) — словарь с адресами используемых серверов, где ключом является условное имя сервера (id сервера внутри приложения), а значением строка с адресом: “ip address:port” или “DNS:port” (сопоставление имен и реальных адресов — временное, его можно менять)
  • wait(int) — время ожидания ответа от сервера при получении портов (в сек.)
  • awake(boolean) — флаг способа создания объекта (False — если создается новый объект, True — если объект создается из ранее «свернутого» — применением операции «гибернации», по умолчанию False)
  • cache_file(str) — имя файла для гибернации

Методы


Cage.file_create( server, path ) – создать новый файл


Cage.file_rename( server, path, new_name ) – переименовать файл


Cage.file_remove( server, path) – удалить файл


Cage.open( server, path, mod ) – открыть файл


Возвращает fchannel номер канала. Параметр mod — это режим открытия файла: «wm» — монопольный (чтение/запись), «rs» — только чтение, и разделяемый только для чтения другими клиентами, «ws» — чтение/запись, и разделяемый только для чтения другими клиентам.


Cage.close (fchannel) – закрыть файл


Cage.write (fchannel, begin, data ) – записать байтовую строку в файл


Cage.read (fchannel, begin, len_data ) – прочитать байтовую строку из файла


Cage.put_pages ( fchannel ) – «выталкивает» из буфера на сервер все страницы указанного канала, которые были модифицированы. Используется в тех точках алгоритма, когда надо быть уверенным, что все операции на канале физически сохранены в файле на сервере.


Cage.push_all () – «выталкивает» из буфера на сервер все страницы всех каналов для экземпляра класса Cage, которые были модифицированы. Используется, когда надо быть уверенным, что все операции на всех каналах сохранены на сервере.