diff --git a/.gitignore b/.gitignore index 18f0865e1278efb1b3a910512e23cdc88e772017..85d09d50d3f728690b35c5da11629bc249c84b20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Dépendances /node_modules +app/node_modules # Logs logs diff --git a/README.md b/README.md index 829a7faf0fc71754bbd0eeaa9e9914f320d74c09..6e1a73997fd8da00839b98c9df574f9a8712f258 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,23 @@ # TP Final Docker +## Lancement de l'application +```shell +sudo docker compose up --build +``` + +## L'esclave (hash_extractor) +```shell +sudo docker swarm init +sudo docker run -ti --network host --rm servuc/hash_extractor:latest ./hash_extractor s ws://127.0.0.1:3000 +``` + +## Scalabilité +```shell +sudo docker build -t scalabilite . +sudo docker service create --name scaler --network host scalabilite +``` + +## Redis +```shell +sudo docker service create --name redis-db --network mon-reseau redis:alpine +``` diff --git a/app.js b/app.js deleted file mode 100644 index 28692358268805bb687b3ae23bc47c1438461bb7..0000000000000000000000000000000000000000 --- a/app.js +++ /dev/null @@ -1,59 +0,0 @@ -const express = require('express'); -const crypto = require('crypto'); -const redis = require('redis'); - -const app = express(); -app.use(express.json()); - -// le client Redis -const client = redis.createClient({ - url: 'redis://redis:6379' -}); - -client.on('error', (err) => console.log('Erreur Redis Client', err)); - -// etablissement de la connexion Redis -async function connectRedis() { - try { - await client.connect(); - } catch (err) { - console.error('Erreur de connexion Redis:', err); - process.exit(1); - } -} - -connectRedis(); - -app.post('/calculate-md5', async (req, res) => { - try { - const text = req.body.text; - const hash = crypto.createHash('md5').update(text).digest('hex'); - - // on stocke le hash dans Redis avec la chaîne originale comme clé - await client.set(text, hash); - - res.json({ text: text, hash: hash }); - } catch (err) { - res.status(500).json({ error: 'Erreur du serveur' }); - } -}); - -app.get('/get-md5/:text', async (req, res) => { - try { - const text = req.params.text; - - //récupérer le hash de Redis - const hash = await client.get(text); - if (hash === null) { - return res.status(404).json({ error: 'Texte non trouvé' }); - } - res.json({ text: text, hash: hash }); - } catch (err) { - res.status(500).json({ error: 'Erreur du serveur' }); - } -}); - -const PORT = 3000; -app.listen(PORT, () => { - console.log(`Serveur démarré sur le port ${PORT}`); -}); diff --git a/Dockerfile b/app/Dockerfile similarity index 91% rename from Dockerfile rename to app/Dockerfile index 9b48d419f46abe0485827db8de22df9e704ae5e7..8a1e911ab467ee2374bae31e500af52f61dab3ca 100644 --- a/Dockerfile +++ b/app/Dockerfile @@ -6,7 +6,7 @@ COPY package*.json ./ RUN npm install -COPY . . +COPY .. . EXPOSE 3000 diff --git a/app/app.js b/app/app.js new file mode 100644 index 0000000000000000000000000000000000000000..076595cb1e7620610127ab7a34a46c7a408ad6f0 --- /dev/null +++ b/app/app.js @@ -0,0 +1,114 @@ +const express = require('express'); +const crypto = require('crypto'); +const redis = require('redis'); +const WebSocket = require('ws'); +const http = require('http'); + +const { generateSimulatedHash } = require('./utils'); + +const app = express(); +app.use(express.json()); + +// le client Redis +const client = redis.createClient({ + url: 'redis://redis:6379' +}); + +client.on('error', (err) => console.log('Erreur Redis Client', err)); + +// etablissement de la connexion Redis +async function connectRedis() { + try { + await client.connect(); + } catch (err) { + console.error('Erreur de connexion Redis:', err); + process.exit(1); + } +} + +connectRedis(); + +// Création du serveur HTTP +const server = http.createServer(app); + +// Création du serveur WebSocket en attachant au serveur HTTP +const wss = new WebSocket.Server({ server }); + +// Gestionnaire d'ouverture de la connexion WebSocket +wss.on('connection', (ws) => { + console.log('Connexion WebSocket avec un client établie'); + + // Gestion des messages WebSocket + ws.on('message', (message) => { + console.log('Message reçu du client:', message); + }); +}); + + app.post('/generateHash', (req, res) => { + const difficulty = req.body.data; + + if (!difficulty) { + return res.status(400).json({ error: 'Missing data in the request.' }); + } + + const hash = generateSimulatedHash(difficulty); + wss.clients.forEach((client) => { + if (client.readyState === WebSocket.OPEN) { + client.send(hash); + } + }); + + res.json({ hash }); + }); + +app.post('/calculate-md5', async (req, res) => { + try { + const text = req.body.text; + const hash = crypto.createHash('md5').update(text).digest('hex'); + + // on stocke le hash dans Redis avec la chaîne originale comme clé + await client.set(text, hash); + + // Envoi du texte au service esclave via WebSocket + wss.clients.forEach((client) => { + if (client.readyState === WebSocket.OPEN) { + client.send(hash); + } + }); + + res.json({ text: text, hash: hash }); + } catch (err) { + res.status(500).json({ error: 'Erreur du serveur' }); + } +}); + +app.get('/get-md5/:text', async (req, res) => { + try { + const text = req.params.text; + + //récupérer le hash de Redis + const hash = await client.get(text); + if (hash === null) { + return res.status(404).json({ error: 'Texte non trouvé' }); + } + res.json({ text: text, hash: hash }); + } catch (err) { + res.status(500).json({ error: 'Erreur du serveur' }); + } +}); + +const PORT = 3000; +server.listen(PORT, () => { + console.log(`Serveur démarré sur le port ${PORT}`); +}); + + +const socket = new WebSocket('ws://127.0.0.1:3000'); + +socket.addEventListener('open', (event) => { + console.log('Connexion WebSocket établie avec le serveur'); +}); + +socket.addEventListener('message', (event) => { + console.log('Message reçu du serveur:', event.data); +}); \ No newline at end of file diff --git a/docker-compose.yml b/app/docker-compose.yml similarity index 99% rename from docker-compose.yml rename to app/docker-compose.yml index 1120cfa0785d0cc3e25e8b2fcbe01430d1612f72..0f74bcdcc3e697bef593b7236faed5efccc701d3 100644 --- a/docker-compose.yml +++ b/app/docker-compose.yml @@ -15,3 +15,4 @@ services: image: redis:alpine ports: - "6379:6379" + diff --git a/package-lock.json b/app/package-lock.json similarity index 97% rename from package-lock.json rename to app/package-lock.json index 4e2b1f5541cd5cd567e46a4e66aa385f121b0b1a..360eeb4b6fd4f375ff08c5a686b009c39b77d70d 100644 --- a/package-lock.json +++ b/app/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "express": "^4.18.2", "md5": "^2.3.0", - "redis": "^4.6.12" + "redis": "^4.6.12", + "ws": "^8.16.0" } }, "node_modules/@redis/bloom": { @@ -769,6 +770,26 @@ "node": ">= 0.8" } }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/app/package.json similarity index 87% rename from package.json rename to app/package.json index 4a1124ad959ac6aa3e2bbd271ca9366136a6df4f..a92053d9723876d4d0e834cf153dabd90d3fa2dd 100644 --- a/package.json +++ b/app/package.json @@ -12,6 +12,7 @@ "dependencies": { "express": "^4.18.2", "md5": "^2.3.0", - "redis": "^4.6.12" + "redis": "^4.6.12", + "ws": "^8.16.0" } } diff --git a/app/utils.js b/app/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..accc27fea5299ce2b76ee8df96bfef56d5bf5d1b --- /dev/null +++ b/app/utils.js @@ -0,0 +1,19 @@ +const crypto = require('crypto'); +function generateSimulatedHash(difficulty) { + let data; + + if (difficulty === 'gentil') { + data = crypto.randomBytes(16).toString('hex'); // Mode gentil (faible complexité) + } else if (difficulty === 'normal') { + data = crypto.randomBytes(1000).toString('hex'); // Mode normal (moyenne complexité) + } else if (difficulty === 'agressif') { + data = crypto.randomBytes(1000).toString('hex'); // Mode agressif (haute complexité) + } + + const hash = crypto.createHash('md5').update(data).digest('hex'); + return hash; +} + +module.exports = { + generateSimulatedHash, +}; \ No newline at end of file diff --git a/scalabilite/Dockerfile b/scalabilite/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e3bfbc36644083ea7098fc0a2210fcfc618bb292 --- /dev/null +++ b/scalabilite/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:3.14 + +RUN apk add --no-cache docker + +WORKDIR /app + +COPY main.sh . + +CMD ["sh", "main.sh"] diff --git a/scalabilite/main.sh b/scalabilite/main.sh new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391