15
\$\begingroup\$

Assume a simple standard client/server game. For the server, is it worthwhile to have a separate process that listens for connections and messages from clients and sends the data via local sockets or stdin to another process that runs the actual game server?

The other option would be to have both things be done in a single process. Queueing incoming messages and executing them in the right order there shouldn't be a halting issue.

I am wondering if the extra resources to separate the two "activities" is actually worth it. How should I decide? I'd like to hear any pros/cons.

\$\endgroup\$
  • 1
    \$\begingroup\$ How do both parts communicate? Sockets? \$\endgroup\$ – vz0 Dec 12 '14 at 8:59
  • \$\begingroup\$ Do you envisage yourself changing the "listener" to use a different communication technique, or adding options to use more than one type of client-server communication (eg if mobile clients had to communicate in a different way)? If so, it may be worth separating it so that you can swap the modules in/out as required. \$\endgroup\$ – Jon Story Dec 12 '14 at 11:17
  • \$\begingroup\$ @JonStory Yes, I do. Even with 2 different listeners it still could be a single process though, but after reading all the answers in here and thinking some more about it, I have decided that it will be worth it to have separate processes. For this particular project the main client will be a javascript browser one, but I plan to add a native mobile client app in the future. \$\endgroup\$ – luleksde Dec 12 '14 at 12:05
18
\$\begingroup\$

From an API design perspective, when deciding whether to make multiple separate communicating programs or just one, the question is: can each program function meaningfully without the others? The answer will vary based on your project and preferences.

If they can't, it's not worth thinking about. Clearly they're so heavily linked that they're not really separate processes.

If they can, and you can see yourself wanting to drop in different components to replace them in the future, then an OS-provided process abstraction might help.

How much it helps depends on the rest of your tech stack though. For example Erlang internally models things as processes already, so you won't gain much of a conceptual benefit from splitting it into OS-processes too. Unless you're thinking of maybe rewriting those parts of the server in a different language. A C++ program's internal components are typically coupled much tighter and hence be harder to swap out, hence splitting them into different OS processes can save you work later if you can foresee such rearrangements.

\$\endgroup\$
12
\$\begingroup\$

is it worthwhile to have a separate process that listens for connections and messages from clients and sends the data via local sockets or stdin to another process that runs the actual game server?

To answer whether it is worthwhile, you had to first ask yourself, what is the problem you are trying to solve by adding a dedicated queuing service. If it solves that problem, then it is worthwhile; if it doesn't solve a problem or if you don't have a problem to solve to begin with, then it's probably not.

Let's see some reasons why some servers use a multi-tier architecture:

  1. Load balancing - load balancing make sense if you want to spread your workload over to multiple worker machines. If your program have bottlenecks that you want to solve simply by having multiple concurrent worker process on the same machine, then it's best in the long run to actually solve the bottleneck, but as a short term workaround, spawning worker processes could be practical.
  2. Privilege separation - Maybe you don't want a security breach into your chat server to automatically gain access of your game server or vice versa. If your game server is separate from your in-game chat server, you can configure your game server and chat server to live in separate security domain (e.g. run as different user, with different access privileges, different process limits, etc).
  3. Zero downtime upgrade - if you want to achieve zero downtime upgrade, you need to have multiple tiers and configure the system such that when you take down a server for servicing, its requests will be redirected to the other servers in the same tier to ensure continuous service.
  4. Breaking limit - if you reach the socket limit, file descriptor limit, a global interpreter lock, etc, you may be able to work around that limit by running multiple processes. Another way to solve this is to change the limit, but that's not always easy as you may have to recompile the kernel, or there may be security or performance implications.
  5. Limiting resources leakage - you want to write software that doesn't leak resources, but even in fully garbage managed languages this is extremely hard in a long-lived processes, and worse this is hard to replicate in a development environment. A multitier architecture allows you to kill and respawn the game servers after certain amount of time or number of requests to limit the damages from resource leakages, without disrupting service.
\$\endgroup\$
5
\$\begingroup\$

I agree with ratchet freak. As long as you have a single gameserver, it's not worth the trouble.

However, this architecture might prove useful when you need to scale up horizontally. When one gameserver is no longer enough and you need to distribute your game on multiple gameservers for performance reasons, the "socket server" architecture could very easily be adapted to turn the socket server into a load balancer which automatically routes connections to one of many backend server.

But when you aren't sure you will ever need this, it is likely overengineering to develop two separate server applications at this point.

\$\endgroup\$
4
\$\begingroup\$

It probably isn't, most languages has asynchronous sockets that allow you to use multiple connections at a time without blocking while data is waiting. This shifts the "socket server" part to the OS/kernel.

With an explicit socket server you will incur the cost of a few extra copies as you pass the data through the local socket; one thing that will kill scalability is extra copies where you don't need them.

\$\endgroup\$
  • 1
    \$\begingroup\$ Unless you already know that your server will have very high scalability requirements, I wouldn't worry about performance at this stage. The overhead of copying some data in memory is vanishingly small compared to that of sending data over the internet. \$\endgroup\$ – Anko Dec 11 '14 at 12:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.