{"id":12666,"date":"2017-08-28T17:37:55","date_gmt":"2017-08-28T15:37:55","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=12666"},"modified":"2017-08-28T17:39:15","modified_gmt":"2017-08-28T15:39:15","slug":"node-js-parallelizzare-il-lavoro-con-il-modulo-cluster","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/node-js-parallelizzare-il-lavoro-con-il-modulo-cluster\/","title":{"rendered":"Node.js: parallelizzare il lavoro con il modulo cluster"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/introduzione-a-node-js\/\" target=\"_blank\" rel=\"noopener\">Node.js<\/a> deve\u00a0buona parte del\u00a0suo successo all&#8217;efficienza che lo contraddistingue: consuma poche risorse e lavora su un unico thread permettendo comunque attivit\u00e0 asincrone.\u00a0Questi ed altri vantaggi l&#8217;hanno reso molto utile per creare servizi di piccole dimensioni in grado di\u00a0modularizzare il lavoro: approccio ideale in un&#8217;epoca che vede il successo delle architetture basate su\u00a0<a href=\"http:\/\/www.devapp.it\/wordpress\/microservizi-per-logiche-applicative-di-grandi-dimensioni\/\" target=\"_blank\" rel=\"noopener\">Microservizi<\/a>.<\/p>\n<p>Il modulo di cui parliamo oggi si chiama <strong>cluster<\/strong> e permette di parallelizzare il lavoro creando un processo server in grado di generare suoi propri figli tramite il metodo <em>fork<\/em>.<\/p>\n<p>Ribadiamo che stiamo trattando di creazione di processi multipli, quindi non multi-threading in uno stesso processo, pertanto i <em>worker<\/em>, ossia i processi figlio, potranno\u00a0comunicare tra loro\u00a0utilizzando\u00a0le tecniche di IPC (InterProcess Communication).<\/p>\n<p>Vediamo come funziona questo modulo:<\/p>\n<ol>\n<li>scriveremo una porzione di codice che dovr\u00e0 essere svolta dal <strong>processo iniziale<\/strong>, detto <strong>master<\/strong>, nella quale essenzialmente andremo ad effettuare le <em>fork<\/em> per creare i processi figlio;<\/li>\n<li>nella porzione di script\u00a0relativo ai <strong>processi figlio<\/strong> eseguiremo il codice che vorremo parallelizzare. Si noti a questo punto che, in un cluster, tipicamente tutti i processi figlio svolgono lo stesso tipo di attivit\u00e0.<\/li>\n<\/ol>\n<p>Molto interessante \u00e8 anche\u00a0considerare che se nel codice dei processi\u00a0<em>worker<\/em> attiveremo un servizio &#8211; ad esempio, <a href=\"http:\/\/www.devapp.it\/wordpress\/creare-api-rest-con-node-js-ed-express-js\/\" target=\"_blank\" rel=\"noopener\">API REST con Express<\/a> &#8211; <strong>tutti i processi figlio rimarranno in ascolto sulla stessa porta<\/strong> creando effettivamente un cluster in grado di bilanciare il carico di risposta di un medesimo servizio.<\/p>\n<p>Nell&#8217;esempio seguente, creiamo un servizio REST, con tanti processi figlio quanti ne permette il processore (tramite il <strong>modulo os<\/strong> verifichiamo il numero di CPU disponibili) ed ogni figlio eseguir\u00e0 le API Express sulla stessa porta TCP, in questo caso la 4200:<\/p>\n<pre class=\"lang:js decode:true\">var cluster = require('cluster');\r\n\r\nif(cluster.isMaster) {\r\n    \r\n    \/\/ codice processo master: facciamo partire i processi worker\r\n    var numCPU = require('os').cpus().length;\r\n\r\n    \/\/ eseguiamo tante fork quanti sono le CPU disponibili\r\n    for(var i = 0; i &lt; numCPU; i++) {\r\n        cluster.fork();\r\n    }\r\n\r\n} else {\r\n    \/\/ codice del processo worker\r\n    var app = require('express')();\r\n\r\n    app.get('\/', function (req, res) {\r\n\tres.send('Risposta dal processo ' + process.pid);\r\n    });\r\n\r\n    var server = app.listen(4200, function() {\r\n        console.log('Avviato processo con PID ' + process.pid);\r\n    });\r\n\r\n   \r\n}<\/pre>\n<p>All&#8217;interno del codice dei worker (nel blocco <em>else<\/em>, in pratica) abbiamo disponibile anche la variabile <em>process<\/em> tramite la quale potremo leggere il PID, l&#8217;identificativo univoco che distingue il processo nel sistema operativo.<\/p>\n<p>Sull&#8217;oggetto cluster potremo anche reagire ad una serie di <strong>eventi<\/strong>\u00a0relativi ai processi worker come <em>online<\/em> che ne segnala l&#8217;entrata in funzione ed <em>exit<\/em> che ne notifica la conclusione del lavoro.\u00a0La sintassi di impiego sar\u00e0 la seguente:<\/p>\n<pre class=\"lang:js decode:true\">var cluster = require('cluster');\r\n...\r\n...\r\ncluster.on('online', function(worker) {\r\n     \/* worker (un processo figlio) entrato in esecuzione\r\n        tramite worker.process ne possiamo leggere le propriet\u00e0 *\/\r\n    });<\/pre>\n<p>&nbsp;<\/p>\n<p>Ecco un altro esempio di come Node.js sia in grado fornire un servizio utile con poche righe di codice. Efficienza, flessibilit\u00e0 e semplicit\u00e0: queste le sue parole d&#8217;ordine.<br \/>\nChe ne pensate? Fateci sapere!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Node.js deve\u00a0buona parte del\u00a0suo successo all&#8217;efficienza che lo contraddistingue: consuma poche risorse e lavora su un unico&#8230;<\/p>\n","protected":false},"author":561,"featured_media":12967,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[481,1],"tags":[1624,1826,1822,1825,1824,1538,1823,1633,1537],"class_list":["post-12666","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-risorse-utili","category-tutorial-pratici","tag-api-rest","tag-cluster","tag-express","tag-interprocess-communication","tag-ipc","tag-javascript","tag-multi-process","tag-multi-threading","tag-node-js"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12666","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=12666"}],"version-history":[{"count":5,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12666\/revisions"}],"predecessor-version":[{"id":13219,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12666\/revisions\/13219"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/12967"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=12666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=12666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=12666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}