Comment envoyer 200000 requêtes HTTP avec NodeJS ? A priori cette question semble facile ? Voyons si c'est le cas ?
Commençons petit
Avant d'envoyer plusieurs centaines de requêtes voyons déjà comment en envoyer une seule :
#!/usr/bin/env node var http = require('http'); var options = { host: '127.0.0.1', port: 80, path: '/' }; http.get(options, function(response) { console.log(response.statusCode); });
On boucle !
#!/usr/bin/env node var http = require('http'); var options = { host: '127.0.0.1', port: 80, path: '/' }; for(var i = 0; i < 2000000; i++) { http.get(options, function(res) { console.log(res.statusCode); }); }
Résultat :
FATAL ERROR: JS Allocation failed - process out of memory
Économiser la mémoire
Ok, on y a été un peu fort, on va optimiser notre boucle en sortant le client HTTP de la boucle, histoire de l'instancier qu'une seule fois.
#!/usr/bin/env node var http = require('http'); var client = http.createClient(80, '127.0.0.1'); for(var i = 0; i < 200000; i++) { var request = client.request("GET", '/') request.end(); request.on('response', function(response) { console.log(response.statusCode); }); }
Résultat :
node.js:205 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: EMFILE, Too many open files at net_legacy.js:741:19 at Object.lookup (dns_legacy.js:159:5) at Socket.connect (net_legacy.js:729:20) at Object.createConnection (net_legacy.js:268:5) at new ClientRequest (http2.js:1041:23) at Client.request (http2.js:1475:11) at Object.<anonymous> (/home/touv/tests/node/loop02.js:11:23) at Module._compile (module.js:416:26) at Object..js (module.js:434:10) at Module.load (module.js:335:31)
Oups, NodeJS est-il incapable d'exécuter un traitement aussi simple ? Ou mon code est-il mauvais ?
Pool HTTP Request
Pour lancer nos 200000 requetes, il va falloir économiser la mémoire et les descripteurs, mais surtout s'adapter au mode asynchrone et éviter de vouloir balancer 200000 requêtes en parallèle !
Pour nous aider, il existe le module node-pool qui propose :
"a small but usefull resource pooling/limiting/throttling library".
Voilà donc la solution à notre question toute simple ...
#!/usr/bin/env node var http = require('http'); var pool = require('generic-pool').Pool({ name : 'http_request', create : function(callback) { var c = http.createClient(80, '127.0.0.1'); callback(null, c); }, destroy : function(client) { }, max : 10, idleTimeoutMillis : 300, log : false }); for(var i = 0; i < 200000; i++) { pool.acquire(function(err, client) { var request = client.request("GET", '/'); request.end(); request.on('response', function(response) { console.log(response.statusCode); pool.release(client); }); }); }
Aucun commentaire:
Enregistrer un commentaire