You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to create a cluster but with some custom load balancing logic. It's actually more complicated than "I want a custom scheduling strategy" hence I need custom JS logic, plus cluster module doesn't even support custom load balancing algorithm anyway.
It occurred to me, what I can do is,
Create 10 worker processes using child_process
Have the master process listens on a port
Pass over the socket object to worker process (and before that, apply custom JS logic)
The worker process takes over and handles the request
Here's my question: It seems that this is a very easy way to "reinvent" cluster module, without the extra magic and limitation.
It feels too good to be true. Am I missing anything here?
Here's a code snippet I tried locally by adopting some of the examples online
master.js
const{ fork }=require("node:child_process")constchildren=[]for(leti=0;i<10;i++){children.push(fork("./worker.js"))}letloadBalancingIndex=0// Open up the server and send sockets to child. Use pauseOnConnect to prevent// the sockets from being read before they are sent to the child process.constserver=require("node:net").createServer({pauseOnConnect: true})server.on("connection",socket=>{console.log("receive connection",loadBalancingIndex)children[loadBalancingIndex].send("socket",socket)loadBalancingIndex=(loadBalancingIndex+1)%children.length})server.listen(8008)
worker.js
consthttp=require("http")constexpress=require("express")constapp=express()constserver=http.createServer(app)console.log(`worker pid=${process.pid}`)app.get("/heavy",(req,res)=>{lettotal=0for(leti=0;i<5_000_000;i++){total++}res.send(`The result of the CPU intensive task is ${total} (${process.pid})\n`)})process.on("message",(m,socket)=>{if(m==="socket"){if(socket){server.emit("connection",socket)}}})
here's a corresponding example using cluster.
server.js
constexpress=require("express")constport=8008constapp=express()console.log(`worker pid=${process.pid}`)app.get("/heavy",(req,res)=>{lettotal=0for(leti=0;i<5_000_000;i++){total++}res.send(`The result of the CPU intensive task is ${total}\n`)})app.listen(port,()=>{console.log(`App listening on port ${port}`)})
cluster.js
constcluster=require("cluster")constos=require("os")constcpuCount=10// os.cpus().lengthconsole.log(`The total number of CPUs is ${cpuCount}`)console.log(`Primary pid=${process.pid}`)cluster.setupPrimary({exec: __dirname+"/server.js",})for(leti=0;i<cpuCount;i++){cluster.fork()}cluster.on("exit",(worker,code,signal)=>{console.log(`worker ${worker.process.pid} has been killed`)console.log("Starting another worker")cluster.fork()})
The example is being adapted from here, and I used the same loadtest tool, both approaches seem to increase the RPS simiarly.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I'm trying to create a cluster but with some custom load balancing logic. It's actually more complicated than "I want a custom scheduling strategy" hence I need custom JS logic, plus
cluster
module doesn't even support custom load balancing algorithm anyway.It occurred to me, what I can do is,
child_process
Here's my question: It seems that this is a very easy way to "reinvent" cluster module, without the extra magic and limitation.
It feels too good to be true. Am I missing anything here?
Here's a code snippet I tried locally by adopting some of the examples online
master.js
worker.js
here's a corresponding example using cluster.
server.js
cluster.js
The example is being adapted from here, and I used the same loadtest tool, both approaches seem to increase the RPS simiarly.
Beta Was this translation helpful? Give feedback.
All reactions