Master server design

Isn’t this a fairly standard AJAX use-case for long-polling, etc.? (Caveat: I have not done web development like this in many many years.)

Yes, I think, except that in AJAX long-polling connection closed after the client receives data and then opens a new connection (?) whereas in SSE the connection is kept open.

AJAX long-polling:

Server-Sent Events

Server-Sent Events (SSE) is the new kid on the block in the world of client/server communication. It’s introduced as a part of HTML 5 standard which is not supported by Internet Explorer . So it is not the best option if your application must support legacy browsers.

SSE has two major differences with WebSocket:

  • The communication is unidirectional
  • The client/server communication is over HTTP

In SSE an HTTP connection establishes between client and server, similar to Rest API which never closes. Then the server can stream data to the client whenever is needed. But the client cannot communicate with the server over the same connection. The client has to request for any data using the conventional Rest APIs. In other words, SSE is exactly the opposite of the Ajax polling.

SSE

SSE (source: https://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet?answertab=votes#tab-top by Tieme)

source:

1 Like

Sounds useful. I’ve never used it, but it seems like it would fit the bill for notifications and such.

1 Like

Hey guys,
Another question!

Suppose I have developed two games, let’s say App-1 and App-2 both of these games have lobby features. The functionality of lobby service is the same for all.

I can see two approaches to handle this on master server:

1- Having one lobby service (one war file connected to one data base) that handles lobby for all apps. And endpoint is dynamic like this

/{appName}/lobbies

2- Having two lobby services (2 war files with separate databases) each handles one app. And endpoints are hardcoded like this

/app-1/lobbies

/app-2/lobbies

Which approach do you recommend?

Regards

From a developers point of view, the first would save me a lot of repeated code if all that was different was the name. The second would allow me to use separate code for separate logic.

1 Like

There won’t be repeated code in the 2nd approach as well.

Just need to change these settings in the application.properties once for each app before building the war file:

spring.data.mongodb.database= # once with app-1 DB and once with app-2 DB
spring.data.mongodb.port=
spring.data.mongodb.host=

server.servlet.context-path= # once with /app-1 and once with /app-2

Then the first approach seems like it has less maintenance. Once you’ve written the code for invalid app names (just a 404 redirect) it’s all set up.

1 Like

One concern I have with the first approach is that database (in my case it is a single MongoDB) size might drastically grow up as it holds data for all users of all apps now and I might hit performance issues.

@jayfella is this something to worry about?

Sorry if sounds stupid question :slightly_smiling_face:

Well… You shouldn’t need to worry about the row count of your database. Some database systems have caches that alleviate the strain. Column count is something you can control - and it’s always a good idea to make sure you aren’t creating columns you don’t really need.

I’m not a database expert, but I have a lot of experience and time using them. If the users are universal across all apps it would make sense to keep them in the same database. It might even make sense to separate that data from the other data if that’s the only similarity - that is to say there is one account for multiple different games. That would be called an SSO auth scheme.

2 Likes

Okay, I see. Thanks so much for the helps

And yes, of course, user account data will be shared across all apps and will be handle in a separate module (SSO) on a single database, my point mostly was about per app related stuff like the lobby data, player campaigns,…

If it bears no relation to all of the apps it shouldn’t be in the same database. It sounds to me like you want a users database and individual databases for each app - because each one bears no relation to the other.

1 Like

Yes, exactly.

And I thought this is possible only through the 2nd approach with separate war files for each app, Yes?

It would make sense to, yeah. One app for the accounts and one for each app. This way if one app goes down they can still log in and use the apps that aren’t down. And subsequently you can take one app down for maintenance and leave the rest of the services available.

It seems like a cluster-f*ck but it will mean you can pretty much leave the accounts alone once it’s done, and in terms of maintenance your separation will save you from going bald dealing with so much code that doesn’t even relate to one another.

1 Like

I should probably explain this a little more, too.

  • Always store files in a file system. Images are a great example of this.
  • If you rarely pull additional profile data (about me, description, my website, my address, etc) don’t put it in the user object. Put it in a separate object. This way if there is no additional data (the user didn’t provide any) you can just return null (no additional data) and every single row of users isn’t populated with mostly empty columns. You’ve saved yourself pulling x columns of empty data for each user that is queried - and not even needing it most of the time except for when they click the profile page - which is rare in comparison. The profile table will probably receive a single digit percentage of the traffic of the user table.
2 Likes

Yeah, will keep in mind. Thanks

Just to be sure I am still in the right path!

@jayfella now that I have a separate server for the account and each app, does it make sense to switch my JWT auth algorithm from HS512 hash-based authentication to the RS256 signature?

So each app can authenticate requests independently by using the shared public key.

If you mean RS256 - yes. A public/private key will just make things a lot more secure since you can’t control the client.

1 Like

Yes RS256

And thank you for the quick response. :slightly_smiling_face:

1 Like

So far so clear

What about when some client wants to connect to the game server.

Suppose client has already got the ip:port of the game server from the master server and now wants to make a connection to game server.

Should I also give the client a temporary access token to use when connecting a game server? So the game server can also safely authenticate who is being connected, either doing itself by using the shared public-key or by asking from the master server.

Yes. Of sorts.

The user requests to join with their session ID they got when they logged in.

GameServer checks SID with auth server and accepts/rejects.

If accepted, auth server sets “active game” column to server token.

Their Session ID can only be part of one game. To do that you bind an “active game” column to a user. This stops single users logging into multiple games (account sharing).

Now you know who is connected to what. But you don’t want to keep querying the main server after they have joined successfully. From here-on you can accept the connection as valid.

Send the user back a token from the game-server. Do NOT use the original SID because that’s a password for all intent with ALL permissions. Use that token as a user reference to communicate bi-directionally.

1 Like