1. Trang chủ
  2. » Công Nghệ Thông Tin

ZeroMQ docx

515 3,7K 2
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề ZeroMQ
Tác giả Pieter Hintjens
Trường học O'Reilly Media
Chuyên ngành Computer Science / Networking
Thể loại sách hướng dẫn / Thư viện hướng dẫn
Năm xuất bản 2013
Thành phố Sebastopol
Định dạng
Số trang 515
Dung lượng 11,59 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

3 Fixing the World 3 Audience for This Book 5 Getting the Examples 5 Ask and Ye Shall Receive 5 A Minor Note on Strings 10 Version Reporting 11 Getting the Message Out 11 Divide and Conq

Trang 3

Pieter Hintjens

ZeroMQ

Trang 4

by Pieter Hintjens

Copyright © 2013 Pieter Hintjens All rights reserved.

Printed in the United States of America.

Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.

O’Reilly books may be purchased for educational, business, or sales promotional use Online editions are

also available for most titles (http://my.safaribooksonline.com) For more information, contact our corporate/ institutional sales department: 800-998-9938 or corporate@oreilly.com.

Editors: Andy Oram and Maria Gulick

Production Editor: Christopher Hearse

Copyeditor: Gillian McGarvey

Proofreader: Rachel Head

Indexer: Angela Howard Cover Designer: Randy Comer Interior Designer: David Futato Illustrator: Rebecca Demarest and Kara Ebrahim

March 2013: First Edition

Revision History for the First Edition:

2013-03-11: First release

See http://oreilly.com/catalog/errata.csp?isbn=9781449334062 for release details.

Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly

Media, Inc ZeroMQ, the image of a fourhorn sculpin, and related trade dress are trademarks of O’Reilly

Media, Inc.

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trade‐ mark claim, the designations have been printed in caps or initial caps.

While every precaution has been taken in the preparation of this book, the publisher and authors assume

no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.

ISBN: 978-1-449-33406-2

[LSI]

Trang 5

To Noémie, Freeman, and Gregor.

Trang 7

Table of Contents

Preface xiii

Part I Learning to Work with ØMQ 1 Basics 3

Fixing the World 3

Audience for This Book 5

Getting the Examples 5

Ask and Ye Shall Receive 5

A Minor Note on Strings 10

Version Reporting 11

Getting the Message Out 11

Divide and Conquer 16

Programming with ØMQ 21

Getting the Context Right 21

Making a Clean Exit 22

Why We Needed ØMQ 23

Socket Scalability 27

Upgrading from ØMQ v2.2 to ØMQ v3.2 27

Warning: Unstable Paradigms! 28

2 Sockets and Patterns 31

The Socket API 32

Plugging Sockets into the Topology 32

Using Sockets to Carry Data 34

Unicast Transports 35

ØMQ Is Not a Neutral Carrier 35

I/O Threads 36

Messaging Patterns 37

v

Trang 8

High-Level Messaging Patterns 38

Working with Messages 39

Handling Multiple Sockets 41

Multipart Messages 44

Intermediaries and Proxies 45

The Dynamic Discovery Problem 45

Shared Queue (DEALER and ROUTER Sockets) 48

ØMQ’s Built-in Proxy Function 53

Transport Bridging 54

Handling Errors and ETERM 56

Handling Interrupt Signals 61

Detecting Memory Leaks 62

Multithreading with ØMQ 63

Signaling Between Threads (PAIR Sockets) 68

Node Coordination 70

Zero-Copy 74

Pub-Sub Message Envelopes 75

High-Water Marks 77

Missing Message Problem Solver 78

3 Advanced Request-Reply Patterns 81

The Request-Reply Mechanisms 81

The Simple Reply Envelope 82

The Extended Reply Envelope 82

What’s This Good For? 85

Recap of Request-Reply Sockets 85

Request-Reply Combinations 86

The REQ to REP Combination 87

The DEALER to REP Combination 87

The REQ to ROUTER Combination 87

The DEALER to ROUTER Combination 88

The DEALER to DEALER Combination 88

The ROUTER to ROUTER Combination 88

Invalid Combinations 88

Exploring ROUTER Sockets 89

Identities and Addresses 89

ROUTER Error Handling 91

The Load-Balancing Pattern 91

ROUTER Broker and REQ Workers 92

ROUTER Broker and DEALER Workers 94

A Load-Balancing Message Broker 96

A High-Level API for ØMQ 102

Trang 9

Features of a Higher-Level API 104

The CZMQ High-Level API 105

The Asynchronous Client/Server Pattern 111

Worked Example: Inter-Broker Routing 116

Establishing the Details 116

Architecture of a Single Cluster 117

Scaling to Multiple Clusters 118

Federation Versus Peering 121

The Naming Ceremony 122

Prototyping the State Flow 123

Prototyping the Local and Cloud Flows 126

Putting It All Together 133

4 Reliable Request-Reply Patterns 141

What Is “Reliability”? 141

Designing Reliability 142

Client-Side Reliability (Lazy Pirate Pattern) 144

Basic Reliable Queuing (Simple Pirate Pattern) 148

Robust Reliable Queuing (Paranoid Pirate Pattern) 151

Heartbeating 159

Shrugging It Off 160

One-Way Heartbeats 160

Ping-Pong Heartbeats 161

Heartbeating for Paranoid Pirate 161

Contracts and Protocols 163

Service-Oriented Reliable Queuing (Majordomo Pattern) 164

Asynchronous Majordomo Pattern 186

Service Discovery 191

Idempotent Services 193

Disconnected Reliability (Titanic Pattern) 194

High-Availability Pair (Binary Star Pattern) 206

Detailed Requirements 208

Preventing Split-Brain Syndrome 211

Binary Star Implementation 211

Binary Star Reactor 218

Brokerless Reliability (Freelance Pattern) 223

Model One: Simple Retry and Failover 225

Model Two: Brutal Shotgun Massacre 228

Model Three: Complex and Nasty 233

Conclusion 244

5 Advanced Publish-Subscribe Patterns 245

Table of Contents | vii

Trang 10

Pros and Cons of Publish-Subscribe 245

Pub-Sub Tracing (Espresso Pattern) 247

Last Value Caching 250

Slow Subscriber Detection (Suicidal Snail Pattern) 254

High-Speed Subscribers (Black Box Pattern) 258

Reliable Publish-Subscribe (Clone Pattern) 260

Centralized Versus Decentralized 261

Representing State as Key-Value Pairs 261

Getting an Out-of-Band Snapshot 271

Republishing Updates from Clients 276

Working with Subtrees 281

Ephemeral Values 284

Using a Reactor 292

Adding the Binary Star Pattern for Reliability 296

The Clustered Hashmap Protocol 306

Building a Multithreaded Stack and API 310

Part II Software Engineering Using ØMQ 6 The ØMQ Community 325

Architecture of the ØMQ Community 326

How to Make Really Large Architectures 327

Psychology of Software Architecture 328

The Contract 330

The Process 332

Crazy, Beautiful, and Easy 332

Stranger, Meet Stranger 333

Infinite Property 333

Care and Feeding 334

The ØMQ Process: C4 335

Language 335

Goals 336

Preliminaries 338

Licensing and Ownership 339

Patch Requirements 340

Development Process 342

Creating Stable Releases 345

Evolution of Public Contracts 347

A Real-Life Example 349

Git Branches Considered Harmful 352

Simplicity Versus Complexity 353

Trang 11

Change Latency 353

Learning Curve 353

Cost of Failure 353

Up-Front Coordination 354

Scalability 354

Surprise and Expectations 354

Economics of Participation 354

Robustness in Conflict 355

Guarantees of Isolation 355

Visibility 355

Conclusions 355

Designing for Innovation 356

The Tale of Two Bridges 356

How ØMQ Lost Its Road Map 356

Trash-Oriented Design 359

Complexity-Oriented Design 361

Simplicity-Oriented Design 362

Burnout 364

Patterns for Success 366

The Lazy Perfectionist 366

The Benevolent Tyrant 366

The Earth and Sky 366

The Open Door 367

The Laughing Clown 367

The Mindful General 367

The Social Engineer 367

The Constant Gardener 367

The Rolling Stone 368

The Pirate Gang 368

The Flash Mob 368

The Canary Watcher 368

The Hangman 369

The Historian 369

The Provocateur 369

The Mystic 369

7 Advanced Architecture Using ØMQ 371

Message-Oriented Pattern for Elastic Design 372

Step 1: Internalize the Semantics 373

Step 2: Draw a Rough Architecture 373

Step 3: Decide on the Contracts 374

Step 4: Write a Minimal End-to-End Solution 374

Table of Contents | ix

Trang 12

Step 5: Solve One Problem and Repeat 375

Unprotocols 375

Contracts Are Hard 376

How to Write Unprotocols 377

Why Use the GPLv3 for Public Specifications? 378

Using ABNF 379

The Cheap or Nasty Pattern 380

Serializing Your Data 382

ØMQ Framing 382

Serialization Languages 383

Serialization Libraries 384

Handwritten Binary Serialization 385

Code Generation 386

Transferring Files 392

State Machines 403

Authentication Using SASL 410

Large-Scale File Publishing: FileMQ 411

Why Make FileMQ? 412

Initial Design Cut: The API 412

Initial Design Cut: The Protocol 413

Building and Trying FileMQ 414

Internal Architecture 415

Public API 416

Design Notes 417

Configuration 418

File Stability 419

Delivery Notifications 420

Symbolic Links 420

Recovery and Late Joiners 421

Test Use Case: The Track Tool 423

Getting an Official Port Number 424

8 A Framework for Distributed Computing 425

Design for the Real World 426

The Secret Life of WiFi 427

Why Mesh Isn’t Here Yet 428

Some Physics 429

What’s the Current Status? 430

Conclusions 432

Discovery 432

Preemptive Discovery over Raw Sockets 432

Cooperative Discovery Using UDP Broadcasts 434

Trang 13

Multiple Nodes on One Device 439

Designing the API 439

More About UDP 448

Spinning Off a Library Project 448

Point-to-Point Messaging 450

UDP Beacon Framing 450

True Peer Connectivity (Harmony Pattern) 452

Detecting Disappearances 454

Group Messaging 455

Testing and Simulation 457

On Assertions 457

On Up-Front Testing 458

The Zyre Tester 459

Test Results 461

Tracing Activity 463

Dealing with Blocked Peers 464

Distributed Logging and Monitoring 467

A Plausible Minimal Implementation 468

Protocol Assertions 470

Binary Logging Protocol 471

Content Distribution 473

Writing the Unprotocol 475

Conclusions 476

9 Postface 479

Tales from Out There 479

Rob Gagnon’s Story 479

Tom van Leeuwen’s Story 479

Michael Jakl’s Story 480

Vadim Shalts’s Story 480

How This Book Happened 481

Removing Friction 482

Licensing 484

Index 485

Table of Contents | xi

Trang 15

ØMQ in a Hundred Words

ØMQ (also known as ZeroMQ, 0MQ, or zmq) looks like an embeddable networkinglibrary, but acts like a concurrency framework It gives you sockets that carry atomicmessages across various transports, like in-process, inter-process, TCP, and multicast.You can connect sockets N-to-N with patterns like fan-out, pub-sub, task distribution,and request-reply It’s fast enough to be the fabric for clustered products Its asynchro‐nous I/O model gives you scalable multicore applications, built as asynchronousmessage-processing tasks It has a score of language APIs and runs on most operatingsystems ØMQ is from iMatix and is LGPLv3 open source

The Zen of Zero

The Ø in ØMQ is all about trade-offs On the one hand, this strange name lowers ØMQ’svisibility on Google and Twitter On the other hand, it annoys the heck out of someDanish folk who write us things like “ØMG røtfl”, and “Ø is not a funny-looking zero!”

and “Rødgrød med Fløde!” (which is apparently an insult that means “May your neigh‐

bours be the direct descendants of Grendel!”) Seems like a fair trade

Originally, the zero in ØMQ was meant to signify “zero broker” and (as close to) “zerolatency” (as possible) Since then, it has come to encompass different goals: zero ad‐ministration, zero cost, zero waste More generally, “zero” refers to the culture of min‐imalism that permeates the project We add power by removing complexity rather than

by exposing new functionality

How This Book Came to Be

In the summer of 2010, ØMQ was still a little-known niche library described by itsrather terse reference manual and a living but sparse wiki Martin Sustrik and I weresitting in the bar of the Hotel Kyjev in Bratislava plotting how to make ØMQ more

xiii

Trang 16

widely popular Martin had written most of the ØMQ code, and I’d put up the fundingand organized the community Over some Zlatý Bažant, we agreed that ØMQ needed

a new, simpler website and a basic guide for new users

Martin collected some ideas for topics to explain I’d never written a line of ØMQ codebefore this, so it became a live learning documentary As I worked through simpleexamples to more complex ones, I tried to answer many of the questions I’d seen on themailing list Because I’d been building large-scale architectures for 30 years, there were

a lot of problems I was keen to throw ØMQ at Amazingly, the results were mostly simpleand elegant, even when working in C I felt a pure joy learning ØMQ and using it tosolve real problems, which brought me back to programming after a few years’ pause.And often, not knowing how it was “supposed” to be done, we improved ØMQ as wewent along

From the start, I wanted the guide to be a community project, so I put it onto GitHuband let others contribute with pull requests This was considered a radical, even vulgarapproach by some We came to a division of labor: I’d do the writing and make theoriginal C examples, and others would help fix the text and translate the examples intoother languages

This worked better than I dared hope You can now find all the examples in severallanguages, and many in a dozen languages It’s a kind of programming language RosettaStone, and a valuable outcome in itself We set up a high score: reach 80% translationand your language gets its own guide PHP, Python, Lua, and Haxe reached this goal.People asked for PDFs, and we created those People asked for ebooks, and got those.About a hundred people have contributed to the guide to date

The guide achieved its goal of popularizing ØMQ The style pleases most and annoyssome, which is how it should be In December 2010, my work on ØMQ and the guidestopped, as I found myself going through late-stage cancer, heavy surgery, and sixmonths of chemotherapy When I picked up work again in mid-2011, it was to startusing ØMQ in anger for one of the largest use-cases imagineable: on the mobile phonesand tablets of the world’s biggest electronics company

But the goal of the guide was, from the start, a printed book So it was exciting to get anemail from Bill Lubanovic in January 2012, introducing me to his editor, Andy Oram,

at O’Reilly, suggesting a ØMQ book “Of course!” I said Where do I sign? How much

do I have to pay? Oh, I get money for this? All I have to do is finish it?”

Of course, as soon as O’Reilly announced a ØMQ book, other publishers started sendingout emails to potential authors You’ll probably see a rash of ØMQ books coming outnext year That’s good Our niche library has hit the mainstream and deserves its sixinches of shelf space My apologies to the other ØMQ authors We’ve set the bar horriblyhigh, and my advice is to make your books complementary Perhaps focus on a specificlanguage, platform, or pattern

Trang 17

This is the magic and power of communities: be the first community in a space, stayhealthy, and you own that space for ever.

Audience

This book is written for professional programmers who want to learn how to make themassively distributed software that will dominate the future of computing We assumeyou can read C code, because most of the examples here are in C (even though ØMQ

is used in many languages) We assume you care about scale, because ØMQ solves thatproblem above all others We assume you need the best possible results with the leastpossible cost, because otherwise you won’t appreciate the trade-offs that ØMQ makes.Other than that basic background, we try to present all the concepts in networking anddistributed computing you will need to use ØMQ

Conventions Used in This Book

We used the following typographical conventions in this book:

Italic

Indicates new terms, commands and command-line options, URLs, email address‐

es, filenames, and file extensions

Constant width

Used for program listings, as well as within paragraphs to refer to program elementssuch as variable or function names, data types, and environment variables

Constant width bold

Shows user input at the command line

Constant width italic

Shows placeholder user input that you should replace with something that makessense for you

This icon signifies a tip, suggestion, or general note

Using the Code Examples

The code examples are all online in the repository at https://github.com/imatix/zguide/ tree/master/examples/ You’ll find each example translated into several—often a dozen

—other languages The examples are licensed under MIT/X11; see the LICENSE file in

that directory The text of the book explains in each case how to run each example

Preface | xv

Trang 18

We appreciate, but do not require, attribution An attribution usually includes the title,

author, publisher, and ISBN For example: “ZeroMQ by Pieter Hintjens (O’Reilly).

Copyright 2013 Pieter Hintjens, 978-1-449-33406-2.”

If you feel your use of code examples falls outside fair use or the permission given above,feel free to contact us at permissions@oreilly.com

Safari® Books Online

Safari Books Online (www.safaribooksonline.com) is an on-demanddigital library that delivers expert content in both book and videoform from the world’s leading authors in technology and business.Technology professionals, software developers, web designers, and business and crea‐tive professionals use Safari Books Online as their primary resource for research, prob‐lem solving, learning, and certification training

Safari Books Online offers a range of product mixes and pricing programs for organi‐zations, government agencies, and individuals Subscribers have access to thousands ofbooks, training videos, and prepublication manuscripts in one fully searchable databasefrom publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Pro‐fessional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, JohnWiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FTPress, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technol‐ogy, and dozens more For more information about Safari Books Online, please visit us

Trang 19

For more information about our books, courses, conferences, and news, see our website

at http://www.oreilly.com

Find us on Facebook: http://facebook.com/oreilly

Follow us on Twitter: http://twitter.com/oreillymedia

Watch us on YouTube: http://www.youtube.com/oreillymedia

Acknowledgments

Thanks to Andy Oram for making this happen at O’Reilly and editing the book.Thanks to Bill Desmarais, Brian Dorsey, Daniel Lin, Eric Desgranges, Gonzalo Dieth‐elm, Guido Goldstein, Hunter Ford, Kamil Shakirov, Martin Sustrik, Mike Castleman,Naveen Chawla, Nicola Peduzzi, Oliver Smith, Olivier Chamoux, Peter Alexander,Pierre Rouleau, Randy Dryburgh, John Unwin, Alex Thomas, Mihail Minkov, JeremyAvnet, Michael Compton, Kamil Kisiel, Mark Kharitonov, Guillaume Aubert, Ian Bar‐ber, Mike Sheridan, Faruk Akgul, Oleg Sidorov, Lev Givon, Allister MacLeod, AlexanderD’Archangel, Andreas Hoelzlwimmer, Han Holl, Robert G Jakabosky, Felipe Cruz,Marcus McCurdy, Mikhail Kulemin, Dr Gergö Érdi, Pavel Zhukov, Alexander Else,Giovanni Ruggiero, Rick “Technoweenie”, Daniel Lundin, Dave Hoover, Simon Jefford,Benjamin Peterson, Justin Case, Devon Weller, Richard Smith, Alexander Morland,Wadim Grasza, Michael Jakl, Uwe Dauernheim, Sebastian Nowicki, Simone Deponti,Aaron Raddon, Dan Colish, Markus Schirp, Benoit Larroque, Jonathan Palardy, IsaiahPeng, Arkadiusz Orzechowski, Umut Aydin, Matthew Horsfall, Jeremy W Sherman,Eric Pugh, Tyler Sellon, John E Vincent, Pavel Mitin, Min RK, Igor Wiedler, Olof Åkes‐son, Patrick Lucas, Heow Goodman, Senthil Palanisami, John Gallagher, Tomas Roos,Stephen McQuay, Erik Allik, Arnaud Cogoluègnes, Rob Gagnon, Dan Williams, EdwardSmith, James Tucker, Kristian Kristensen, Vadim Shalts, Martin Trojer, Tom van Leeu‐wen, Hiten Pandya, Harm Aarts, Marc Harter, Iskren Ivov Chernev, Jay Han, SoniaHamilton, Nathan Stocks, Naveen Palli, and Zed Shaw for their contributions to thiswork

Thanks to Martin Sustrik for his years of incredible work on ZeroMQ

Thanks to Stathis Sideris for Ditaa

Preface | xvii

Trang 21

PART I Learning to Work with ØMQ

In the first part of this book, you’ll learn how to use ØMQ We’ll cover the basics, theAPI, the different socket types and how they work, reliability, and a host of patterns youcan use in your applications You’ll get the best results by working through the examplesand text from start to end

Trang 23

CHAPTER 1 Basics

Fixing the World

How to explain ØMQ? Some of us start by saying all the wonderful things it does It’s sockets on steroids It’s like mailboxes with routing It’s fast! Others try to share their

moment of enlightenment, that zap-pow-kaboom satori paradigm-shift moment when

it all became obvious Things just become simpler Complexity goes away It opens the mind Others try to explain by comparison It’s smaller, simpler, but still looks famili‐

ar Personally, I like to remember why we made ØMQ at all, because that’s most likely

where you, the reader, still are today

Programming is a science dressed up as art, because most of us don’t understand thephysics of software and it’s rarely, if ever, taught The physics of software is not algo‐rithms, data structures, languages, and abstractions These are just tools we make, use,and throw away The real physics of software is the physics of people

Specifically, it’s about our limitations when it comes to complexity and our desire towork together to solve large problems in pieces This is the science of programming:

make building blocks that people can understand and use easily, and people will work

together to solve the very largest problems

We live in a connected world, and modern software has to navigate this world So, thebuilding blocks for tomorrow’s very largest solutions are connected and massively par‐allel It’s not enough for code to be “strong and silent” any more Code has to talk tocode Code has to be chatty, sociable, and well-connected Code has to run like thehuman brain; trillions of individual neurons firing off messages to each other, a mas‐sively parallel network with no central control, no single point of failure, yet able tosolve immensely difficult problems And it’s no accident that the future of code lookslike the human brain, because the endpoints of every network are, at some level, humanbrains

3

Trang 24

If you’ve done any work with threads, protocols, or networks, you’ll realize this is prettymuch impossible It’s a dream Even connecting a few programs across a few sockets isplain nasty when you start to handle real-life situations Trillions? The cost would beunimaginable Connecting computers is so difficult that creating software and services

to do this is a multi-billion dollar business

So we live in a world where the wiring is years ahead of our ability to use it We had asoftware crisis in the 1980s, when leading software engineers like Fred Brooks believed

there was no “silver bullet” to “promise even one order of magnitude of improvement

in productivity, reliability, or simplicity.”

Brooks missed free and open source software, which solved that crisis, enabling us toshare knowledge efficiently Today we face another software crisis, but it’s one we don’ttalk about much Only the largest, richest firms can afford to create connected appli‐cations There is a cloud, but it’s proprietary Our data and our knowledge are disap‐pearing from our personal computers into clouds that we cannot access and with which

we cannot compete Who owns our social networks? It is like the mainframe-PC rev‐olution in reverse

We can leave the political philosophy for another book The point is that while theInternet offers the potential of massively connected code, the reality is that this is out

of reach for most of us, and so large, interesting problems (in health, education, eco‐nomics, transport, and so on) remain unsolved because there is no way to connect thecode, and thus no way to connect the brains that could work together to solve theseproblems

There have been many attempts to solve the challenge of connected software There arethousands of IETF specifications, each solving part of the puzzle For application de‐velopers, HTTP is perhaps the one solution to have been simple enough to work, but itarguably makes the problem worse by encouraging developers and architects to think

in terms of big servers and thin, stupid clients

So today people are still connecting applications using raw UDP and TCP, proprietaryprotocols, HTTP, and WebSockets It remains painful, slow, hard to scale, and essentiallycentralized Distributed peer-to-peer architectures are mostly for play, not work Howmany applications use Skype or BitTorrent to exchange data?

Which brings us back to the science of programming To fix the world, we needed to

do two things One, to solve the general problem of “how to connect any code to anycode, anywhere.” Two, to wrap that up in the simplest possible building blocks that

people could understand and use easily.

It sounds ridiculously simple And maybe it is That’s kind of the whole point

Trang 25

Audience for This Book

We assume you are using the latest 3.2 release of ØMQ We assume you are using aLinux box or something similar We assume you can read C code, more or less, as that’sthe default language for the examples We assume that when we write constants likePUSH or SUBSCRIBE, you can imagine they are really called ZMQ_PUSH or ZMQ_SUBSCRIBE if the programming language needs it

Getting the Examples

This book’s examples live in the book’s Git repository The simplest way to get all theexamples is to clone this repository:

git clone depth=1 git://github.com/imatix/zguide.git

Next, browse the examples subdirectory You’ll find examples by language If there are

examples missing in a language you use, you’re encouraged to submit a translation This

is how this book became so useful, thanks to the work of many people All examples arelicensed under MIT/X11

Ask and Ye Shall Receive

So let’s start with some code We’ll begin, of course, with a “Hello World” example We’llmake a client and a server The client sends “Hello” to the server, which replies with

“World” (Figure 1-1) Example 1-1 presents the code for the server in C, which opens

a ØMQ socket on port 5555, reads requests on it, and replies with “World” to eachrequest

Example 1-1 Hello World server (hwserver.c)

//

// Hello World server

// Binds REP socket to tcp://*:5555

// Expects "Hello" from client, replies with "World"

void context zmq_ctx_new ();

// Socket to talk to clients

void responder zmq_socket context, ZMQ_REP);

zmq_bind responder, "tcp://*:5555" );

Audience for This Book | 5

Trang 26

while 1

// Wait for next request from client

zmq_msg_t request;

zmq_msg_init & request);

zmq_msg_recv & request, responder, 0 );

printf "Received Hello\n");

zmq_msg_close & request);

// Do some 'work'

sleep 1 );

// Send reply back to client

zmq_msg_t reply;

zmq_msg_init_size & reply, 5 );

memcpy zmq_msg_data & reply), "World" , 5 );

zmq_msg_send & reply, responder, 0 );

zmq_msg_close & reply);

ØMQ uses C as its reference language, and this is the main language we’ll use for ex‐amples If you’re reading this online, the link below the example takes you to translationsinto other programming languages For print readers, Example 1-2 shows what the sameserver looks like in C++

Trang 27

Example 1-2 Hello World server (hwserver.cpp)

//

// Hello World server in C++

// Binds REP socket to tcp://*:5555

// Expects "Hello" from client, replies with "World"

// Wait for next request from client

socket.recv & request);

std :: cout << "Received Hello" << std :: endl;

* Hello World server

* Binds REP socket to tcp://*:5555

* Expects "Hello" from client, replies with "World"

* @author Ian Barber <ian(dot)barber(at)gmail(dot)com>

*/

$context new ZMQContext( );

// Socket to talk to clients

Ask and Ye Shall Receive | 7

Trang 28

$responder new ZMQSocket($context, ZMQ :: SOCKET_REP);

$responder -> bind( "tcp://*:5555" );

// Wait for next request from client

$request $responder -> recv();

printf "Received request: [%s]\n", $request);

// Do some 'work'

sleep 1 );

// Send reply back to client

$responder -> send( "World" );

}

Example 1-4 shows the client code

Example 1-4 Hello World client (hwclient.c)

//

// Hello World client

// Connects REQ socket to tcp://localhost:5555

// Sends "Hello" to server, expects "World" back

void context zmq_ctx_new ();

// Socket to talk to server

printf "Connecting to hello world server \n");

void requester zmq_socket context, ZMQ_REQ);

zmq_connect requester, "tcp://localhost:5555" );

// int request_nbr;

// for (request_nbr = 0; request_nbr != 10; request_nbr++) { // zmq_msg_t request;

// zmq_msg_init_size (&request, 5);

// memcpy (zmq_msg_data (&request), "Hello", 5);

// printf ("Sending Hello %d \n", request_nbr); // zmq_msg_send (&request, requester, 0);

// zmq_msg_close (&request);

//

// zmq_msg_t reply;

// zmq_msg_init (&reply);

// zmq_msg_recv (&reply, requester, 0);

// printf ("Received World %d\n", request_nbr);

// zmq_msg_close (&reply);

// }

Trang 29

Figure 1-2 There was a terrible accident

You could throw thousands of clients at this server, all at once, and it would continue

to work happily and quickly For fun, try starting the client and then starting the server,

see how it all still works, and then think for a second what this means

Let us explain briefly what these two programs are actually doing They create a ØMQcontext 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 It then waits for a request in a loop,and responds each time with a reply The client sends a request and reads the reply backfrom the server

If you kill the server (Ctrl-C) and restart it, the client won’t recover properly Recoveringfrom crashing processes isn’t quite that easy Making a reliable request-reply flow iscomplex enough that we won’t cover it until “Reliable Request-Reply Patterns” in Chap‐ter 4

There is a lot happening behind the scenes, but what matters to us programmers is howshort 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 ØMQ It maps to RPC(remote procedure calls) and the classic client/server model

Ask and Ye Shall Receive | 9

Trang 30

A Minor Note on Strings

ØMQ doesn’t know anything about the data you send except its size in bytes That meansyou are responsible for formatting it safely so that applications can read it back Doingthis for objects and complex data types is a job for specialized libraries like protocolbuffers But even for strings, you need to take care

In C and some other languages, strings are terminated with a null byte We could send

a string like “HELLO” with that extra null byte:

zmq_msg_init_data & request, "Hello" , 6 NULL , NULL );

However, if you send a string from another language, it probably will not include thatnull byte For example, when we send that same string in Python, we do this:

socket send "Hello" )

Then what goes onto the wire is a length (one byte for shorter strings) and the stringcontents as individual characters (Figure 1-3)

So let’s establish the rule that ØMQ strings are length-specified and are sent on the wire

without a trailing null In the simplest case (and we’ll do this in our examples), a ØMQ

string maps neatly to a ØMQ message frame, which looks like the above figure—a lengthand some bytes

Here is what we need to do, in C, to receive a ØMQ string and deliver it to the application

zmq_msg_init & message);

int size zmq_msg_recv & message, socket, 0 );

Trang 31

if size == 1

return NULL ;

char string malloc size );

memcpy string, zmq_msg_data & message), size);

zmq_msg_close & message);

The result is zhelpers.h, which lets us write sweeter and shorter ØMQ applications in

C It is a fairly long source, and only fun for C developers, so read it at your leisure

Version Reporting

ØMQ does come in several versions, and quite often if you hit a problem, it’ll be some‐

thing that’s been fixed in a later version So it’s a useful trick to know exactly what version

of ØMQ you’re actually linking with Example 1-5 is a tiny program that lets you do justthat

Example 1-5 ØMQ version reporting (version.c)

int major, minor, patch;

zmq_version & major, & minor, & patch);

printf "Current 0MQ version is %d.%d.%d\n", major, minor, patch);

}

Getting the Message Out

The second classic pattern is one-way data distribution, in which a server pushes updates

to a set of clients Let’s look at an example that pushes out weather updates consisting

of a zip code, temperature, and relative humidity We’ll generate random values, justlike the real weather stations do

Version Reporting | 11

Trang 32

Example 1-6 shows the code for the server We’ll use port 5556 for this application.

Example 1-6 Weather update server (wuserver.c)

//

// Weather update server

// Binds PUB socket to tcp://*:5556

// Publishes random weather updates

//

#include "zhelpers.h"

int main void)

{

// Prepare our context and publisher

void context zmq_ctx_new ();

void publisher zmq_socket context, ZMQ_PUB);

int rc zmq_bind publisher, "tcp://*:5556" );

assert rc == );

rc zmq_bind publisher, "ipc://weather.ipc" );

assert rc == );

// Initialize random number generator

srandom ((unsigned) time NULL ));

// Get values that will fool the boss

int zipcode, temperature, relhumidity;

sprintf update, "%05d %d %d" , zipcode, temperature, relhumidity);

s_send publisher, update);

Trang 33

Figure 1-4 Publish-subscribe

Example 1-7 shows the client application, which listens to the stream of updates andgrabs anything to do with a specified zip code (by default, New York City, because that’s

a great place to start any adventure)

Example 1-7 Weather update client (wuclient.c)

//

// Weather update client

// Connects SUB socket to tcp://localhost:5556

// Collects weather updates and finds avg temp in zipcode

//

#include "zhelpers.h"

int main int argc, char argv [])

{

void context zmq_ctx_new ();

// Socket to talk to server

printf "Collecting updates from weather server \n");

void subscriber zmq_socket context, ZMQ_SUB);

int rc zmq_connect subscriber, "tcp://localhost:5556" );

assert rc == );

// Subscribe to zipcode, default is NYC, 10001

char filter argc ) argv 1 : "10001 " ;

rc zmq_setsockopt subscriber, ZMQ_SUBSCRIBE, filter, strlen filter)); assert rc == );

// Process 100 updates

int update_nbr;

long total_temp ;

for update_nbr ; update_nbr 100 ; update_nbr ++ ) {

char string s_recv subscriber);

int zipcode, temperature, relhumidity;

Getting the Message Out | 13

Trang 34

printf "Average temperature for zipcode '%s' was %dF\n",

filter, (int) (total_temp update_nbr));

zmq_close subscriber);

zmq_ctx_destroy context);

}

Note that when you use a SUB socket you must set a subscription using zmq_setsock

opt() and SUBSCRIBE, as in this code If you don’t set any subscription, you won’t getany messages It’s a common mistake for beginners The subscriber can set many sub‐

scriptions, which are added together That is, if an update matches any subscription, the

subscriber receives it The subscriber can also cancel specific subscriptions A subscrip‐tion is often but not necessarily a printable string See zmq_setsockopt() for how thisworks

The PUB-SUB socket pair is asynchronous The client does zmq_msg_recv(), in a loop(or once if that’s all it needs) Trying to send a message to a SUB socket will cause anerror Similarly, the service does zmq_msg_send() as often as it needs to, but must not

do zmq_msg_recv() on a PUB socket

In theory, with ØMQ sockets it does not matter which end connects and which endbinds However, in practice there are undocumented differences that I’ll come to later.For now, bind the PUB and connect the SUB, unless your network design makes thatimpossible

There is one more important thing to know about PUB-SUB sockets: you do not knowprecisely when a subscriber starts to get messages Even if you start a subscriber, wait a

while, and then start the publisher, the subscriber will always miss the first messages that the publisher sends This is because as the subscriber connects to the publisher (some‐

thing that takes a small but nonzero amount of time), the publisher may already besending messages out

This “slow joiner” symptom hits enough people, often enough, that we’re going to ex‐plain it in detail Remember that ØMQ does asynchronous I/O (i.e., in the background).Say you have two nodes doing this, in this order:

• Subscriber connects to an endpoint and receives and counts messages

• Publisher binds to an endpoint and immediately sends 1,000 messages

The subscriber will most likely not receive anything You’ll blink, check that you set acorrect filter, and try again, and the subscriber will still not receive anything

Trang 35

Making a TCP connection involves to and from handshaking that can take several mil‐liseconds (msec), depending on your network and the number of hops between peers.

In that time, ØMQ can send very many messages For the sake of argument, assume ittakes 5 msec to establish a connection, and that same link can handle 1M messages persecond During the 5 msec that the subscriber is connecting to the publisher, it takesthe publisher only 1 msec to send out those 1K messages

In Chapter 2, we’ll explain how to synchronize a publisher and subscribers so that youdon’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 realapplication, though, because it is extremely fragile as well as inelegant and slow Usesleeps to prove to yourself what’s happening, and then read Chapter 2 to see how to dothis 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 carewhat transpired before it started up This is how we built our weather client example

So, the client subscribes to its chosen zip code and collects a thousand updates for thatzip code That means about 10 million updates from the server, if zip codes are randomlydistributed You can start the client, and then the server, and the client will keep working.You can stop and restart the server as often as you like, and the client will keep working.When the client has collected its thousand updates, it calculates the average, prints it,and exits

Some points about the publish-subscribe pattern:

• A subscriber can connect to more than one publisher, using one connect call eachtime Data will then arrive and be interleaved (“fair queued”) so that no single pub‐lisher drowns out the others

• If a publisher has no connected subscribers, then it will simply drop all messages

• If you’re using TCP and a subscriber is slow, messages will queue up on the pub‐lisher We’ll look at how to protect publishers against this by using the “high-watermark” in the next chapter

• From ØMQ v3.x, filtering happens on the publisher’s side when using a connectedprotocol (tcp or ipc) Using the epgm protocol, filtering happens on the subscriber’sside In ØMQ v2.x, all filtering happened on the subscriber’s side

This is how long it takes to receive and filter 10M messages on my laptop, which is a2011-era Intel I7—fast, but nothing special:

ph@nb201103:~/work/git/zguide/examples/c$ time wuclient

Collecting updates from weather server

Average temperature for zipcode '10001 ' was 28F

Getting the Message Out | 15

Trang 36

real 0m4.470s

user 0m0.000s

sys 0m0.008s

Divide and Conquer

As a final example (you are surely getting tired of juicy code and want to delve back intophilological discussions about comparative abstractive norms), let’s do a little super‐computing Then, coffee Our supercomputing application is a fairly typical parallelprocessing model (Figure 1-5) We have:

• A ventilator that produces tasks that can be done in parallel

• A set of workers that processes tasks

• A sink that collects results back from the worker processes

Figure 1-5 Parallel pipeline

In reality, workers run on superfast boxes, perhaps using GPUs (graphic processingunits) to do the hard math Example 1-8 shows the code for the ventilator Itgenerates 100 tasks, each one a message telling the worker to sleep for some number ofmilliseconds

Trang 37

Example 1-8 Parallel task ventilator (taskvent.c)

//

// Task ventilator

// Binds PUSH socket to tcp://localhost:5557

// Sends batch of tasks to workers via that socket

//

#include "zhelpers.h"

int main void)

{

void context zmq_ctx_new ();

// Socket to send messages on

void sender zmq_socket context , ZMQ_PUSH );

zmq_bind sender , "tcp://*:5557" );

// Socket to send start of batch message on

void sink zmq_socket context , ZMQ_PUSH );

zmq_connect sink , "tcp://localhost:5558" );

printf "Press Enter when the workers are ready: " );

getchar ();

printf "Sending tasks to workers \n");

// The first message is "0" and signals start of batch

s_send sink , "0" );

// Initialize random number generator

srandom ((unsigned) time NULL ));

// Send 100 tasks

int task_nbr ;

int total_msec ; // Total expected cost in msec

for task_nbr ; task_nbr 100 ; task_nbr ++ ) {

sprintf string , "%d" , workload );

s_send sender , string );

}

printf "Total expected cost: %d msec\n", total_msec );

sleep 1 ); // Give 0MQ time to deliver

Trang 38

The code for the worker application is in Example 1-9 It receives a message, sleeps forthat number of seconds, and then signals that it’s finished.

Example 1-9 Parallel task worker (taskwork.c)

//

// Task worker

// Connects PULL socket to tcp://localhost:5557

// Collects workloads from ventilator via that socket

// Connects PUSH socket to tcp://localhost:5558

// Sends results to sink via that socket

//

#include "zhelpers.h"

int main void)

{

void context zmq_ctx_new ();

// Socket to receive messages on

void receiver zmq_socket context, ZMQ_PULL);

zmq_connect receiver, "tcp://localhost:5557" );

// Socket to send messages to

void sender zmq_socket context, ZMQ_PUSH);

zmq_connect sender, "tcp://localhost:5558" );

// Process tasks forever

char string s_recv receiver);

// Simple progress indicator for the viewer

Trang 39

Example 1-10 Parallel task sink (tasksink.c)

//

// Task sink

// Binds PULL socket to tcp://localhost:5558

// Collects results from workers via that socket

//

#include "zhelpers.h"

int main void)

{

// Prepare our context and socket

void context zmq_ctx_new ();

void receiver zmq_socket context, ZMQ_PULL);

zmq_bind receiver, "tcp://*:5558" );

// Wait for start of batch

char string s_recv receiver);

free string);

// Start our clock now

int64_t start_time s_clock ();

// Process 100 confirmations

int task_nbr;

for task_nbr ; task_nbr 100 ; task_nbr ++ ) {

char string s_recv receiver);

// Calculate and report duration of batch

printf "Total elapsed time: %d msec\n",

(int) (s_clock () start_time));

zmq_close receiver);

zmq_ctx_destroy context);

}

The average cost of a batch is five seconds When we start one, two, and four workers,

we get results like this from the sink:

Total elapsed time: 1018 msec

Divide and Conquer | 19

Trang 40

Let’s look at some aspects of this code in more detail:

• The workers connect upstream to the ventilator, and downstream to the sink Thismeans you can add workers arbitrarily If the workers bound to their endpoints,you would need (a) more endpoints and (b) to modify the ventilator and/or the

sink each time you added a worker We say that the ventilator and sink are stable parts of our architecture and the workers are dynamic parts of it.

• We have to synchronize the start of the batch with all workers being up and running.This is a fairly common gotcha in ØMQ, and there is no easy solution The connect method takes a certain amount of time, so when a set of workers connect tothe ventilator, the first one to successfully connect will get a whole load of messages

in that short time while the others are still connecting If you don’t synchronize thestart of the batch somehow, the system won’t run in parallel at all Try removing thewait in the ventilator, and see what happens

• The ventilator’s PUSH socket distributes tasks to workers (assuming they are all

connected before the batch starts going out) evenly This is called load balancing,

and it’s something we’ll look at again in more detail

• The sink’s PULL socket collects results from workers evenly This is called fair queuing (Figure 1-6)

Figure 1-6 Fair queuing

The pipeline pattern also exhibits the “slow joiner” syndrome, leading to accusationsthat PUSH sockets don’t load-balance properly If you are using PUSH and PULL andone of your workers gets way more messages than the others, it’s because that PULLsocket has joined faster than the others, and grabs a lot of messages before the othersmanage to connect

Ngày đăng: 31/03/2014, 08:20

Xem thêm

TỪ KHÓA LIÊN QUAN

w