Перш ніж почну, повинен залишити
У цій статті хотів би розібрати шар, який відповідає за зберігання файлів, і як це може бути використано будь-якою людиною.
У попередній статті я трохи "накотив бочку" на ipfs, але це сталося саме в контексті завдання, що мною вирішується. Загалом, я вважаю цей проект крутим. Просто мені більше подобається можливість створювати різні мережі під різні завдання. Це дозволяє краще організовувати структуру та знижувати навантаження на окремі вузли та мережу в цілому. Можна навіть у рамках одного якогось проекту, за потреби, дробити мережу на шматки за якимись критеріями, знижуючи загальне навантаження.
Отже, storacle використовує механізм
- Файли можуть додаватися до сховища через будь-який вузол.
- Файли зберігаються повністю, не блоками.
- Кожен файл має свій унікальний хеш за вмістом для подальшої роботи з ним.
- Файли можуть дублюватися для більшої надійності
- Кількість файлів на одному вузлі обмежена лише файловою системою (є виняток, про нього буде нижче)
- Кількість файлів у мережі обмежена можливостями spreadable за кількістю допустимих вузлів у мережі, які у другій версії зможуть дозволяти працювати з нескінченним числом вузлів (про це в іншій статті)
Простий приклад, як це взагалі працює із програми:
Сервер:
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 штук (256 / sqrt(XNUMX)).
Назва папок формуються з хеш файлу, щоб можна було швидко отримати доступ, знаючи хеш.
Така структура була обрана виходячи з великої кількості різних вимог до сховища: підтримка слабких файлових систем, де в одній папці не бажано мати багато файлів, швидкий обхід усіх папок за потреби, і т.д. Якась золота середина.
Кешування
При додаванні файлів, а також при їх отриманні в кеш записуються посилання на файли.
Завдяки цьому дуже часто не потрібно обходити всю мережу в пошуках файлу. Це прискорює отримання посилань та зменшує навантаження на мережу. Також кешування відбувається через http заголовки.
Ізоморфність
Клієнт написаний на JavaScript та ізоморфний, його можна використовувати прямо з браузера.
Можна завантажити файл
Відкладені посилання
Цікавою фічею також є "відкладене посилання". Це посилання на файл, який можна отримати синхронно, тут і зараз, а файл підтягнеться, коли вже буде знайдений у сховищі. Це дуже зручно, коли, наприклад, потрібно показати на сайті якісь картинки. Просто проставляємо в src відкладене посилання та все. Кейсів можна вигадати багато.
Api клієнта
- асинхронний Client.prototype.storeFile() - Збереження файлу
- асинхронний Client.prototype.getFileLink() - Отримання прямого посилання на файл
- асинхронний Client.prototype.getFileLinks() — отримання списку прямих посилань на файл із усіх вузлів, де він є
- асинхронний Client.prototype.getFileToBuffer() - Отримати файл у буфер
- асинхронний Client.prototype.getFileToPath() - Отримати файл у файлову систему
- асинхронний Client.prototype.getFileToBlob() - Отримати файл в blob (для браузерної версії)
- асинхронний 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, щоб додати файл. Всі екшени можна знайти в
Навіщо тобі це може бути потрібно
- Якщо ти хочеш створити якийсь децентралізований проект, у якому планується зберігати та працювати з файлами зручними методами. Наприклад, проект із музикою, описаний за посиланням на початку статті, використовує storacle.
- Якщо ти працюєш над іншими проектами, де потрібно зберігати файли розподілено. Ти можеш легко побудувати свою закриту мережу, гнучко налаштовувати вузли та додавати нові, коли це потрібно.
- Якщо тобі просто потрібно десь зберігати файли свого сайту і тобі влом писати все самому. Можливо ця бібліотека підійде краще за інших, у твоєму випадку.
- Якщо у тебе проект, у якому ти працюєш із файлами, але хочеш усі маніпуляції робити з браузера. Ти можеш уникнути написання серверного коду.
Мої контакти:
Джерело: habr.com