I just pushed the source for speedy, a non-blocking rpc library, to github. While there’s nothing super-new about it, I’ve found it useful in a few projects I’ve worked on, and so I pulled it out for others to make use of.
Speedy is non-blocking on the client and server side, relatively fast (~50k-requests/s), and straightforward to use. (The name is incidental – it was originally called HTTP/RPC, but it didn’t use HTTP, then jsonrpc, but it doesn’t use JSON, so it ended up being speedy, which at least is somewhat accurate.)
Installation is easy via pip or easy_install:
pip install speedy
Usage is straightforward. On the server side, you initialize the server with a handler object: methods are called on the handler object in response to RPC calls. Each method call on the server side takes a ‘handle’ as the first argument. When a result is ready, simply callhandle.done()
with the value to return.
On the client side, speedy adopts the Futures model found in some other libraries. Client side methods return immediately with a future object. The future object can be queried for completion (Future.done()
) and waited on (Future.wait()
). The non-blocking behavior is very convenient you want to execute a few hundred things in parallel and then wait for them.
Serverclass MyHandler(object): def foo(self, handle, arg1, arg2): handle.done(do_something(arg1, arg2)) import rpc.server s = rpc.server.RPCServer('localhost', 9999, handler=MyHandler()) s.start()
Clientimport rpc.client c = rpc.client.RPCClient('localhost', 9999) future = c.foo('Some data', 'would go here') assert future.wait() == 'Expected result.'
Why not eventlet/greenlet?
Eventlet adds user-level threading to existing code, and theoretically would be a perfect way to implement non-blocking RPC’s in a blocking style. Unfortunately, in my experience, it just doesn’t work enough of the time. Existing RPC libraries are not necessarily designed with massively multi-threaded systems, and the various issues that crop up when using eventlet make debugging just too painful. It’s better and faster just to handle non-blocking calls explicitly – if you as a user want a blocking interface, then by all means feel free to put eventlet on top of speedy.