Deepworld's MMO dream team: Ruby, MongoDB, and the cloud
MMO servers are hungry beasts. They run cpu-intensive game logic and coordinate the actions of hundreds of players, all of whom have persistent TCP and/or UDP connections. You don't have the same overhead as HTTP, but you've got a lot more overall communication, and any real latency quickly becomes unforgiveable.
There's a lot of debate over the performance of Ruby versus other technologies, but if you can scale horizontally, it doesn't matter so much. If your developers know Ruby and can bust it out five times faster than a Java or C++ server, you're going to save time and money.
So for Deepworld, we chose Ruby, knowing in the back of our minds that we could also extend it with C if we needed to. Which we did - but only for our convoluted game logic and physics. After all, EventMachine is a wondrous and fast reactor-based server, the Ruby equivalent of Node.js except with a decade of maturity under its belt. We actually did try Node.js out at first, because it's apparently The Hotness, plus coffeescript is pretty sweet. However, the integration challenges and relative youth of its many libraries quickly scared us off. The argument for Node.js as compared to EventMachine is generally "Node.js is built from the ground up to be callback-based, whereas you have to use specific libraries in EventMachine, and also V8 blah blah."
<snark> Wait! I have to use SPECIFIC libraries! That is so much work! Clearly I should instead go with a fledgling technology, because bandwagons are fun. </snark>
Speaking of bandwagons, we opted to use MongoDB as our data store, and it has been rather awesome. Schemas are for suckers.
We've eked out a ton of performance with relatively few problems by using a fairly simple architectural strategy:
Spin up lots of servers, each hosting multiple worlds (effectively sharding the MMO's universe)
When a world loads, download (and "own") the data
Keep things mostly in memory, synching to MongoDB every so often
Be sure to synch to MongoDB if everything goes boom
Spin down when a world unloads
Ruby has been more than capable of handling loads in this fashion, and as mentioned, we can still get the benefit of super-fast C code with custom extensions. Our liquid dynamics, for example, are written in C because they involve a crapload of world lookups and changes. We also use C to generate noise for procedural world generation, but most of our logic is just good ol' vanilla Ruby.
Ultimately, developers are expensive (and grumpy), and servers are cheap.
We haven't done huge scaling tests yet, but we have successfully run a hundred simulated players on a world (over TCP) without too much trouble. And since we can limit the amount of players per world, and worlds per server, we're fairly confident things will be okay-ish. Naturally, we may be proven wrong, but it's worth it.
Because we're Rubyists, through and through.











