Reactive Design Patterns
Total Page:16
File Type:pdf, Size:1020Kb
Reactive Design Patterns ROLAND KUHN WITH BRIAN HANAFEE AND JAMIE ALLEN FOREWORD BY JONAS BONÉR MANNING SHELTER ISLAND For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Email: [email protected] ©2017 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. Development editor: Jennifer Stout 20 Baldwin Road Technical development editor: Brian Hanafee PO Box 761 Project editors: Tiffany Taylor and Janet Vail Shelter Island, NY 11964 Line editor: Ben Kovitz Copyeditor: Tiffany Taylor Proofreader: Katie Tennant Technical proofreader: Thomas Lockney Typesetter: Dottie Marsico Cover designer: Leslie Haimes ISBN 9781617291807 Printed in the United States of America 1 2 3 4 5 6 70 8 9 10 – EBM – 22 21 20 19 18 17 To my children — Roland brief contents PART 1 INTRODUCTION................................................................ 1 1 ■ Why Reactive? 3 2 ■ A walk-through of the Reactive Manifesto 12 3 ■ Tools of the trade 39 PART 2 THE PHILOSOPHY IN A NUTSHELL ................................... 65 4 ■ Message passing 67 5 ■ Location transparency 81 6 ■ Divide and conquer 91 7 ■ Principled failure handling 100 8 ■ Delimited consistency 105 9 ■ Nondeterminism by need 113 10 ■ Message flow 120 PART 3 PATTERNS .................................................................... 125 11 ■ Testing reactive applications 127 12 ■ Fault tolerance and recovery patterns 162 13 ■ Replication patterns 184 14 ■ Resource-management patterns 220 15 ■ Message flow patterns 255 16 ■ Flow control patterns 294 17 ■ State management and persistence patterns 311 v contents foreword xv preface xvii acknowledgments xix about this book xxi about the authors xxiv PART 1 INTRODUCTION.................................................1 Why Reactive? 3 1 1.1 The anatomy of a Reactive application 4 1.2 Coping with load 5 1.3 Coping with failures 7 1.4 Making the system responsive 8 1.5 Avoiding the ball of mud 10 1.6 Integrating nonreactive components 10 1.7 Summary 11 A walk-through of the Reactive Manifesto 12 2 2.1 Reacting to users 12 Understanding the traditional approach 13 ■ Analyzing latency with a shared resource 15 ■ Limiting maximum latency with a queue 16 vii viii CONTENTS 2.2 Exploiting parallelism 18 Reducing latency via parallelization 18 ■ Improving parallelism with composable Futures 20 ■ Paying for the serial illusion 21 2.3 The limits of parallel execution 23 Amdahl’s Law 23 ■ Universal Scalability Law 24 2.4 Reacting to failure 26 Compartmentalization and bulkheading 28 ■ Using circuit breakers 29 ■ Supervision 30 2.5 Losing strong consistency 31 ACID 2.0 33 ■ Accepting updates 34 2.6 The need for Reactive design patterns 35 Managing complexity 36 ■ Bringing programming models closer to the real world 37 2.7 Summary 38 Tools of the trade 39 3 3.1 Early Reactive solutions 39 3.2 Functional programming 41 Immutability 41 ■ Referential transparency 44 ■ Side effects 45 ■ Functions as first-class citizens 46 3.3 Responsiveness to users 47 Prioritizing the three performance characteristics 47 3.4 Existing support for Reactive design 48 Green threads 48 ■ Event loops 49 ■ Communicating Sequential Processes 50 ■ Futures and promises 52 Reactive Extensions 57 ■ The Actor model 58 Summary 62 PART 2 THE PHILOSOPHY IN A NUTSHELL ....................65 Message passing 67 4 4.1 Messages 67 4.2 Vertical scalability 68 4.3 Event-based vs. message-based 69 4.4 Synchronous vs. asynchronous 71 4.5 Flow control 73 CONTENTS ix 4.6 Delivery guarantees 76 4.7 Events as messages 78 4.8 Synchronous message passing 80 4.9 Summary 80 Location transparency 81 5 5.1 What is location transparency? 81 5.2 The fallacy of transparent remoting 82 5.3 Explicit message passing to the rescue 83 5.4 Optimization of local message passing 84 5.5 Message loss 85 5.6 Horizontal scalability 87 5.7 Location transparency makes testing simpler 87 5.8 Dynamic composition 88 5.9 Summary 90 Divide and conquer 91 6 6.1 Hierarchical problem decomposition 92 Defining the hierarchy 92 6.2 Dependencies vs. descendant modules 94 Avoiding the matrix 95 6.3 Building your own big corporation 96 6.4 Advantages of specification and testing 97 6.5 Horizontal and vertical scalability 98 6.6 Summary 99 Principled failure handling 100 7 7.1 Ownership means commitment 100 7.2 Ownership implies lifecycle control 102 7.3 Resilience on all levels 104 7.4 Summary 104 Delimited consistency 105 8 8.1 Encapsulated modules to the rescue 106 8.2 Grouping data and behavior according to transaction boundaries 107 x CONTENTS 8.3 Modeling workflows across transactional boundaries 107 8.4 Unit of failure = unit of consistency 108 8.5 Segregating responsibilities 109 8.6 Persisting isolated scopes of consistency 111 8.7 Summary 112 Nondeterminism by need 113 9 9.1 Logic programming and declarative data flow 113 9.2 Functional reactive programming 115 9.3 Sharing nothing simplifies concurrency 116 9.4 Shared-state concurrency 117 9.5 So, what should we do? 117 9.6 Summary 119 Message flow 120 10 10.1 Pushing data forward 120 10.2 Modeling the processes of your domain 122 10.3 Identifying resilience limitations 122 10.4 Estimating rates and deployment scale 123 10.5 Planning for flow control 124 10.6 Summary 124 PART 3 PATTERNS .....................................................125 Testing reactive applications 127 11 11.1 How to test 127 Unit tests 128 ■ Component tests 129 ■ String tests 129 Integration tests 129 ■ User-acceptance tests 130 ■ Black-box vs. white-box tests 130 11.2 Test environment 131 11.3 Testing asynchronously 132 Providing blocking message receivers 133 ■ The crux of choosing timeouts 135 ■ Asserting the absence of a message 141 Providing synchronous execution engines 142 ■ Asynchronous assertions 144 ■ Fully asynchronous tests 145 ■ Asserting the absence of asynchronous errors 147 CONTENTS xi 11.4 Testing nondeterministic systems 150 The trouble with execution schedules 151 ■ Testing distributed components 151 ■ Mocking Actors 152 ■ Distributed components 153 11.5 Testing elasticity 154 11.6 Testing resilience 154 Application resilience 155 ■ Infrastructure resilience 158 11.7 Testing responsiveness 160 11.8 Summary 161 Fault tolerance and recovery patterns 162 12 12.1 The Simple Component pattern 162 The problem setting 163 ■ Applying the pattern 163 The pattern, revisited 165 ■ Applicability 166 12.2 The Error Kernel pattern 166 The problem setting 167 ■ Applying the pattern 167 The pattern, revisited 170 ■ Applicability 171 12.3 The Let-It-Crash pattern 171 The problem setting 172 ■ Applying the pattern 172 The pattern, revisited 173 ■ Implementation considerations 174 ■ Corollary: the Heartbeat pattern 175 Corollary: the Proactive Failure Signal pattern 176 12.4 The Circuit Breaker pattern 177 The problem setting 177 ■ Applying the pattern 178 The pattern, revisited 181 ■ Applicability 182 12.5 Summary 182 Replication patterns 184 13 13.1 The Active–Passive Replication pattern 184 The problem setting 185 ■ Applying the pattern 186 The pattern, revisited 196 ■ Applicability 197 13.2 Multiple-Master Replication patterns 197 Consensus-based replication 198 ■ Replication with conflict detection and resolution 201 ■ Conflict-free replicated data types 203 13.3 The Active–Active Replication pattern 210 The problem setting 211 ■ Applying the pattern 211 xii CONTENTS The pattern, revisited 217 ■ The relation to virtual synchrony 218 13.4 Summary 219 Resource-management patterns 220 14 14.1 The Resource Encapsulation pattern 221 The problem setting 221 ■ Applying the pattern 221 The pattern, revisited 227 ■ Applicability 228 14.2 The Resource Loan pattern 229 The problem setting 229 ■ Applying the pattern 230 The pattern, revisited 232 ■ Applicability 233 Implementation considerations 233 ■ Variant: using the Resource Loan pattern for partial exposure 234 14.3 The Complex Command pattern 234 The problem setting 235 ■ Applying the pattern 236 The pattern, revisited 243 ■ Applicability 243 14.4 The Resource Pool pattern 244 The problem setting 244 ■ Applying the pattern 245 The pattern, revisited 247 ■ Implementation considerations 248 14.5 Patterns for managed blocking 248 The problem setting 249 ■ Applying the pattern 249 The pattern, revisited 251 ■ Applicability 253 14.6 Summary 253 Message flow patterns 255 15 15.1 The Request–Response pattern 255 The problem setting 256 ■ Applying the pattern 257 Common instances of the pattern 258 ■ The pattern,