
Antes de comenzar, debo dejar , para que quede claro de qué se trata.
En este artículo, me gustaría abordar la capa responsable del almacenamiento de archivos y cómo puede ser utilizada por cualquier persona. , no hay conexión directa con la música. Se puede organizar el almacenamiento de cualquier archivo.
En el artículo anterior, comenté un poco sobre ipfs, pero esto ocurrió precisamente en el contexto del problema que estaba resolviendo. En general, considero que este proyecto es genial. Simplemente me gusta más la capacidad de crear diferentes redes para diversas tareas. Esto permite organizar mejor la estructura y reducir la carga en nodos individuales y en la red en su conjunto. Incluso se puede fragmentar la red en partes basadas en ciertos criterios dentro de un mismo proyecto, reduciendo así la carga general.
Entonces, storacle utiliza un mecanismo para organizar la red. Características principales:
- Los archivos pueden añadirse al almacenamiento a través de cualquier nodo.
- Los archivos se guardan en su totalidad, no en bloques.
- Cada archivo tiene su propio hash único basado en su contenido para futuras operaciones con él.
- Los archivos pueden duplicarse para mayor fiabilidad.
- El número de archivos en un nodo está limitado solo por el sistema de archivos (hay una excepción, la mencionaré más abajo).
- El número de archivos en la red está limitado por las capacidades de spreadable y el número permitido de nodos en la red, que en la segunda versión podrá permitir trabajar con un número infinito de nodos (de esto hablaré en otro artículo).
Un ejemplo simple de cómo funciona esto en el programa:
Servidor:
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);
}
})();Una mirada desde adentro
Bajo el capó no hay nada sobrenatural. La información sobre la cantidad de archivos, su tamaño total y otros aspectos se almacenan en una base de datos en memoria y se actualizan al eliminar y agregar archivos, por lo que no es necesario acceder con frecuencia al sistema de archivos. La única excepción es la inclusión del recolector de basura, cuando se necesita la circulación de archivos al alcanzar ciertos tamaños de almacenamiento, en lugar de prohibir la adición de nuevos. En este caso, es necesario recorrer el almacenamiento, y trabajar con una gran cantidad de archivos (> un millón, digamos) puede generar cargas significativas. Es mejor guardar menos archivos y ejecutar más nodos. Si el "limpiador" está desactivado, no hay tal problema.
El almacenamiento de archivos consiste en 256 carpetas y 2 niveles de anidamiento. Los archivos se almacenan en carpetas de segundo nivel. Es decir, con 1 millón de archivos, habrá alrededor de 62500 en cada carpeta (1000000 / sqrt(256)).
Los nombres de las carpetas se forman a partir del hash del archivo, para poder acceder rápidamente una vez conocido el hash.
Se eligió esta estructura en función de un gran número de requisitos diversos para el almacenamiento: soporte para sistemas de archivos débiles, donde no es deseable tener muchos archivos en una carpeta, acceso rápido a todas las carpetas cuando sea necesario, etc. Es una especie de término medio.
Cacheo
Al agregar archivos, así como al obtenerlos, se registran enlaces a los archivos en la caché.
Gracias a esto, a menudo no es necesario recorrer toda la red en busca de un archivo. Esto acelera la obtención de enlaces y reduce la carga en la red. Además, la caché se realiza a través de encabezados HTTP.
Isomorfismo
El cliente está escrito en javascript y es isomórfico, se puede usar directamente desde el navegador.
Puedes cargar un archivo como un script y obtener acceso a window.ClientStoracle o importarlo a través del sistema de compilación, etc.
Enlaces diferidos
Una característica interesante también es el "enlace diferido". Es un enlace a un archivo que se puede obtener de manera sincronizada, aquí y ahora, y el archivo se descargará cuando ya haya sido encontrado en el almacenamiento. Esto es muy conveniente, por ejemplo, cuando necesitas mostrar ciertas imágenes en un sitio web. Simplemente colocamos el enlace diferido en el src y listo. Se pueden imaginar muchos casos.
API del cliente
- async Client.prototype.storeFile() — guarda un archivo
- async Client.prototype.getFileLink() — obtiene un enlace directo al archivo
- async Client.prototype.getFileLinks() — obtener una lista de enlaces directos al archivo desde todos los nodos donde está presente
- async Client.prototype.getFileToBuffer() — obtener el archivo en un búfer
- async Client.prototype.getFileToPath() — obtener el archivo en el sistema de archivos
- async Client.prototype.getFileToBlob() — obtener el archivo en un blob (para la versión del navegador)
- async Client.prototype.removeFile() — eliminar archivo
- Client.prototype.createRequestedFileLink() — crear un enlace diferido
Exportar archivos a otro servidor
Para transferir archivos a otro nodo puedes:
- Simplemente copiar toda la carpeta de almacenamiento junto con la configuración. (esto puede no funcionar en el futuro)
- Copiar solo la carpeta con los archivos. Pero, en este caso, necesitarás ejecutar una vez la función node.normalizeFilesInfo(), para recalcular todos los datos y registrarlos en la base de datos.
- Usar la función node.exportFiles(), que comenzará a copiar los archivos.
Configuraciones principales del nodo
Al iniciar el nodo de almacenamiento, puedes especificar todas las configuraciones necesarias.
Describiré las más importantes, lo demás se puede encontrar en GitHub.
- storage.dataSize — tamaño de la carpeta con archivos
- storage.tempSize — tamaño de la carpeta temporal
- storage.autoCleanSize — tamaño mínimo de almacenamiento que debe mantenerse. Si se especifica este parámetro, en cuanto el espacio comience a ser insuficiente, se eliminarán los archivos menos utilizados.
- file.maxSize — tamaño máximo del archivo
- file.minSize — tamaño mínimo del archivo
- file.preferredDuplicates — número preferido de duplicados del archivo en la red
- file.mimeWhitelist — tipos de archivos permitidos
- file.mimeBlacklist — tipos de archivos no permitidos
- file.extWhitelist — extensiones de archivos permitidas
- file.extBlacklist — extensiones de archivos no permitidas
- file.linkCache — varias configuraciones de caché de enlaces
Casi todos los parámetros relacionados con tamaños pueden especificarse tanto en valores absolutos como en relativos.
Trabajo a través de la línea de comandos
La biblioteca se puede utilizar a través de la línea de comandos. Para ello, necesitas instalarla globalmente: npm i -g storacle. Después de esto, puedes ejecutar las acciones necesarias desde el directorio con el proyecto, donde está el nodo. Por ejemplo, storacle -a storeFile -f ./file.txt -c ./config.js, para agregar un archivo. Todas las acciones se pueden encontrar en
Por qué podrías necesitar esto
- Si deseas crear algún proyecto descentralizado, en el que se planea almacenar y trabajar con archivos de manera conveniente. Por ejemplo, el proyecto de música descrito en el enlace al principio del artículo utiliza storacle.
- Si trabajas en otros proyectos donde necesitas almacenar archivos de forma descentralizada, puedes construir fácilmente tu propia red privada, configurando los nodos de manera flexible y añadiendo nuevos cuando sea necesario.
- Si solo necesitas un lugar para almacenar los archivos de tu sitio y no quieres escribir todo tú mismo, quizás esta biblioteca sea la mejor opción para ti.
- Si tienes un proyecto en el que trabajas con archivos, pero quieres realizar todas las operaciones desde el navegador, puedes evitar escribir código del lado del servidor.
Mis contactos:
Fuente: habr.com
