It's probably a bad idea to use durable sockets for reliable pubsub (I know I documented this in the Guide but that was before it became clear that this functionality is kind of bogus).
Explicit identities are dangerous for servers since they create entropy (state accumulation) unless (and even) if you set strict high-water marks.
They're also a real pain internally and as part of simplifying 0MQ's construction we eventually want to get rid of them.
There are better ways to keep and synchronize state among a set of subscribers. See the detailed Clone pattern in Ch5 of the Guide, for example.
1. The 0MQ devs originally got asserts backwards, using them to validate external input (e.g. on sockets) instead of internal consistency. We've been fixing this for a year or two now, and it's pretty good. You'll get assertion failures if you e.g. use sockets from multiple threads. Not so much if you pass bad stuff onto sockets.
2. 2.1 was a great step forwards, and the use of "sleep" was in toy examples. Real networking apps tend to run forever, so this message loss at exit wasn't a big deal. You're right that the product is still young.
3. Totally agreed, this lack of peer presence detection is annoying, and the source of some debate on the lists.
4. Threading model works fine for me, I've used it extensively. A usable reactor is a hundred lines of code, no more. See the libzapi zloop reactor, in C, for example.
5. Demultiplexing sounds like useful functionality but should probable sit above sockets.
Before I opened the 0MQ Pandora box I'd given up coding and was happily writing my autobiography. 0MQ seemed like a pleasant way to spend a weekend. But before I knew it, I'd lost control. Days, weeks, months have passed now, all I think about are more subtle and perfect messaging patterns. They flash before my eyes. Weird names and topologies. It doesn't get better, but worse. Soon I'll be coding all nighters, my wife will leave me, my kids will forget me, and all I'll be doing is programming, motherfucker.
Seriously, 0MQ has made network programming fun (again) in a bad, addictive, way. Any design I can think of turns into real working code in a few hours, sometimes days. And I'm using C, a language that isn't normally fun to work in.
Right now, it's multithreaded clients and servers for resilient shared distributed hash maps. Tomorrow, network-wide logging. After that, another message broker. And so on.
Yes, it's a negative experience. I'd like my old lazy life back.
It is challenging to explain anything subtle, when your viewpoint depends so much on what you already know, your preconceptions, and assumptions.
Sorry for the comic book style. It's how my mind works. Feel free to send a patch. :)
The benefits of 0MQ to me, as a programmer, are:
* Really easy to write utterly solid multithreading code, in a language (C) that has zero support for this;
* Really easy to take this same code and make it multiprocess, or multibox, with few changes.
* Built-in handling of asynchronous I/O, which I need in any real application.
* Speed, meaning I can be lazy and my code still runs very quicky. This is less obvious than it seems. 0MQ's critical path is extremely evil.
It's so hard to explain this with a diagram or a slideshow. The only way to understand is to use it, to write code with 0MQ. Certainly for me, when I started programming 0MQ apps, my understanding of what this library was about, and what it could do for me, totally changed.
Significantly simpler, faster, and more general. MPI is like one of the patterns ZeroMQ provides (the pipeline pattern) with a lot on top. That makes it great for parallel programming, but not so great for (e.g.) data distribution (pubsub) and other forms of message queuing.
You're right that a message queue is shared state and has to be gotten right but that can be done (and ZeroMQ does it) without locks. It's thus invisible to application developers. You're wrong to say that multiple threads serialize on a queue no matter how it's implemented. ZeroMQ lets threads write full speed to a queue while another thread reads full speed from the queue, without wait states.
Badly designed, anything can become hell. Crazy has no limits. The point of the talk was that message passing is fundamentally not at the same level as mutexes, semaphores, and monitors. Shared state does not scale linearly, no matter how well you use it, whereas message passing does, given cheap, fast, universal messaging.
:-) If you hope for enlightenment from watching a 10-minute talk, you're going to be disappointed. I do like your summary of the presentation... "Concurrency is hard... Actors... ZeroMQ... End scene!". Nice.
Enlightenment requires that you change in some way. For me, like many people who have taken the step of downloading and learning 0MQ, the feeling of "wow, this is too easy, where's the catch?" comes only after a few days writing code, and then your brain makes a slight adjustment, and it's all obvious, and that is a small but real enlightenment.
It's great to get feedback on the talk. Impossible to even introduce 0MQ properly in 10 minutes, so this presentation was really just to drive discussion. I'd apologise for the polemical title but that's just how I talk.
To some of the comments here...
- Parallel programming may be taught in CompSci courses, for sure, and it's a popular use for 0MQ, but (a) it's not applied to mainstream application development, and (b) it is not designed to scale to networks of any size.
- The Actor model is not key to building a successful message-based concurrent application, but it's a good example, and helps people understand that there are alternatives to shared-state concurrency.
- It's IMO useless to ask people to learn Erlang or Scala to get message based concurrency. People use Java, C, C#, PHP, Python, and probably still COBOL somewhere. So the challenge is how to give this mainstream a toolset that lets them build large parallel applications.
Perhaps next year at FOSDEM we can do a devroom and take the time to see a real application evolve from a simple stand-alone process into a real distributed one. 0MQ is very hard to grasp as a theory, one needs to actually use it for a few days before the beauty a cheap, universal, fast, intelligent, easy to use, and asynchronous queuing messaging fabric hits home.
0MQ has what is called a high-water mark on (outgoing) queues. You can then decide whether to block if the queue gets full, or poll the socket to know when it's ready for output. This is also how TCP works. 0MQ abstracts the complexities of the network that you don't want to see, but it exposes those parts you still need to. It would make a very nice transport for file transfer, and I'll probably add such an example to the 0MQ Guide.
JMS does cover some of the same ground, all messaging does. But it's basically an API wrapper around two ancient technologies, a queue system and a topic system. I think it might have been IBM MQSeries (which became WebSphere MQ) and some other product but can't find the details.
What JMS achieved was to somehow turn these two very different semantics into a single one, based around "destinations". That was very clever but also makes JMS weirdly complex to use because the queue (request-reply) pattern and the topic (publish-subscribe) pattern just don't work the same way. We designed AMQP originally by taking the JMS spec and reverse engineering that into a wire level protocol. Then around version 0.3 we threw out destinations and came up with a generic wiring model based on exchanges, bindings, queues. That was my summer holiday in 2005.
AMQP is BTW still some way away from a 1.0 standard and mainly it's been five years trying to get reliability working in the center of the network. That always seemed destined to failure, as I explained in a presentation to the working group in 2006: http://www.zeromq.org/whitepapers:switch-or-broker.
AMQP and JMS both focus on resources held in the center of the network. It's familiar to anyone using HTTP as their stack. Thin stupid clients talking to big smart servers. 0MQ turns the focus to smart clients working across a thin, stupid (but massive) network.
Both approaches have their value. We (iMatix and the 0MQ community) tend to believe we can do a lot more, faster and more cheaply, using the distributed approach.
If you read the 0MQ Reference Manual at http://api.zeromq.org/zmq.html you'll see that it specifies the abstraction, while the code implements that abstraction.
Lol. Actually I believe 0MQ (or rather, the principles it embodies) is something all serious developers need to learn. How to do concurrency properly, how to get above TCP sockets, how to design simple APIs, how to do open source properly, etc. It's hard to see that exposure to 0MQ would make anyone a worse developer.
As a programmer, using 0MQ is Better than Sex. You can quote me on that. It would be unethical to deny such fun to anyone. What beginners need, with any new technology, is a set of clear recipes that they can implement without having to invent everything. This was why a books like Stevens' trilogy were so vital to getting TCP out of labs and into the grubby hands of ADHD bleeding-edge types.
In most cases 0MQ will recover silently (and usefully) from common networking problems. When a peer crashes, for example, and then comes back, its partners don't see the problem. Messages get queued, and then delivered. This works for the main socket types and transports (but not PAIR and inproc:)
This lets us do things like start clients and THEN start a server... the clients automatically connect when the server comes along. The server can go away, be replaced by another on the same endpoint, and clients will gracefully and invisibly start talking to the new server.
In some cases this is precisely what we want, in other cases it's not. If we need to detect dead peers, we add heartbeating as a message flow on top of 0MQ. Most larger 0MQ applications currently do this. Eventually 0MQ sockets may offer heartbeating, it seems a natural evolution. ("Seems" but is not necessarily.)
Additionally there are some patterns (like synchronous request-reply) that simply don't handle network issues properly. If your service dies while processing a request, your client if it does a blocking read will hang forever. There are work-arounds such as using non-blocking reads.
It would be a mistake to try to solve all challenges at once in any project. 0MQ is taking it step by step, starting with the core questions of how to design massively-scalable patterns correctly. Just doing that is worth gold, as you can see from people actually using 0MQ, who consistently tell us, "this makes our life orders of magnitude easier, thank you".
And as we solve the core problems properly, we'll continue to address other aspects, either in 0MQ core or in layers on top of that, and this process will continue ad infinitum.
Zed, whats with all the premature optimization? Surely Mongrel2 should first be able to make coffee, build you an island and f@!in transform into a jet and fly you there, before you start to make it faster!
Just kidding. It's always nice to see science in action. Great work! I suspect there's an impact on ZeroMQ's own poll/epoll strategy.
Nice question. 0MQ has a wire protocol but it's minimalist, just doing framing. As we push 0MQ out into wider use we'll grow the protocol stack upwards. It'll take years. We do have a protocol specification project - http://rfc.zeromq.org/
We do intend to deliver IETF-quality specs that turn messaging patterns like pubsub into 1st class citizens of the Internet, so that arbitrary vendors can produce pieces that plug into this. But these specs will still be really simple.
I've always advocated a standard API for AMQP and proposed one (WireAPI) years ago, because this reduces vendor capture. Imagine if vendors designed arbitrary socket APIs... well some do, and it locks their users in.
So 0MQ is partly an API standardization project, partly an architecture project (to build a layer that seems to be missing from the stack), and partly a protocol specification project.
This is the metaprogramming we used to build OpenAMQ. It was very successful in technology terms (1M lines of real code generated from 20k lines of metacode) but a failure in social tems (too high a barrier to community participation).
No misunderstandings... When the AMQP working group was founded, RHAT took a very assertive role over AMQP and created versions that no-one else implemented, and which were pushed through the working group by sheer political force. Read the abomination that is the AMQP/0.9 spec, if you have the courage. The determination of RHAT to create incompatible forks of the spec is a large part of what killed AMQP in our eyes. We spent several years trying to save AMQP from that. We failed. We're a small team, RHAT had 20 people working on this.
I designed and wrote AMQP versions 0.1 through 0.8 and iMatix founded the AMQP working group. I was editor of the last 0.9.1 spec which fixed almost all of the bugs and inconsistencies of 0.8. It's a great, clean, tight spec but still fundamentally flawed :-) As for AMQP/1.0, no comment, but I would not run my business on it.
Explicit identities are dangerous for servers since they create entropy (state accumulation) unless (and even) if you set strict high-water marks.
They're also a real pain internally and as part of simplifying 0MQ's construction we eventually want to get rid of them.
There are better ways to keep and synchronize state among a set of subscribers. See the detailed Clone pattern in Ch5 of the Guide, for example.
http://zguide.zeromq.org/page:all#A-Shared-Key-Value-Cache-C...