Перед началом хотелось бы оставить ссылку на предыдущую статью, чтобы уточнить, о чем именно идет речь.
В этой статье я хочу представить слой, отвечающий за хранение файлов, и то, как его может использовать кто угодно. Storace — независимая библиотека. Вы можете организовать хранение любых файлов.
В моей предыдущей статье я был слишком строг к ipfs, но это связано с контекстом моей задачи.
На самом деле, я думаю, что этот проект действительно классный. Я просто предпочитаю возможность создавать разные сети для разных задач. Это позволяет лучше организовать структуру и снизить нагрузку на каждый узел и сеть в целом. При необходимости можно даже разделить сеть на части в рамках одного проекта по определенным критериям, снизив общую нагрузку.
Итак, storacle использует расширяемый механизм для организации сети. Основные характеристики:
- Файлы можно добавлять в хранилище через любой узел.
- Файлы сохраняются целиком, а не блоками.
- Каждый файл имеет свой уникальный хэш контента для дальнейшей работы с ним.
- Файлы могут быть продублированы для большей надежности
- Количество файлов на одном узле ограничено только файловой системой (есть исключение, о котором речь пойдет позже)
- Количество файлов в сети ограничено возможностями разброса по количеству разрешенных узлов в сети, что во втором варианте позволяет работать с бесконечным числом узлов (подробнее об этом в другой статье)
Простой пример того, как это работает из программы:
Сервер:
const Node = require('storacle').Node;
(async () => {
try {
const node = new Node({
port: 4000,
hostname: 'localhost'
});
await node.init();
}
catch(err) {
console.error(err.stack);
process.exit(1);
}
})();
Клиент:
const Client = require('storacle').Client;
(async () => {
try {
const client = new Client({
address: 'localhost:4000'
});
await client.init();
const hash = await client.storeFile('./my-file');
const link = await client.getFileLink(hash);
await client.removeFile(hash);
}
catch(err) {
console.error(err.stack);
process.exit(1);
}
})();
Краткий обзор
Ничего сверхъестественного под капотом нет. Информация о количестве файлов, их общем размере и других моментах хранится в in-memory базе данных и обновляется при удалении и добавлении файлов, поэтому нет необходимости часто обращаться к файловой системе. Исключением является включение сборщика мусора при необходимости обращения файлов, а не ограничение их количества. В этом случае вам придется время от времени проходить через хранилище. А работа с большим количеством файлов (скажем, более миллиона файлов) может привести к значительным нагрузкам. Лучше хранить меньше файлов и запускать больше узлов. Если «очиститель» отключен, такой проблемы нет.
Хранилище файлов состоит из 256 папок и 2-х уровней вложенности. Файлы хранятся в папках второго уровня. Итак, если у нас в каждой папке по 1 млн файлов, то их примерно 62500 штук (1000000/sqrt(256)).
Имена папок формируются из хэша файла, чтобы обеспечить вам быстрый доступ в случае необходимости.
Эта структура была выбрана исходя из большого количества различных требований к хранилищу: поддержка слабых файловых систем, где нежелательно иметь много файлов в одной папке, быстрый обход папок при необходимости и так далее.
Кэширование
При добавлении или получении файлов ссылки на файлы записываются в кеш. Часто это означает, что вам не нужно искать файл по всей сети. Это ускоряет получение ссылок и снижает нагрузку на сеть. Кэширование также происходит через http-заголовки.
Изоморфизм
Клиент написан на javascript и является изоморфным, его можно использовать прямо из браузера.
Вы можете загрузить файл https://github.com/ortexx/storacle/blob/master/dist/storacle.client.js в виде скрипта и получить доступ к window.ClientStoracle или импортировать через система сборки и т.д.
Отложенные ссылки
Интересной особенностью также является «отложенная ссылка». Это ссылка на файл, которую можно получить синхронно, здесь и сейчас, и файл будет подтянут, когда будет найден в хранилище. Это очень удобно, например, когда нужно показать какие-то изображения на сайте. Просто поместите отложенную ссылку в src и все. Можно придумать массу случаев.
API клиента
- async Client.prototype.storeFile() — сохранение файла
- async Client.prototype.getFileLink() — получение прямой ссылки на файл
- asyncClient.prototype.getFileLinks() — получение списка прямых ссылок на файл со всех узлов, где он существует
- async Client.prototype.getFileToBuffer() — получение файла в качестве буфера
- async Client.prototype.getFileToPath() — получение файла в файловой системе
- async Client.prototype.getFileToBlob() — получение файла в виде блоба (для браузерной версии)
- async Client.prototype.removeFile() — удаление файла
- Client.prototype.createRequestedFileLink() — создание отложенной ссылки
Экспорт файлов на другой сервер
Чтобы передать файлы на другой узел, вы можете:
- Просто скопируйте всю папку хранилища вместе с настройками. (это может не сработать в будущем).
- Скопируйте только папку с файлами. Но в этом случае вам нужно запустить функцию node.normalizeFilesInfo() один раз, чтобы пересчитать все данные и поместить их в базу данных.
- Используйте функцию node.exportFiles(), которая запускает копирование файлов.
Основные настройки узла
При запуске узла хранения вы можете указать все необходимые настройки. Ниже перечислены только самые основные из них:
- storage.dataSize — размер папки с файлами.
- storage.tempSize — размер временной папки.
- storage.autoCleanSize — минимальный размер хранилища, который вы хотите сохранить. Если указать этот параметр, самые малоиспользуемые файлы будут удаляться, как только не хватит места.
- file.maxSize — максимальный размер файла.
- file.minSize — минимальный размер файла.
- file.preferredDuplicates — предпочтительное количество дубликатов файлов в сети.
- file.mimeWhitelist — допустимые типы файлов.
- file.mimeBlacklist — недопустимые типы файлов.
- file.extWhitelist — допустимые расширения файлов.
- file.extBlacklist — недопустимые расширения файлов.
- file.linkCache — настройки кэширования ссылок.
Практически все параметры, связанные с размерами, можно задавать как в абсолютных, так и в относительных значениях.
Использование командной строки
Библиотеку можно использовать через командную строку. Вам необходимо установить его глобально: npm i -g storacle. После этого вы можете запускать необходимые действия из каталога проекта, где находится нода.
Например, storacle -a storeFile -f ./file.txt -c ./config.js, чтобы добавить файл. Все действия можно найти в https://github.com/ortexx/storacle/blob/master/bin/actions.js
Зачем вам это нужно
- Если вы хотите создать децентрализованный проект, в котором вы будете хранить файлы и работать с ними удобными способами. Например, музыкальный проект, описанный по ссылке в начале статьи, использует storacle.
- Если вы работаете над каким-либо другим проектом, в котором вам необходимо хранить распространяемые файлы. Вы можете легко построить собственную закрытую сеть, гибко настроить узлы и добавить новые, когда вам это нужно.
- Если вам просто нужно где-то хранить файлы вашего сайта и приходится все писать самому. Возможно, эта библиотека лучше других, в вашем случае.
- Если у вас есть проект, в котором вы работаете с файлами, но хотите выполнять все манипуляции из браузера. Вы можете избежать написания кода на стороне сервера.
Мои контакты: