realtime communication with ruby - 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.
When a client moves, use another thread to find all the other clients need to notify(which is a CPU-heavy work). Then push the result to a channel.
The main thread simply subscribes the channel. When it gets the result, push them to the clients.
Need some time to write a demo though.

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
}

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:
Slideshow on using Node.js with Ruby
Discussion on "Real time ruby apps: CRAMP vs NODE.JS"

Related

AJAX or WebSockets for a Heartstone-like game?

Game is a one-vs-one turn based 2D card management game to be played in a browser.
It is very much like Hearstone where a player plays a number of cards, observes effects and then passes turn to the opponent.
Game mechanics and prototype are ready and I need to decide on technology.
Server is PHP + MySQL, heard of node.js but have no experience with it.
I cannot have loss of packets, so need to use HTTP I guess.
Initial idea is to have scheduled AJAX call every 5 seconds to get game state for each client to check for:
end of turn
change of game state (and render animation based on it)
Obviously I would also need to validate every action of an active player on the server.
I am concerned of the number of calls to my server (not an expensive hosting) and how many calls would a modest server be capable of handling...
As a plus of Ajax I see guaranteed packet delivery and no issues with proxies involved (which may cut persistent connections).
Websockets reduce latency and server workload ( no need to open a new connection, meaning a key exchange in case of https), provided that you interact frequently.
A great advantage is that you are able to 'push' a message to the client (as opposed to having to 'pull' via Ajax every few seconds.
The server language shouldn't be a problem, but if you plan to maintain / extend it, you should choose carefully (I'm guessing you're a rather new programmer, thus gaining experience in a better suited environment would not be a huge amount of work).
Edit: just to clarify, I would recommend the usage of a websocket for your use case

Server architecture: websocket multicast server?

What would be the simplest way to build a server that receives incoming connections via a websocket, and streams the data flowing in that socket out to n subscribers on other websockets. Think for example of a streaming application, where one person is broadcasting to n consumers.
Neglecting things like authentication, what would be the simplest way to build a server that can achieve this? I'm a little confused about what would happen when a chunk of data hits the server. It would go into a buffer in memory, then how would it be distributed to the n consumers waiting for it? Some sort of circular buffer? Are websockets an appropriate protocol for this? Thanks.
Here's one using the Ruby Plezi framework (I'm the author, so I'm biased):
require 'plezi'
class Client
# Plezi recognizes websocket handlers by the presence of the
# `on_message` callback.
def on_message data
true
end
protected
# this will be out event.
def publish data
write data
end
end
class Streamer
def on_message data
Client.broadcast :publish, data
end
end
# the streamer will connect to the /streamer path
route '/streamer', Streamer
# the client will connect to the /streamer path
route '/', Client
# on irb, we start the server by exiting the `irb` terminal
exit
You can test it with the Ruby terminal (irb) - it's that simple.
I tested the connections using the Websocket.org echo test with two browser windows, one "streaming" and the other listening.
use ws://localhost:3000/streamer for the streamer websocket connection
use ws://localhost:3000/ for the client's connection.
EDIT (relating to your comment regarding the Library and architecture)
The magic happens in the IO core, which I placed in a separate Ruby gem (Ruby libraries are referred to as 'gems') called Iodine.
Iodine leverages Ruby's Object Oriented approach (in Ruby, everything is an object) to handle broadcasting.
A good entry point for digging through that piece of the code is here. When you encounter the method each, note that it's inherited from the core Protocol and uses an Array derived from the IO map.
Iodine's websocket implementation iterates through the array of IO handlers (the value half of a key=>value map), and if the IO handler is a Websocket it will "broadcast" the message to that IO handler by invoking the on_broadcst callback. The callback is invoked asynchronously and it locks the IO handler while being executed, to avoid conflicts.
Plezi leverages Iodine's broadcast method and uses the same concept so that the on_broadcast callback will filter out irrelevant messages.
Unicasting works a little bit differently, for performance reasons, but it's mostly similar.
I'm sorry for using a lot of shorthand in my code... pre-Ruby habits I guess. I use the condition ? when_true : when_false shorthand a lot and tend to squish stuff into single lines... but it should be mostly readable.
Good luck!

Is the mux in this golang socket.io example necessary?

In an app that I'm making, a user is always part of a 'game'. I'd like to set up a socket.io server to communicate with users in a game. I'm planning to use http://godoc.org/github.com/madari/go-socket.io go-socket.io, which defines the newSocketIOfunction to create a new socketio instance.
Instead of creating one socketio instance, I thought it might be possible to create a map that maps game id's to socket.io instances, and configure them so that they listen on an url that represents the game id.
This way, I can use methods such as broadcast and broadcastExcept to broadcast to all players ithin a single game. However, I'd have to start a new goroutine for every game, and I don't know enough about their performance characteristics to know if this is scalable, since the request rate for a single socketio instance will be very low, about 1/second at peak times, but the connection might be idle for tens of seconds at other times (except for heartbeat, and possibly other communication specified by the socket.io protocol).
Would I be better off creating 1 socket.io instance, and tracking which connections belong to which games?
I'd have to start a new goroutine for every game, and I don't know enough about their performance characteristics to know if this is scalable
Fire away, the Go scheduler is built to efficiently handle thousands and even millions of goroutines.
The default net/http server in the Go standard library spawns a goroutine for every client for instance.
Just remember to return from your goroutines once they're done working. Else you'll end up with a lot of stale ones.
Would I be better off creating 1 socket.io instance, and tracking which connections belong to which games?
I'm not involved in the project but if it follows Go's "get sh*t done" philosophy, then it shouldn't matter. You can find out what works better by profiling both approaches though.

what's the skinny on long polling with ajax and webapi...is it going to kill my server? and string comparisons

I have a very simple long polling ajax call like this:
(function poll(){
$.ajax({ url: "myserver", success: function(data){
//do my stuff here
}, dataType: "json", complete: poll, timeout: 30000 });
})();
I just picked this example up this afternoon and it seems to work great. I'm using it to build out some html on my page and it's nearly instantaneous as best I can tell. I'm a little worried though that this is going to keep worker threads open on my server and that if I have too big of a load on the server, it's going to stop entirely. Can someone shed some light on this theory? On the back end I have a webapi service (.net mvc 4) that calls a database, build the object, then passes the object back down. It also seems to me that in order for this to work, the server would have to be calling the database constantly...and that can't be good right???
My next question is what is the best way on the client to determine if I need to update the html on my page? Currently I"m using JSON.stringify() to turn my object into a string and comparing the string that comes down to the old string and if there's a delta, it re-writes the html on the page. right now there's not a whole lot in the object coming down, but it could potentially get very large and I think doing that string comparison could be pretty resource intensive on the client...especially if it's doing it nearly constantly.
bottom line for me is this: I"m not sure exactly sure how long polling works. I just googled it and found the above sample code and implemented it and, on the surface, it's awesome. I just fear that it's going to bog things down (on the server) and my way of comparing old results to new is going to bog thigns down (on the client).
any and all information you can provide is greatly appreciated.
TIA.
OK, my two cents:
As others said, SignalR is tried and tested code so I would really consider using that instead of writing my own.
SignalR does change some of the IIS settings to optimise IIS for this sort of work. So if you are looking to implement your own, have a look at IIS setting changes done in SignalR
I suppose you are doing long polling so that your server could implement some form of Server Push. Just bear in mind that this will turn your stateless HTTP machine into a stateful machine which is not good if you want to scale. Long polling behind a load ballancer is not nice :) For me this is the worst thing about server push.
ASP.NET uses ThreadPool for serving requests. A long poll will hog a ThreadPool thread. If you have too many of these threads you might end up in thread starvation (and tears). As a ballpark figure, 100 is not too many but +1000 is.
Even SignalR team say that the IIS box which is optimised for SingalR, probably not optimised for normal ASP.NET and they recommend to separate these boxes. So this means cost and overhead.
At the end of the day, I recommend to using long polling if you are solving a business problem (and not because it is just cool) because then that will pay its costs and overheads and headaches.
I agreee with SLaks - i.e. use SignalR if you need realtime web with WebApi http://www.asp.net/signalr. Long polling is difficult to implement well, let someone else handle that complexity i.e. use SignalR (natural choice for WebApi) or Comet.
SignalR attempts 3 other forms of communication before resorting to long polling, web sockets, server sent events and forever frame (here).
In some circumstances you may be better of with simple polling i.e. a hit every second or so to update... take a look at this article. But here is a quote:
when you have a high message volume, long-polling does not provide any substantial
performance improvements over traditional polling. In fact, it could be worse,
because the long-polling might spin out of control into an
unthrottled, continuous loop of immediate polls.
The fear is that with any significant load on your web page your 30 second ajax query could end up being your own denial of service attack.
Even Bayeux (CometD) will resort to simple polling if the load gets too much:
Increased server load and resource starvation are addressed by using
the reconnect and interval advice fields to throttle clients, which in
the worst-case degenerate to traditional polling behaviour.
As for the second part of you question.
If you are using long polling then your server should ideally only be returning an update if something actually has changed thus your UI should probably "trust" the response and assume that a response means new data. The same goes for any of the Server Push type approaches.
If you did move back down towards simple polling pullmethod then you can use the inbuilt http methods for detecting an update using the If-Modified-Since header which would allow you to return a 304 Not Modified, so the server would check the timestamp of an object and only return a 200 with an object if it had been modified since the last request.

Rack concurrency - rack.multithread, async.callback, or both?

I'm attempting to fully understand the options for concurrent request handling in Rack. I've used async_sinatra to build a long-polling app, and am now experimenting with bare-metal Rack using throw :async and/or Thin's --threaded flag. I am comfortable with the subject, but there are some things I just can't make sense of. (No, I am not mistaking concurrency for parallelism, and yes, I do understand the limitations imposed by the GIL).
Q1. My tests indicate that thin --threaded (i.e. rack.multithread=true) runs requests concurrently in separate threads (I assume using EM), meaning long-running request A will not block request B (IO aside). This means my application does not require any special coding (e.g. callbacks) to achieve concurrency (again, ignoring blocking DB calls, IO, etc.). This is what I believe I have observed - is it correct?
Q2. There is another, more oft discussed means of achieving concurrency, involving EventMachine.defer and throw :async. Strictly speaking, requests are not handled using threads. They are dealt with serially, but pass their heavy lifting and a callback off to EventMachine, which uses async.callback to send a response at a later time. After request A has offloaded its work to EM.defer, request B is begun. Is this correct?
Q3. Assuming the above are more-or-less correct, is there any particular advantage to one method over the other? Obviously --threaded looks like a magic bullet. Are there any downsides? If not, why is everyone talking about async_sinatra / throw :async / async.callback ? Perhaps the former is "I want to make my Rails app a little snappier under heavy load" and the latter is better-suited for apps with many long-running requests? Or perhaps scale is a factor? Just guessing here.
I'm running Thin 1.2.11 on MRI Ruby 1.9.2. (FYI, I have to use the --no-epoll flag, as there's a long-standing, supposedly-resolved-but-not-really problem with EventMachine's use of epoll and Ruby 1.9.2. That's beside the point, but any insight is welcome.)
Note: I use Thin as synonym for all web servers implementing the async Rack extension (i.e. Rainbows!, Ebb, future versions of Puma, ...)
Q1. Correct. It will wrap the response generation (aka call) in EventMachine.defer { ... }, which will cause EventMachine to push it onto its built-in thread pool.
Q2. Using async.callback in conjunction with EM.defer actually makes not too much sense, as it would basically use the thread-pool, too, ending up with a similar construct as described in Q1. Using async.callback makes sense when only using eventmachine libraries for IO. Thin will send the response to the client once env['async.callback'] is called with a normal Rack response as argument.
If the body is an EM::Deferrable, Thin will not close the connection until that deferrable succeeds. A rather well kept secret: If you want more than just long polling (i.e. keep the connection open after sending a partial response), you can also return an EM::Deferrable as body object directly without having to use throw :async or a status code of -1.
Q3. You're guessing correct. Threaded serving might improve the load on an otherwise unchanged Rack application. I see a 20% improve for simple Sinatra applications on my machine with Ruby 1.9.3, even more when running on Rubinius or JRuby, where all cores can be utilized. The second approach is useful if you write your application in an evented manner.
You can throw a lot of magic and hacks on top of Rack to have a non-evented application make use of those mechanisms (see em-synchrony or sinatra-synchrony), but that will leave you in debugging and dependency hell.
The async approach makes real sense with applications that tend to be best solved with an evented approach, like a web chat. However, I would not recommend using the threaded approach for implementing long-polling, because every polling connection will block a thread. This will leave you with either a ton of threads or connections you can't deal with. EM's thread pool has a size of 20 threads by default, limiting you to 20 waiting connections per process.
You could use a server that creates a new thread for every incoming connection, but creating threads is expensive (except on MacRuby, but I would not use MacRuby in any production app). Examples are serv and net-http-server. Ideally, what you want is an n:m mapping of requests and threads. But there's no server out there offering that.
If you want to learn more on the topic: I gave a presentation about this at Rocky Mountain Ruby (and a ton of other conferences). A video recording can be found on confreaks.

Resources