
Prima di iniziare, devo lasciare , così sarà chiaro di cosa stiamo parlando.
In questo articolo vorrei esaminare il livello che si occupa della memorizzazione dei file e come questo possa essere utilizzato da chiunque. , senza alcun legame diretto con la musica. Può organizzare la memorizzazione di qualsiasi file.
Nell'articolo precedente ho un po' "sminuito" ipfs, ma ciò è avvenuto proprio nel contesto del compito che stavo affrontando. In generale, considero questo progetto interessante. Mi piace semplicemente di più la possibilità di creare diverse reti per diversi compiti. Questo permette di organizzare meglio la struttura e ridurre il carico sui singoli nodi e sulla rete nel suo insieme. È possibile addirittura, nell'ambito di un certo progetto, suddividere la rete in parti secondo determinati criteri, riducendo il carico complessivo.
Quindi, storacle utilizza un meccanismo per organizzare la rete. Le principali caratteristiche sono:
- I file possono essere aggiunti allo storage attraverso qualsiasi nodo.
- I file vengono salvati interamente, non a blocchi.
- Ogni file ha un proprio hash unico basato sul contenuto per ulteriori operazioni.
- I file possono essere duplicati per maggiore affidabilità
- Il numero di file su un nodo è limitato solo dal file system (c'è un'eccezione, di cui parlerò più avanti)
- Il numero di file nella rete è limitato dalle capacità di spreadable in base al numero di nodi consentiti nella rete, che nella seconda versione potranno permettere di lavorare con un numero infinito di nodi (di questo parlerò in un altro articolo)
Un semplice esempio di come funziona il tutto dal programma:
Server:
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);
}
})();Cliente:
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);
}
})();Uno sguardo dall'interno
Sotto il cofano non c'è nulla di soprannaturale. Le informazioni sul numero di file, sulla loro dimensione totale e altri dettagli sono memorizzati in un database in memoria e vengono aggiornati al momento della cancellazione e aggiunta di file, quindi non è necessario interagire frequentemente con il file system. L'unica eccezione è l'attivazione del garbage collector, quando è necessaria la circolazione dei file al raggiungimento di certe dimensioni di storage, piuttosto che un divieto di aggiunta di nuovi file. In questo caso, è necessario attraversare lo storage, e lavorare con un grande numero di file (> un milione, diciamo) può causare carichi significativi. È meglio conservare meno file e avviare più nodi. Se il "pulitore" è disattivato, questo problema non si pone.
Lo storage dei file è costituito da 256 cartelle e 2 livelli di annidamento. I file sono memorizzati nelle cartelle di secondo livello. Pertanto, con 1 milione di file, in ogni cartella ci saranno circa 62500 file (1000000 / sqrt(256)).
I nomi delle cartelle sono formati dall'hash del file, in modo da poter accedere rapidamente conoscendo l'hash.
Questa struttura è stata scelta in base a un gran numero di requisiti diversi per lo storage: supporto per file system deboli, dove non è consigliabile avere molti file in una cartella, veloce attraversamento di tutte le cartelle se necessario, ecc. Una sorta di compromesso.
Caching
Durante l'aggiunta di file, così come durante il loro recupero, le referenze ai file vengono scritte nella cache.
Grazie a ciò, non è spesso necessario attraversare tutta la rete alla ricerca di un file. Questo accelera il recupero dei link e riduce il carico sulla rete. Inoltre, il caching avviene tramite intestazioni http.
Isomorfismo
Il client è scritto in javascript ed è isomorfo, può essere utilizzato direttamente dal browser.
È possibile caricare un file come script e ottenere accesso a window.ClientStoracle oppure importarlo tramite il sistema di build, ecc.
Link differiti
Una caratteristica interessante è anche il "link differito". Questo è un link a un file che può essere ottenuto in modo sincrono, qui e ora, mentre il file verrà recuperato non appena trovato nello storage. Questo è molto comodo quando, ad esempio, è necessario mostrare alcune immagini sul sito. Basta impostare il link differito in src e il gioco è fatto. Si possono inventare molti casi d'uso.
Api del client
- async Client.prototype.storeFile() — salvataggio del file
- async Client.prototype.getFileLink() — ottenimento di un link diretto al file
- async Client.prototype.getFileLinks() — ottenere un elenco di collegamenti diretti al file da tutti i nodi in cui si trova
- async Client.prototype.getFileToBuffer() — ottenere il file nel buffer
- async Client.prototype.getFileToPath() — ottenere il file nel file system
- async Client.prototype.getFileToBlob() — ottenere il file in blob (per la versione browser)
- async Client.prototype.removeFile() — rimuovere il file
- Client.prototype.createRequestedFileLink() — creare un collegamento posticipato
Esportazione di file su un altro server
Per trasferire file su un altro nodo è possibile:
- Basta copiare l'intera cartella di archiviazione insieme alle impostazioni. (in futuro questo potrebbe non funzionare)
- Copiare solo la cartella con i file. Ma in questo caso, sarà necessario eseguire una volta la funzione node.normalizeFilesInfo(), per ricalcolare tutti i dati e inserirli nel database.
- Utilizzare la funzione node.exportFiles(), che inizierà a copiare i file.
Impostazioni principali del nodo
Avviando un nodo di archiviazione, è possibile specificare tutte le impostazioni necessarie.
Descriverò le principali, il resto può essere trovato su GitHub.
- storage.dataSize — dimensione della cartella con i file
- storage.tempSize — dimensione della cartella temporanea
- storage.autoCleanSize — dimensione minima dell'archiviazione da mantenere. Se si specifica questa impostazione, non appena lo spazio inizia a scarseggiare, i file meno utilizzati verranno eliminati.
- file.maxSize — dimensione massima del file
- file.minSize — dimensione minima del file
- file.preferredDuplicates — numero preferito di duplicati del file nella rete
- file.mimeWhitelist — tipi di file consentiti
- file.mimeBlacklist — tipi di file non consentiti
- file.extWhitelist — estensioni di file consentite
- file.extBlacklist — estensioni di file non consentite
- file.linkCache — varie impostazioni di caching dei collegamenti
Quasi tutte le impostazioni relative alle dimensioni possono essere impostate sia in unità assolute che relative.
Operazioni tramite linea di comando
La libreria può essere utilizzata tramite linea di comando. Per farlo, è necessario installarla globalmente: npm i -g storacle. Dopo di che, è possibile eseguire le azioni necessarie dalla directory del progetto, dove si trova il nodo. Ad esempio, storacle -a storeFile -f ./file.txt -c ./config.js, per aggiungere un file. Tutte le azioni possono essere trovate in
Perché potrebbe esserti utile
- Se desideri creare un qualche tipo di progetto decentralizzato in cui si prevede di archiviare e gestire file in modo pratico. Ad esempio, il progetto musicale descritto nel link all'inizio dell'articolo utilizza storacle.
- Se stai lavorando ad altri progetti in cui è necessario memorizzare file in modo distribuito. Puoi facilmente costruire la tua rete privata, configurare i nodi in modo flessibile e aggiungere nuovi nodi quando necessario.
- Se hai semplicemente bisogno di un luogo dove memorizzare i file del tuo sito e non vuoi scrivere tutto da solo. Forse questa libreria è più adatta alle tue esigenze nel tuo caso.
- Se hai un progetto in cui lavori con file, ma vuoi eseguire tutte le operazioni dal browser. Puoi evitare di scrivere codice server.
I miei contatti:
Fonte: habr.com
