uWebSockets.js icon indicating copy to clipboard operation
uWebSockets.js copied to clipboard

Scaling PubSub

Open yovanoc opened this issue 3 years ago • 4 comments

Hello,

I have a question. How can we scale pubsub properly?

Context:

First, I use cluster or worker_threads for scaling. But There is a need to tell the main process to propagate because each process have his own uWebSockets app, kinda like this:

main process:


  cluster.on("message", async (child, data) => {
    if (
      ["broadcast"].includes(
        data.type
      )
    ) {
      for (const worker of Object.values(clusterMain.workers ?? [])) {
        worker?.send(data);
      }
    }
    // other things
  });



export async function broadcast(
  message: Message,
  topic = "broadcast"
) {
  const messageBuffer = messageToBuffer(message);

  if (topic !== "broadcast") {
    cluster.worker?.send({
      type: "broadcast",
      topic,
      messageBuffer
    });
  } else {
    app.publish(topic, messageBuffer, true, true);
  }
}

workers

cluster.worker?.on("message", data => {
  switch (data.type) {
    case "broadcast": {
      app.publish(data.topic, Buffer.from(data.messageBuffer), true, true);
      break;
    }
    default:
      break;
  }
});

But for debugging purposes I start to think that I can remove clustering in development to add a debugger to the process, then, do the horizontal scaling with Kubernetes, but the same problem will occur too.

So my question is, if there is a way to have a proper production scaling but without letting pubsub on the side.

Thanks !

yovanoc avatar Sep 06 '22 18:09 yovanoc

I would try to help but I am confused what exactly you are asking, what do you mean "without letting pubsub on the side" ?

e3dio avatar Sep 08 '22 01:09 e3dio

Your options are add more threads and/or add more servers, you can test to determine what combination is best for your app, you are suggesting you want single thread because it will simplify your app/debugging, that is probably fine, cloud providers charge per vCPU so adding thread on same machine cost same as adding thread on new server

e3dio avatar Sep 08 '22 02:09 e3dio

Yeah but the pubsub inside uWebSockets won't work if we create more instances inside k8s for example. We have to add a layer on top of that, because each instance have its own app and list of connected clients, I'm looking for a proper way to scale and have pubsub working without too much trouble

yovanoc avatar Sep 08 '22 05:09 yovanoc

Ok so your question is how to send messages between instances/servers, yes that is something you need to set up, not really that hard, broadcast to each other server what topic and what message to send. If you have groups of servers in different geographic regions you would broadcast message to each region, each region broadcasts message to each server

e3dio avatar Sep 08 '22 10:09 e3dio

The way I see it, it depends on the needs of your app:

  • if you plan to scale vertically or horizontally
  • how you plan to scale up and down (or scale out and in)
  • if you need fire-and-forget (pub/sub) or acknowledged (redis streams / kafka / rabbitmq)
  • message broker you're comfortable to use (redis / kafka / rabbitmq)
  • message broker client you're comfortable to use (js libraries as example: node-redis is stable but slow on some areas, ioredis is faster but buggy on some areas)
  • if you really really need it business-wise or you're just premature scaling

There were plans before on having something like those being built-in within uws but I don't think it really pushed through. (can someone confirm lol)

joshxyzhimself avatar Oct 06 '22 19:10 joshxyzhimself