Dean Winchester
Dean Winchester

Reputation: 659

realtime communication with ruby

I'm about to write a game server with ruby. One feature of the game includes player walking around & others should be able to see it.

I've already written a pure socket demo using event machine. But since most of the communication are going to be http-based, so I'm looking for some http polling solution. And of course I could write it with event machine, but is there any gem out there for this kind of job already?

I've tried something like faye, but most of these are for a messaging system, like subscribing & publish to a channel, I seem not to be able to control what clients I should push to. In my case I need to be able to push to specific clients, like one guy moves from 10,10 to 20,20, only those around him (maybe from 0,0 to 30,30, but not a guy at 40,50) need to receive the message.

------------pregress with cramp

Here's a quick update. I'm working on cramp, with 5000 connections, and 100 client move each second, the CPU usage is almost 100%. When I double both figures, the CPU usage is still 100% or so, and the response is very slow.

Clearly I'm not using every resource I had, instead there's only one CPU core occupied. Need more work on it.

------------Node.js's turn

@aam1r Actually Node.js is doing better than cramp. With 5000 connections and 100 client moving per seoncd, the Cpu usage is over 60%. When I doubled to 10000 connections and 200 client moving per second, the CPU usage is 100% and response is becoming slow. Same problem here, either cramp or Node.js can only use one cpu core per process. That's a problem.

------------What about JRuby?

Because of the presence of GIL, there's no true multi-thread simultanious execution with Ruby MRI. None with Node.js either.So I'm going to give JRuby a try.

Need some time to write a demo though.

Upvotes: 2

Views: 447

Answers (2)

Bill Parker
Bill Parker

Reputation: 135

I would recommend using Espresso with Server-Sent Events.

On the server-side you define a streaming action:

class App < E
  map :/

  attr_reader :connections

  def subscribe
    @connections ||= []
    stream :keep_open do |conn|
      connections << conn
      conn.callback { connections.delete conn }
    end
  end

  private
  def communicate_to_clients
    connections.each do |conn|
      conn << 'some message'
    end
end

The :keep_open option will instruct the server to not close connection.

Then open a connection with Javascript:

pool = new EventSource('/subscribe');
pool.on_message = function(msg) {
  // here you receive messages sent by server
  // via communicate_to_clients method
}

Upvotes: 2

Aamir
Aamir

Reputation: 5440

I would suggest not using polling. Polling would result in too much overhead since you'll be making new connections every time make a new request. Also, it won't be real-time enough for you (i.e. you will poll every X seconds -- not instantly)

Instead, I would suggest using something like Cramp. From their website:

Cramp is a fully asynchronous real-time web application framework in Ruby. It is built on top of EventMachine and primarily designed for working with larger number of open connections and providing full-duplex bi-directional communication.

All your clients would maintain a persistent connection through which they can send/receive messages. There won't be overhead of making a new connection every time and messages will be sent in real-time since clients won't be checking "every X seconds".

You can also use Node.js instead of Cramp. It's a Javascript framework that can be used to develop real-time applications.

Here are some more resources that should help you out:

Upvotes: 1

Related Questions