Are there any code examples on how to achieve this on the server side? From what it seems I have to run a websocket server on each machine/process? I would expect to be able to have a master process that handles all incoming websocket connections and then just proxies them to the other processes/machines for the rooms running there to handle. Maybe I am missing something?
Scaling
Hey @kodypeterson, welcome!
If you're using just multiple processes on the same machine, you can use the memshared
as presence provider. If you're using on multiple servers/processes you can use redis
.
Here's the documentation for the presence
attribute: http://colyseus.io/docs/api-server/#optionspresence
Cheers!
@endel thanks for the response. I understand this. I am trying to figure out what the code looks like on a process that is only managing a room.
I am using redis for presence. But I can't seem to get another process that only manages a room going.
@endel Maybe some example code from my end to help:
if (args.room) {
console.log ('MODE: ROOM');
console.log ('ROOM: ' + args.room);
const gameServer = new colyseus.Server({
presence: new colyseus.RedisPresence()
});
gameServer.register(args.room, roomHandlers[args.room]);
} else {
console.log ('MODE: MANAGER');
// This is the main and manager
const gameServer = new colyseus.Server({
presence: new colyseus.RedisPresence()
});
// gameServer.register("game", roomHandlers["game"]);
gameServer.attach({ server: httpServer });
gameServer.listen(port);
console.log(`Listening on http://localhost:${ port }`);
}
I would run this process twice. One without the room argv and another with.
@kodypeterson I see! Every process should have the registered handlers. (There is no such thing as a room manager)
I need to document how scaling works under the hood. But, basically, the client messages are forwarded from one process to another when using Redis - in case the room lives on a different process/machine.
@endel This does not seem to be the case. I have created a "noop" handler now. Essentially just returns false for onRequestJoin
and still the other process does not get triggered.
if (args.room) {
console.log ('MODE: ROOM');
console.log ('ROOM: ' + args.room);
const gameServer = new colyseus.Server({
presence: new colyseus.RedisPresence()
});
gameServer.register("game", roomHandlers["game"]);
} else {
console.log ('MODE: MANAGER');
// This is the main and manager
const gameServer = new colyseus.Server({
presence: new colyseus.RedisPresence()
});
gameServer.register("game", roomHandlers["noop"]);
gameServer.attach({ server: httpServer });
gameServer.listen(port);
console.log(`Listening on http://localhost:${ port }`);
}
Hey @kodypeterson, please try without having the first if
block, it should be fine, then! Just like this example: https://github.com/gamestdio/colyseus/blob/master/usage/ServerScale.ts
@endel ok this is where I am at. Still no good:
const gameServer = new colyseus.Server({
verifyClient: (info, next) => {
// console.log("custom verifyClient!");
next(true);
},
presence: new colyseus.RedisPresence()
});
if (args.room) {
gameServer.register("game", roomHandlers["game"]);
} else {
gameServer.register("game", roomHandlers["noop"]);
}
gameServer.attach({ server: httpServer });
if (args.room) {
gameServer.listen(port+1);
} else {
gameServer.listen(port);
}
console.log(`Listening on http://localhost:${ port }`);
I am still doing the noop thing so that I can force colyseus to try and use the second process.
@endel So, I got this working by calling gameServer.matchMaker.create("game", {});
after registering (I only do this on the second process).
It seems that the you are only subscribing to presence when the room is created. There is no knowledge that a registered handler is registered within presence. So, I have manually created the room on startup.
This probably is not the best way, but it works for now while you can think about how we would want to solve for making the other game servers aware that a room is registered but not yet created.