Navigation Menu

Skip to content

Commit

Permalink
Revert "Fix/tim clifford/at least attempt to fix chapter links"
Browse files Browse the repository at this point in the history
  • Loading branch information
hintjens committed Dec 30, 2014
1 parent a428f8d commit 105b72c
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 41 deletions.
6 changes: 3 additions & 3 deletions chapter1.txt
Expand Up @@ -89,7 +89,7 @@ Now this looks too simple to be realistic, but ZeroMQ sockets have, as we alread

Let us explain briefly what these two programs are actually doing. They create a ZeroMQ context to work with, and a socket. Don't worry what the words mean. You'll pick it up. The server binds its REP (reply) socket to port 5555. The server waits for a request in a loop, and responds each time with a reply. The client sends a request and reads the reply back from the server.

If you kill the server (Ctrl-C) and restart it, the client won't recover properly. Recovering from crashing processes isn't quite that easy. Making a reliable request-reply flow is complex enough that we won't cover it until [php:chapter4#reliable-request-reply|Chapter 4 - Reliable Request-Reply Patterns].
If you kill the server (Ctrl-C) and restart it, the client won't recover properly. Recovering from crashing processes isn't quite that easy. Making a reliable request-reply flow is complex enough that we won't cover it until [#reliable-request-reply].

There is a lot happening behind the scenes but what matters to us programmers is how short and sweet the code is, and how often it doesn't crash, even under a heavy load. This is the request-reply pattern, probably the simplest way to use ZeroMQ. It maps to RPC and the classic client/server model.

Expand Down Expand Up @@ -212,7 +212,7 @@ Then the subscriber will most likely not receive anything. You'll blink, check t

Making a TCP connection involves to and from handshaking that takes several milliseconds depending on your network and the number of hops between peers. In that time, ZeroMQ can send many messages. For sake of argument assume it takes 5 msecs to establish a connection, and that same link can handle 1M messages per second. During the 5 msecs that the subscriber is connecting to the publisher, it takes the publisher only 1 msec to send out those 1K messages.

In [php:chapter2#sockets-and-patterns|Chapter 2 - Sockets and Patterns] we'll explain how to synchronize a publisher and subscribers so that you don't start to publish data until the subscribers really are connected and ready. There is a simple and stupid way to delay the publisher, which is to sleep. Don't do this in a real application, though, because it is extremely fragile as well as inelegant and slow. Use sleeps to prove to yourself what's happening, and then wait for [php:chapter2#sockets-and-patterns|Chapter 2 - Sockets and Patterns] to see how to do this right.
In [#sockets-and-patterns] we'll explain how to synchronize a publisher and subscribers so that you don't start to publish data until the subscribers really are connected and ready. There is a simple and stupid way to delay the publisher, which is to sleep. Don't do this in a real application, though, because it is extremely fragile as well as inelegant and slow. Use sleeps to prove to yourself what's happening, and then wait for [#sockets-and-patterns] to see how to do this right.

The alternative to synchronization is to simply assume that the published data stream is infinite and has no start and no end. One also assumes that the subscriber doesn't care what transpired before it started up. This is how we built our weather client example.

Expand Down Expand Up @@ -329,7 +329,7 @@ Let's look at some aspects of this code in more detail:
#-------------#
[[/code]]

The pipeline pattern also exhibits the "slow joiner" syndrome, leading to accusations that PUSH sockets don't load balance properly. If you are using PUSH and PULL, and one of your workers gets way more messages than the others, it's because that PULL socket has joined faster than the others, and grabs a lot of messages before the others manage to connect. If you want proper load balancing, you probably want to look at the load balancing pattern in [php:chapter3#advanced-request-reply|Chapter 3 - Advanced Request-Reply Patters].
The pipeline pattern also exhibits the "slow joiner" syndrome, leading to accusations that PUSH sockets don't load balance properly. If you are using PUSH and PULL, and one of your workers gets way more messages than the others, it's because that PULL socket has joined faster than the others, and grabs a lot of messages before the others manage to connect. If you want proper load balancing, you probably want to look at the load balancing pattern in [#advanced-request-reply].

++ Programming with ZeroMQ

Expand Down
12 changes: 6 additions & 6 deletions chapter2.txt
Expand Up @@ -2,7 +2,7 @@
.bookmark sockets-and-patterns
+ Sockets and Patterns

In [php:chapter1#basics|Chapter 1 - The Basics] we took ZeroMQ for a drive, with some basic examples of the main ZeroMQ patterns: request-reply, pub-sub, and pipeline. In this chapter, we're going to get our hands dirty and start to learn how to use these tools in real programs.
In [#basics] we took ZeroMQ for a drive, with some basic examples of the main ZeroMQ patterns: request-reply, pub-sub, and pipeline. In this chapter, we're going to get our hands dirty and start to learn how to use these tools in real programs.

We'll cover:

Expand Down Expand Up @@ -178,7 +178,7 @@ The built-in core ZeroMQ patterns are:

* **Exclusive pair**, which connects two sockets exclusively. This is a pattern for connecting two threads in a process, not to be confused with "normal" pairs of sockets.

We looked at the first three of these in [php:chapter1#basics|Chapter 1 - The Basics], and we'll see the exclusive pair pattern later in this chapter. The {{zmq_socket[3]}} man page is fairly clear about the patterns -- it's worth reading several times until it starts to make sense. These are the socket combinations that are valid for a connect-bind pair (either side can bind):
We looked at the first three of these in [#basics], and we'll see the exclusive pair pattern later in this chapter. The {{zmq_socket[3]}} man page is fairly clear about the patterns -- it's worth reading several times until it starts to make sense. These are the socket combinations that are valid for a connect-bind pair (either side can bind):

* PUB and SUB
* REQ and REP
Expand All @@ -196,7 +196,7 @@ You'll also see references to XPUB and XSUB sockets, which we'll come to later (

These four core patterns are cooked into ZeroMQ. They are part of the ZeroMQ API, implemented in the core C++ library, and are guaranteed to be available in all fine retail stores.

On top of those, we add //high-level messaging patterns//. We build these high-level patterns on top of ZeroMQ and implement them in whatever language we're using for our application. They are not part of the core library, do not come with the ZeroMQ package, and exist in their own space as part of the ZeroMQ community. For example the Majordomo pattern, which we explore in [php:chapter4#reliable-request-reply|Chapter 4 - Reliable Request-Reply Patterns], sits in the GitHub Majordomo project in the ZeroMQ organization.
On top of those, we add //high-level messaging patterns//. We build these high-level patterns on top of ZeroMQ and implement them in whatever language we're using for our application. They are not part of the core library, do not come with the ZeroMQ package, and exist in their own space as part of the ZeroMQ community. For example the Majordomo pattern, which we explore in [#reliable-request-reply], sits in the GitHub Majordomo project in the ZeroMQ organization.

One of the things we aim to provide you with in this book are a set of such high-level patterns, both small (how to handle messages sanely) and large (how to make a reliable pub-sub architecture).

Expand Down Expand Up @@ -233,7 +233,7 @@ In memory, ZeroMQ messages are {{zmq_msg_t}} structures (or classes depending on

If you want to send the same message more than once, and it's sizable, create a second message, initialize it using {{zmq_msg_init[3]}}, and then use {{zmq_msg_copy[3]}} to create a copy of the first message. This does not copy the data but copies a reference. You can then send the message twice (or more, if you create more copies) and the message will only be finally destroyed when the last copy is sent or closed.

ZeroMQ also supports //multipart// messages, which let you send or receive a list of frames as a single on-the-wire message. This is widely used in real applications and we'll look at that later in this chapter and in [php:chapter3#advanced-request-reply|Chapter 3 - Advanced Request-Reply Patters].
ZeroMQ also supports //multipart// messages, which let you send or receive a list of frames as a single on-the-wire message. This is widely used in real applications and we'll look at that later in this chapter and in [#advanced-request-reply].

Frames (also called "message parts" in the ZeroMQ reference manual pages) are the basic wire format for ZeroMQ messages. A frame is a length-specified block of data. The length can be zero upwards. If you've done any TCP programming you'll appreciate why frames are a useful answer to the question "how much data am I supposed to read of this network socket now?"

Expand Down Expand Up @@ -501,7 +501,7 @@ But our broker has to be nonblocking. Obviously, we can use {{zmq_poll[3]}} to w
#---------# #---------# #---------#
[[/code]]

Luckily, there are two sockets called DEALER and ROUTER that let you do nonblocking request-response. You'll see in [php:chapter3#advanced-request-reply|Chapter 3 - Advanced Request-Reply Patters] how DEALER and ROUTER sockets let you build all kinds of asynchronous request-reply flows. For now, we're just going to see how DEALER and ROUTER let us extend REQ-REP across an intermediary, that is, our little broker.
Luckily, there are two sockets called DEALER and ROUTER that let you do nonblocking request-response. You'll see in [#advanced-request-reply] how DEALER and ROUTER sockets let you build all kinds of asynchronous request-reply flows. For now, we're just going to see how DEALER and ROUTER let us extend REQ-REP across an intermediary, that is, our little broker.

In this simple extended request-reply pattern, REQ talks to ROUTER and DEALER talks to REP. In between the DEALER and ROUTER, we have to have code (like our broker) that pulls messages off the one socket and shoves them onto the other[figure].

Expand Down Expand Up @@ -881,7 +881,7 @@ All the code should be recognizable to you by now. How it works:

* The server starts a proxy that connects the two sockets. The proxy pulls incoming requests fairly from all clients, and distributes those out to workers. It also routes replies back to their origin.

Note that creating threads is not portable in most programming languages. The POSIX library is pthreads, but on Windows you have to use a different API. In our example, the {{pthread_create}} call starts up a new thread running the {{worker_routine}} function we defined. We'll see in [php:chapter3#advanced-request-reply|Chapter 3 - Advanced Request-Reply Patters] how to wrap this in a portable API.
Note that creating threads is not portable in most programming languages. The POSIX library is pthreads, but on Windows you have to use a different API. In our example, the {{pthread_create}} call starts up a new thread running the {{worker_routine}} function we defined. We'll see in [#advanced-request-reply] how to wrap this in a portable API.

Here the "work" is just a one-second pause. We could do anything in the workers, including talking to other nodes. This is what the MT server looks like in terms of ØMQ sockets and nodes. Note how the request-reply chain is {{REQ-ROUTER-queue-DEALER-REP}}[figure].

Expand Down
12 changes: 6 additions & 6 deletions chapter3.txt
Expand Up @@ -2,7 +2,7 @@
.bookmark advanced-request-reply
+ Advanced Request-Reply Patterns

In z[php:chapter2#sockets-and-patterns|Chapter 2 - Sockets and Patterns] we worked through the basics of using ZeroMQ by developing a series of small applications, each time exploring new aspects of ZeroMQ. We'll continue this approach in this chapter as we explore advanced patterns built on top of ZeroMQ's core request-reply pattern.
In [#sockets-and-patterns] we worked through the basics of using ZeroMQ by developing a series of small applications, each time exploring new aspects of ZeroMQ. We'll continue this approach in this chapter as we explore advanced patterns built on top of ZeroMQ's core request-reply pattern.

We'll cover:

Expand Down Expand Up @@ -45,7 +45,7 @@ If you spy on the network data flowing between {{hwclient}} and {{hwserver}}, th

+++ The Extended Reply Envelope

Now let's extend the REQ-REP pair with a ROUTER-DEALER proxy in the middle and see how this affects the reply envelope. This is the //extended request-reply pattern// we already saw in [php:chapter2#sockets-and-patterns|Chapter 2 - Sockets and Patterns]. We can, in fact, insert any number of proxy steps[figure]. The mechanics are the same.
Now let's extend the REQ-REP pair with a ROUTER-DEALER proxy in the middle and see how this affects the reply envelope. This is the //extended request-reply pattern// we already saw in [#sockets-and-patterns]. We can, in fact, insert any number of proxy steps[figure]. The mechanics are the same.

[[code type="textdiagram" title="Extended Request-Reply Pattern"]]
#-------# #-------#
Expand Down Expand Up @@ -131,7 +131,7 @@ The REQ socket picks this message up, and checks that the first frame is the emp

+++ What's This Good For?

To be honest, the use cases for strict request-reply or extended request-reply are somewhat limited. For one thing, there's no easy way to recover from common failures like the server crashing due to buggy application code. We'll see more about this in [php:chapter4#reliable-request-reply|Chapter 4 - Reliable Request-Reply Patterns]. However once you grasp the way these four sockets deal with envelopes, and how they talk to each other, you can do very useful things. We saw how ROUTER uses the reply envelope to decide which client REQ socket to route a reply back to. Now let's express this another way:
To be honest, the use cases for strict request-reply or extended request-reply are somewhat limited. For one thing, there's no easy way to recover from common failures like the server crashing due to buggy application code. We'll see more about this in [#reliable-request-reply]. However once you grasp the way these four sockets deal with envelopes, and how they talk to each other, you can do very useful things. We saw how ROUTER uses the reply envelope to decide which client REQ socket to route a reply back to. Now let's express this another way:

* Each time ROUTER gives you a message, it tells you what peer that came from, as an identity.
* You can use this with a hash table (with the identity as key) to track new peers as they arrive.
Expand Down Expand Up @@ -195,7 +195,7 @@ And when we receive a message, we:

+++ The REQ to ROUTER Combination

In the same way that we can replace REQ with DEALER, we can replace REP with ROUTER. This gives us an asynchronous server that can talk to multiple REQ clients at the same time. If we rewrote the "Hello World" server using ROUTER, we'd be able to process any number of "Hello" requests in parallel. We saw this in the [php:chapter2#sockets-and-patterns|Chapter 2 - Sockets and Patterns] {{mtserver}} example.
In the same way that we can replace REQ with DEALER, we can replace REP with ROUTER. This gives us an asynchronous server that can talk to multiple REQ clients at the same time. If we rewrote the "Hello World" server using ROUTER, we'd be able to process any number of "Hello" requests in parallel. We saw this in the [#sockets-and-patterns] {{mtserver}} example.

We can use ROUTER in two distinct ways:

Expand All @@ -218,7 +218,7 @@ When you replace a REP with a DEALER, your worker can suddenly go full asynchron

+++ The ROUTER to ROUTER Combination

This sounds perfect for N-to-N connections, but it's the most difficult combination to use. You should avoid it until you are well advanced with ZeroMQ. We'll see one example it in the Freelance pattern in [php:chapter4#reliable-request-reply|Chapter 4 - Reliable Request-Reply Patterns], and an alternative DEALER to ROUTER design for peer-to-peer work in [php:chapter8#moving-pieces]|Chapter 8 - A Framework for Distributed Computing].
This sounds perfect for N-to-N connections, but it's the most difficult combination to use. You should avoid it until you are well advanced with ZeroMQ. We'll see one example it in the Freelance pattern in [#reliable-request-reply], and an alternative DEALER to ROUTER design for peer-to-peer work in [#moving-pieces].

+++ Invalid Combinations

Expand Down Expand Up @@ -338,7 +338,7 @@ Anywhere you can use REQ, you can use DEALER. There are two specific differences
* The REQ socket always sends an empty delimiter frame before any data frames; the DEALER does not.
* The REQ socket will send only one message before it receives a reply; the DEALER is fully asynchronous.

The synchronous versus asynchronous behavior has no effect on our example because we're doing strict request-reply. It is more relevant when we address recovering from failures, which we'll come to in [php:chapter4#reliable-request-reply|Chapter 4 - Reliable Request-Reply Patterns].
The synchronous versus asynchronous behavior has no effect on our example because we're doing strict request-reply. It is more relevant when we address recovering from failures, which we'll come to in [#reliable-request-reply].

Now let's look at exactly the same example but with the REQ socket replaced by a DEALER socket:

Expand Down

0 comments on commit 105b72c

Please sign in to comment.