
Zanim zacznę, muszę zostawić , aby było jasne, o co dokładnie chodzi.
W tym artykule chciałbym omówić warstwę, która odpowiada za przechowywanie plików, oraz jak może być to wykorzystane przez każdego użytkownika. , nie ma żadnego bezpośredniego związku z muzyką. Można zorganizować przechowywanie dowolnych plików.
W poprzednim artykule trochę "przekładałem bęben" na ipfs, ale miało to miejsce w kontekście zadania, które realizowałem. Ogólnie uważam ten projekt za świetny. Po prostu bardziej podoba mi się możliwość tworzenia różnych sieci do różnych zadań. Umożliwia to lepszą organizację struktury i zmniejsza obciążenie poszczególnych węzłów oraz sieci jako całości. Nawet w ramach jednego projektu, w razie potrzeby, można podzielić sieć na kawałki według różnych kryteriów, zmniejszając całkowite obciążenie.
Zatem storacle wykorzystuje mechanizm do organizacji sieci. Główne cechy:
- Pliki mogą być dodawane do magazynu przez dowolny węzeł.
- Pliki są przechowywane w całości, a nie w blokach.
- Każdy plik ma swój unikalny hash według treści do dalszej pracy z nim.
- Pliki mogą być duplikowane dla większej niezawodności
- Liczba plików na jednym węźle jest ograniczona tylko przez system plików (jest wyjątek, o którym będzie mowa poniżej)
- Liczba plików w sieci jest ograniczona możliwościami spreadable co do liczby dozwolonych węzłów w sieci, które w drugiej wersji będą mogły umożliwić pracę z nieskończoną liczbą węzłów (o tym w innym artykule)
Prosty przykład, jak to w ogóle działa z programu:
Serwer:
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);
}
})();Klient:
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);
}
})();Wgląd od wewnątrz
Pod maską nie ma nic nadzwyczajnego. Informacje o liczbie plików, ich łącznym rozmiarze i innych kwestiach są przechowywane w pamięci i aktualizowane przy usuwaniu i dodawaniu plików, dlatego nie ma potrzeby częstego sięgania do systemu plików. Wyjątkiem jest włączenie zbieracza śmieci, kiedy potrzebna jest cyrkulacja plików przy osiągnięciu określonych rozmiarów przechowalni, a nie zakaz dodawania nowych. W takim przypadku trzeba przeszukać przechowalnię, a praca z dużą liczbą plików (> miliona) może prowadzić do znacznych obciążeń. Lepiej przechowywać mniej plików i uruchamiać więcej węzłów. Jeśli "czyściciel" jest wyłączony, to takiego problemu nie ma.
Przechowalnia plików składa się z 256 folderów i 2 poziomów zagnieżdżenia. Pliki są przechowywane w folderach drugiego poziomu. To znaczy, przy posiadaniu 1 mln plików w każdym takim folderze będzie około 62500 sztuk (1000000 / sqrt(256)).
Nazwy folderów są tworzone z hasha pliku, aby można było szybko uzyskać dostęp, znając hash.
Taka struktura została wybrana ze względu na wiele różnych wymagań dotyczących przechowalni: wsparcie dla słabych systemów plików, gdzie w jednym folderze nie pożądane jest posiadanie wielu plików, szybkie przeszukiwanie wszystkich folderów w razie potrzeby itd. Jest to swoiste złote środek.
Odtwarzanie
Podczas dodawania plików, a także ich pobierania, w pamięci podręcznej zapisywane są linki do plików.
Dzięki temu często nie ma potrzeby przeszukiwania całej sieci w poszukiwaniu pliku. Przyspiesza to uzyskiwanie linków i zmniejsza obciążenie sieci. Również pamięć podręczna działa przez nagłówki HTTP.
Izomorfność
Klient napisany jest w JavaScript i jest izomorficzny, można go używać bezpośrednio z przeglądarki.
Można załadować plik jako skrypt i uzyskać dostęp do window.ClientStoracle lub zaimportować przez system budowy itd.
Opóźnione linki
Interesującą cechą jest również "opóźniony link". To link do pliku, który można uzyskać synchronicznie, tu i teraz, a plik zostanie pobrany, gdy tylko zostanie znaleziony w przechowalni. Jest to bardzo wygodne, gdy na przykład potrzebne jest pokazanie jakichś obrazków na stronie. Po prostu podstawiamy w src opóźniony link i tyle. Można wymyślić wiele przypadków użycia.
Api klienta
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.storeFile() — zapis pliku
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.getFileLink() — uzyskanie bezpośredniego linku do pliku
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.getFileLinks() — uzyskanie listy bezpośrednich linków do pliku ze wszystkich węzłów, na których się znajduje
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.getFileToBuffer() — pobierz plik do bufora
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.getFileToPath() — pobierz plik do systemu plików
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.getFileToBlob() — pobierz plik jako blob (dla wersji przeglądarkowej)
- (196 tysięcy linii kodu, 11 autorów, 7 komiterów, 11 otwartych problemów); Client.prototype.removeFile() — usuń plik
- Client.prototype.createRequestedFileLink() — utwórz opóźniony link
Eksport plików na inny serwer
Aby przenieść pliki na inny węzeł, można:
- Po prostu skopiować cały folder magazynu wraz z ustawieniami. (w przyszłości może to nie działać)
- Skopiować tylko folder z plikami. Ale w takim przypadku będzie trzeba jeden raz uruchomić funkcję node.normalizeFilesInfo(), aby przeliczyć wszystkie dane i wprowadzić je do bazy.
- Użyć funkcji node.exportFiles(), która rozpocznie kopiowanie plików.
Podstawowe ustawienia węzła
Uruchamiając węzeł magazynu, można określić wszystkie potrzebne ustawienia.
Opiszę najważniejsze, resztę można znaleźć na GitHubie.
- storage.dataSize — rozmiar folderu z plikami
- storage.tempSize — rozmiar folderu tymczasowego
- storage.autoCleanSize — minimalny rozmiar magazynu, który należy utrzymać. Jeśli ustalisz ten parametr, to gdy miejsca zacznie brakować, najmniej używane pliki będą usuwane.
- file.maxSize — maksymalny rozmiar pliku
- file.minSize — minimalny rozmiar pliku
- file.preferredDuplicates — preferowana liczba duplikatów pliku w sieci
- file.mimeWhitelist — dozwolone typy plików
- file.mimeBlacklist — niedozwolone typy plików
- file.extWhitelist — dozwolone rozszerzenia plików
- file.extBlacklist — niedozwolone rozszerzenia plików
- file.linkCache — różne ustawienia pamięci podręcznej linków
Prawie wszystkie parametry związane z rozmiarami mogą być podawane zarówno w wartościach bezwzględnych, jak i względnych.
Praca przez wiersz poleceń
Bibliotekę można używać przez wiersz poleceń. W tym celu należy zainstalować ją globalnie: npm i -g storacle. Po tym można uruchamiać potrzebne akcje z katalogu z projektem, w którym jest węzeł. Na przykład, storacle -a storeFile -f ./file.txt -c ./config.js, aby dodać plik. Wszystkie akcje można znaleźć w
Po co to może być potrzebne
- Jeśli chcesz stworzyć jakiś zdecentralizowany projekt, w którym planuje się przechowywać i pracować z plikami w wygodny sposób. Na przykład, projekt z muzyką, opisany w linku na początku artykułu, wykorzystuje storacle.
- Jeśli pracujesz nad innymi projektami, gdzie potrzebne jest przechowywanie plików w sposób rozproszony, możesz łatwo zbudować swoją zamkniętą sieć, elastycznie konfigurować węzły i dodawać nowe, gdy zajdzie taka potrzeba.
- Jeśli po prostu potrzebujesz miejsca do przechowywania plików swojej strony i nie chce ci się nic pisać samodzielnie, być może ta biblioteka będzie lepsza niż inne w twoim przypadku.
- Jeśli masz projekt, w którym pracujesz z plikami, ale chcesz wykonywać wszystkie operacje z poziomu przeglądarki, możesz uniknąć pisania kodu serwerowego.
Moje kontakty:
Źródło: habr.com
