I had a bunch of questions about why it had "Zero" in the name, and why should I use this instead of just building RPC on ØMQ (zeromq). Then I went to the Github page.
Currently using 0MQ to set up our cluster...handles concurrency, the guide has plenty of thorough examples (not to mention it's humorous, and it has examples in every mainstream language (C, C++, python, java, ruby, haskell, etc).
It would be nice if the protocol was published. I understand it's just msgpack and zeromq, but exception handling and message ID's escape me until I dig into the source (or finding the wire format on the pycon notes). I could definitely see myself (or someone else) creating a compatible, low-level C implementation of both a server and a client.
The documentation is pretty sparse, a few questions:
- How does it handle concurrency? Is each procedure run in a Python thread? Process? Gevent thread?
- How does it handle faults and recovery?
- Do you differentiate errors on the RPC layer with that on the procedure layer? For example, what if the RPC call I do does an RPC call that times out?
On a philosophical note, I'm not sure more RPC layers are what the world needs. The transparency a library like this gives you is really a big lie unless you are willing to accept that any call can now be an RPC one. Otherwise it greatly affects the correctness of your program (method M can now fail with some network failure).
Faults are handled differently depending on whether they are ZeroRPC-layer errors or application errors. To maintain the integrity of the connection itself, there is a heartbeat system independent of any given request. There is also an optional timeout that can be set for a given call's response. Application-level errors are propagated as "RemoteError" exceptions in the python interface. In order to collect more info about remote errors, there is also support for ZeroRPC[0] in Raven[1], the Sentry[2] client (Disqus' error logging system). In any failure case, both sides of the connection are notified and given an opportunity to clean up after themselves.
As to the philosophical concerns, I do agree on some level: RPC in general (and ZeroRPC in particular) are powerful weapons that need to be treated with care. That being said, there are a number of cases that are greatly simplified by the higher-level abstractions and more-robust error handling ZeroRPC provides.
Thanks for the detailed criticism and the kind words.
All procedures are run in their own gevent thread.
Yes, we differentiate errors on the RPC layer - there is a builtin heartbeat system so timeouts can be detected even when the procedure returns an infinite stream (think logs or system metrics). There is no built-in retry mechanism.
On the philosophy question: we discourage "pretending" that a call is local. That lead to the demise of original rpc and as you point out leads to weak systems. It remains the job of the developer to be aware of the network boundary and design accordingly.
It's such a grief that there is no ruby support yet. It would help a lot with our current project where we have site written in ruby/rails and backend services in python. We currently use Redis a broker between the two. At the same we've been looking at zeromq as a possible and simpler alternative.
Can developers share some info about their current roadmap? What languages will be supported next?
We did python and node.js first because we use them a lot internally. There's no firm roadmap for future implementations, but we're hoping once the protocol is well-documented, implementations can start growing organically.
We started writing zerorpc in 2010. We did test msgpack-rpc at the time, but it was barely a proof-of-concept.
A few key differences: zerorpc supports zeromq (including pub-sub and push-pull topologies), streaming responses, and has a bunch a of great instrumentation built on top of it.
Somewhat of a side-note, but interestingly enough, MessagePack's author cited ZeroRPC as a good example of MessagePack's use case: https://gist.github.com/2908191
One of my clients has been looking at implementing back-end communications between processes, including transaction handoffs... using RPC calls. We had been looking at using dnode, but I've noticed zeroRPC before as well. Is there anyone out there with experience using both or programming for both at least that has any input?
I did not play with dnode long enough to judge it. On the other hand, I can give some details about zerorpc that might help you to determine if it will be a better fit or not.
zerorpc support:
heartbeat: on remote loss, any pending action is canceled (either on server or client side), and your application is notified properly. You can disable the heartbeat. You can also require that a client wait for a server to come to life before checking for a heartbeat.
timeout: you can specify a timeout for how long a request should take (independently of any heartbeat).
streaming: one call, and a stream as a result. Its serves two purposes:
- transferring data sets that that would not fit in memory as well as reducing the transfer latency for big data.
- push/pull stream to get events whenever they come. The client effectively "subscribe".
Note that it's up to you to decide what to do when a client can't consume the stream fast enough, so you can do push/pull style (server blocks for client), pub/sub style (server discards messages), punish style (server shits on the client ;)).
Both implementations use asynchronous io. The difference is simply the API they expose - each implementation simply uses the best api available. With Node the dominant programming model is callback-based so that's what is used. Python has the advantage of a strong and well-supported coroutine library (gevent) so python developers aren't used to putting up with callback spaggheti.
tl;dr zerorpc is agnostic and each implementation uses the best tool for the job.
Looks very convenient. Are their any plans for other language support (in particular on the client side). Ruby and PHP client libraries would be useful.
[+] [-] jcromartie|13 years ago|reply
You should mention ØMQ on the front page!
[+] [-] capkutay|13 years ago|reply
[+] [-] m0th87|13 years ago|reply
[+] [-] kodablah|13 years ago|reply
[+] [-] m0th87|13 years ago|reply
[+] [-] sausagefeet|13 years ago|reply
- How does it handle concurrency? Is each procedure run in a Python thread? Process? Gevent thread?
- How does it handle faults and recovery?
- Do you differentiate errors on the RPC layer with that on the procedure layer? For example, what if the RPC call I do does an RPC call that times out?
On a philosophical note, I'm not sure more RPC layers are what the world needs. The transparency a library like this gives you is really a big lie unless you are willing to accept that any call can now be an RPC one. Otherwise it greatly affects the correctness of your program (method M can now fail with some network failure).
That being said, good work!
[+] [-] gabrielgrant|13 years ago|reply
Faults are handled differently depending on whether they are ZeroRPC-layer errors or application errors. To maintain the integrity of the connection itself, there is a heartbeat system independent of any given request. There is also an optional timeout that can be set for a given call's response. Application-level errors are propagated as "RemoteError" exceptions in the python interface. In order to collect more info about remote errors, there is also support for ZeroRPC[0] in Raven[1], the Sentry[2] client (Disqus' error logging system). In any failure case, both sides of the connection are notified and given an opportunity to clean up after themselves.
As to the philosophical concerns, I do agree on some level: RPC in general (and ZeroRPC in particular) are powerful weapons that need to be treated with care. That being said, there are a number of cases that are greatly simplified by the higher-level abstractions and more-robust error handling ZeroRPC provides.
------
[0]: http://raven.readthedocs.org/en/latest/config/zerorpc.html [1]: https://github.com/dcramer/raven [2]: https://github.com/dcramer/sentry
[+] [-] shykes|13 years ago|reply
All procedures are run in their own gevent thread.
Yes, we differentiate errors on the RPC layer - there is a builtin heartbeat system so timeouts can be detected even when the procedure returns an infinite stream (think logs or system metrics). There is no built-in retry mechanism.
On the philosophy question: we discourage "pretending" that a call is local. That lead to the demise of original rpc and as you point out leads to weak systems. It remains the job of the developer to be aware of the network boundary and design accordingly.
[+] [-] shykes|13 years ago|reply
[+] [-] m0th87|13 years ago|reply
Python: http://news.ycombinator.com/item?id=3761954
Node.js: http://news.ycombinator.com/item?id=4137576
[+] [-] densh|13 years ago|reply
Can developers share some info about their current roadmap? What languages will be supported next?
[+] [-] lonestar|13 years ago|reply
[+] [-] m0th87|13 years ago|reply
[+] [-] shykes|13 years ago|reply
[+] [-] cshenk|13 years ago|reply
http://msgpack.wordpress.com/category/messagepack-rpc/ http://wiki.msgpack.org/display/MSGPACK/Design+of+RPC
How zeroRPC differs from that in performance, perspective and status? Did you know of msgpack-rpc when started zeroRPC?
[+] [-] shykes|13 years ago|reply
A few key differences: zerorpc supports zeromq (including pub-sub and push-pull topologies), streaming responses, and has a bunch a of great instrumentation built on top of it.
[+] [-] m0th87|13 years ago|reply
[+] [-] druiid|13 years ago|reply
[+] [-] bombela|13 years ago|reply
zerorpc support:
heartbeat: on remote loss, any pending action is canceled (either on server or client side), and your application is notified properly. You can disable the heartbeat. You can also require that a client wait for a server to come to life before checking for a heartbeat.
timeout: you can specify a timeout for how long a request should take (independently of any heartbeat).
streaming: one call, and a stream as a result. Its serves two purposes: - transferring data sets that that would not fit in memory as well as reducing the transfer latency for big data. - push/pull stream to get events whenever they come. The client effectively "subscribe".
Note that it's up to you to decide what to do when a client can't consume the stream fast enough, so you can do push/pull style (server blocks for client), pub/sub style (server discards messages), punish style (server shits on the client ;)).
-- fx
[+] [-] cmelbye|13 years ago|reply
[+] [-] DanielRibeiro|13 years ago|reply
It would be nice to show how to do asynchronous calls in python, and synchronous in node.js
[+] [-] shykes|13 years ago|reply
tl;dr zerorpc is agnostic and each implementation uses the best tool for the job.
[+] [-] sausagefeet|13 years ago|reply
[+] [-] al_james|13 years ago|reply
[+] [-] shykes|13 years ago|reply
[+] [-] eclark|13 years ago|reply