Table of Contents
Preface xiii
1 Why Event-Driven Microservices 1
What Are Event-Driven Microservices? 2
Introduction to Domain-Driven Design and Bounded Contexts 3
Leveraging Domain Models and Bounded Contexts 4
Aligning Bounded Contexts with Business Requirements 5
Communication Structures 6
Business Communication Structures 7
Implementation Communication Structures 7
Data Communication Structures 8
Conway's Law and Communication Structures 9
Communication Structures in Traditional Computing 10
Option 1 Make a New Service 10
Option 2 Add It to the Existing Service 11
Pros and Cons of Each Option 11
The Team Scenario, Continued 13
Conflicting Pressures 13
Event-Driven Communication Structures 13
Events Are the Basis of Communication 14
Event Streams Provide the Single Source of Truth 14
Consumers Perform Their Own Modeling and Querying 14
Data Communication Is Improved Across the Organization 15
Accessible Data Supports Business Communication Changes 15
Asynchronous Event-Driven Microservices 15
Example Team Using Event-Driven Microservices 16
Synchronous Microservices 17
Drawbacks of Synchronous Microservices 17
Benefits of Synchronous Microservices 19
Summary 20
2 Event-Driven Microservice Fundamentals 21
Building Topologies 21
Microservice Topology 21
Business Topology 22
The Contents of an Event 23
The Structure of an Event 23
Unkeyed Event 24
Entity Event 24
Keyed Event 24
Materializing State from Entity Events 25
Event Data Definitions and Schemas 27
Microservice Single Writer Principle 28
Powering Microservices with the Event Broker 28
Event Storage and Serving 29
Additional Factors to Consider 30
Event Brokers Versus Message Brokers 31
Consuming from the Immutable Log 32
Providing a Single Source of Truth 34
Managing Microservices at Scale 34
Putting Microservices into Containers 35
Putting Microservices into Virtual Machines 35
Managing Containers and Virtual Machines 35
Paying the Microservice Tax 35
Summary 37
3 Communication and Data Contracts 39
Event-Driven Data Contracts 39
Using Explicit Schemas as Contracts 40
Schema Definition Comments 41
Full-Featured Schema Evolution 41
Code Generator Support 42
Breaking Schema Changes 43
Selecting an Event Format 45
Designing Events 45
Tell the Truth, the Whole Truth, and Nothing but the Truth 46
Use a Singular Event Definition per Stream 46
Use the Narrowest Data Types 47
Keep Events Single-Purpose 47
Minimize the Size of Events 51
Involve Prospective Consumers in the Event Design 51
Avoid Events as Semaphores or Signals 51
Summary 52
4 Integrating Event-Driven Architectures with Existing Systems 53
What Is Data Liberation? 54
Compromises for Data Liberation 55
Converting Liberated Data to Events 57
Data Liberation Patterns 57
Data Liberation Frameworks 58
Liberating Data by Query 58
Bulk Loading 59
Incremental Timestamp Loading 59
Autoincrementing ID Loading 59
Custom Querying 59
Incremental Updating 59
Benefits of Query-Based Updating 60
Drawbacks of Query-Based Updating 61
Liberating Data Using Change-Data Capture Logs 61
Benefits of Using Data Store Logs 63
Drawbacks of Using Data Base Logs 63
Liberating Data Using Outbox Tables 64
Performance Considerations 65
Isolating Internal Data Models 65
Ensuring Schema Compatibility 67
Capturing Change-Data Using Triggers 70
Making Data Definition Changes to Data Sets Under Capture 74
Handling After-the-Fact Data Definition Changes for the Query and CDC Log Patterns 75
Handling Data Definition Changes for Change-Data Table Capture Patterns 75
Sinking Event Data to Data Stores 75
The Impacts of Sinking and Sourcing on a Business 76
Summary 78
5 Event-Driven Processing Basics 79
Composing Stateless Topologies 80
Transformations 81
Branching and Merging Streams 81
Repartitioning Event Streams 81
Example: Repartitioning an Event Stream 82
Copartitioning Event Streams 83
Example: Copartitioning an Event Stream 83
Assigning Partitions to a Consumer Instance 84
Assigning Partitions with the Partition Assignor 84
Assigning Copartitioned Partitions 85
Partition Assignment Strategies 85
Recovering from Stateless Processing Instance Failures 87
Summary 87
6 Deterministic Stream Processing 89
Determinism with Event-Driven Workflows 90
Timestamps 90
Synchronizing Distributed Timestamps 92
Processing with Timestamps Events 92
Event Scheduling and Deterministic Processing 93
Custom Event Schedulers 94
Processing Based on Event Time, Processing Time, and Ingestion Time 94
Timestamp Extraction by the Consumer 95
Request-Response Calls to External Systems 95
Watermarks 95
Watermarks in Parallel Processing 96
Stream Time 97
Stream Time in Parallel Processing 98
Out-of-Order and Late-Arriving Events 99
Late Events with Watermarks and Stream Time 101
Causes and Impacts of Out-of-Order Events 101
Time-Sensitive Functions and Windowing 103
Handling Late Events 105
Reprocessing Versus Processing in Near-Real Time 106
Intermittent Failures and Late Events 107
Producer/Event Broker Connectivity Issues 108
Summary and Further Reading 109
7 Stateful Streaming 111
State Stores and Materializing State from an Event Stream 111
Recording State to a Changelog Event Stream 112
Materializing State to an Internal State Store 113
Materializing Global State 114
Advantages of Using Internal State 114
Disadvantages of Using Internal State 116
Scaling and Recovery of Internal State 116
Materializing State to an External State Store 120
Advantages of External State 120
Drawbacks of External State 121
Scaling and Recovery with External State Stores 122
Rebuilding Versus Migrating State Stores 124
Rebuilding 124
Migrating 124
Transactions and Effectively Once Processing 125
Example: Stock Accounting Service 126
Effectively Once Processing with Client-Broker Transactions 127
Effectively Once Processing Without Client-Broker Transactions 128
Summary 133
8 Building Workflows with Microservices 135
The Choreography Pattern 136
A Simple Event-Driven Choreography Example 137
Creating and Modifying a Choreographed Workflow 138
Monitoring a Choreographed Workflow 139
The Orchestration Pattern 139
A Simple Event-Driven Orchestration Example 141
A Simple Direct-Call Orchestration Example 142
Comparing Direct-Call and Event-Driven Orchestration 142
Creating and Modifying an Orchestration Workflow 143
Monitoring the Orchestration Workflow 144
Distributed Transactions 144
Choreographed Transactions: The Saga Pattern 145
Orchestrated Transactions 146
Compensation Workflows 149
Summary 149
9 Microservices Using Function-as-a-Service 151
Designing Function-Based Solutions as Microservices 151
Ensure Strict Membership to a Bounded Context 151
Commit Offsets Only After Processing Has Completed 152
Less Is More 153
Choosing a FaaS Provider 153
Building Microservices Out of Functions 153
Cold Start and Warm Starts 155
Starting Functions with Triggers 155
Triggering Based on New Events: The Event-Stream Listener 155
Triggering Based on Consumer Group Lag 157
Triggering on a Schedule 158
Triggering Using Webhooks 159
Triggering on Resource Events 159
Performing Business Work with Functions 159
Maintaining State 160
Functions Calling Other Functions 160
Event-Driven Communication Pattern 161
Direct-Call Pattern 162
Termination and Shutdown 165
Tuning Your Functions 165
Allocating Sufficient Resources 165
Batch Event-Processing Parameters 166
Scaling Your FaaS Solutions 166
Summary 167
10 Basic Producer and Consumer Microservices 169
Where Do BPCs Work Well? 170
Integration with Existing and Legacy Systems 170
Stateful Business Logic That Isn't Reliant Upon Event Order 171
When the Data Layer Does Much of the Work 172
Independent Scaling of the Processing and Data Layer 173
Hybrid BPC Applications with External Stream Processing 174
Example: Using an External Stream-Processing Framework to Join Event Streams 174
Summary 176
11 Heavyweight Framework Microservices 177
A Brief History of Heavyweight Frameworks 178
The Inner Workings of Heavyweight Frameworks 179
Benefits and Limitations 181
Cluster Setup Options and Execution Modes 183
Use a Hosted Service 183
Build Your Own Full Cluster 183
Create Clusters with CMS Integration 184
Application Submission Modes 186
Driver Mode 186
Cluster Mode 186
Handling State and Using Checkpoints 186
Scaling Applications and Handling Event Stream Partitions 188
Scaling an Application While It Is Running 189
Scaling an Application by Restarting It 191
Autoscaling Applications 192
Recovering from Failures 192
Multitenancy Considerations 192
Languages and Syntax 193
Choosing a Framework 193
Example: Session Windowing of Clicks and Views 194
Summary 197
12 Lightweight Framework Microservices 199
Benefits and Limitations 199
Lightweight Processing 200
Handling State and Using Changelogs 201
Scaling Applications and Recovering from Failures 201
Event Shuffling 202
State Assignment 202
State Replication and Hot Replicas 203
Choosing a Lightweight Framework 203
Apache Kafka Streams 203
Apache Samza: Embedded Mode 204
Languages and Syntax 204
Stream-Table-Table Join: Enrichment Pattern 205
Summary 209
13 Integrating Event-Driven and Request-Response Microservices 211
Handling External Events 211
Autonomously Generated Events 212
Reactively Generated Events 212
Handling Autonomously Generated Analytical Events 213
Integrating with Third-Party Request-Response APIs 214
Processing and Serving Stateful Data 216
Serving Real-Time Requests with Internal State Stores 217
Serving Real-Time Requests with External State Stores 220
Handling Requests Within an Event-Driven Workflow 223
Processing Events for User Interfaces 224
Micro-Frontends in Request-Response Applications 231
The Benefits of Microfrontends 232
Composition-Based Microservices 232
Easy Alignment to Business Requirements 232
Drawbacks of Microfrontends 233
Potentially Inconsistent UI Elements and Styling 233
Varying Microfrontend Performance 233
Example: Experience Search and Review Application 234
Summary 237
14 Supportive Tooling 239
Microservice-to-Team Assignment System 239
Event Stream Creation and Modification 240
Event Stream Metadata Tagging 240
Quotas 241
Schema Registry 241
Schema Creation and Modification Notifications 243
Offset Management 243
Permissions and Access Control Lists for Event Streams 244
State Management and Application Reset 245
Consumer Offset Lag Monitoring 246
Streamlined Microservice Creation Process 247
Container Management Controls 247
Cluster Creation and Management 248
Programmatic Bringup of Event Brokers 248
Programmatic Bringup of Compute Resources 248
Cross-Cluster Event Data Replication 249
Programmatic Bringup of Tooling 249
Dependency Tracking and Topology Visualization 250
Topology Example 251
Summary 254
15 Testing Event-Driven Microservices 255
General Testing Principles 255
Unit-Testing Topology Functions 256
Stateless Functions 256
Stateful Functions 256
Testing the Topology 257
Testing Schema Evolution and Compatibility 258
Integration Testing of Event-Driven Microservices 258
Local Integration Testing 259
Create a Temporary Environment Within the Runtime of Your Test Code 261
Create a Temporary Environment External to Your Test Code 262
Integrate Hosted Services Using Mocking and Simulator Options 263
Integrate Remote Services That Have No Local Options 264
Full Remote Integration Testing 265
Programmatically Create a Temporary Integration Testing Environment 265
Testing Using a Shared Environment 268
Testing Using the Production Environment 269
Choosing Your Full-Remote Integration Testing Strategy 270
Summary 270
16 Deploying Event-Driven Microservices 273
Principles of Microservice Deployment 273
Architectural Components of Microservice Deployment 274
Continuous Integration, Delivery, and Deployment Systems 275
Container Management Systems and Commodity Hardware 276
The Basic Full-Stop Deployment Pattern 276
The Rolling Update Pattern 278
The Breaking Schema Change Pattern 279
Eventual Migration via Two Event Streams 280
Synchronized Migration to the New Event Stream 281
The Blue-Green Deployment Pattern 282
Summary 283
17 Conclusion 285
Communication Layers 285
Business Domains and Bounded Contexts 286
Shareable Tools and Infrastructure 286
Schematized Events 287
Data Liberation and the Single Source of Truth 287
Microservices 288
Microservice Implementation Options 288
Testing 289
Deploying 289
Final Words 290
Index 293