Tải bản đầy đủ

Microservices patterns

Chris Richardson

MANNING


List of Patterns
Application architecture patterns

External API patterns

Monolithic architecture (40)
Microservice architecture (40)

API gateway (259)
Backends for frontends (265)

Decomposition patterns

Testing patterns

Decompose by business capability (51)

Decompose by subdomain (54)

Consumer-driven contract test (302)
Consumer-side contract test (303)
Service component test (335)

Messaging style patterns
Messaging (85)
Remote procedure invocation (72)

Security patterns

Reliable communications patterns

Cross-cutting concerns patterns

Circuit breaker (78)

Externalized configuration (361)
Microservice chassis (379)

Service discovery patterns
3rd party registration (85)
Client-side discovery (83)
Self-registration (82)
Server-side discovery (85)

Transactional messaging patterns
Polling publisher (98)
Transaction log tailing (99)
Transactional outbox (98)

Data consistency patterns
Saga (114)

Business logic design patterns
Aggregate (150)
Domain event (160)
Domain model (150)
Event sourcing (184)


Transaction script (149)

Querying patterns
API composition (223)
Command query responsibility segregation
(228)

Access token (354)

Observability patterns
Application metrics (373)
Audit logging (377)
Distributed tracing (370)
Exception tracking (376)
Health check API (366)
Log aggregation (368)

Deployment patterns
Deploy a service as a container (393)
Deploy a service as a VM (390)
Language-specific packaging format (387)
Service mesh (380)
Serverless deployment (416)
Sidecar (410)

Refactoring to microservices patterns
Anti-corruption layer (447)
Strangler application (432)


Microservices Patterns



Microservices Patterns
WITH EXAMPLES IN JAVA
CHRIS RICHARDSON

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: orders@manning.com
©2019 by Chris Richardson. 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.
20 Baldwin Road
PO Box 761
Shelter Island, NY 11964

Development editor:
Technical development editor:
Review editor:
Project editor:
Copy editor:
Proofreader:
Technical proofreader:
Typesetter:
Cover designer:

ISBN: 9781617294549
Printed in the United States of America
1 2 3 4 5 6 7 8 9 10 – DP – 23 22 21 20 19 18

Marina Michaels
Christian Mennerich
Aleksandar Dragosavljevic´
Lori Weidert
Corbin Collins
Alyson Brener
Andy Miles
Dennis Dalinnik
Marija Tudor


Where you see wrong or inequality or injustice, speak out, because this is your country.
This is your democracy. Make it. Protect it. Pass it on.
— Thurgood Marshall, Justice of the Supreme Court



brief contents
1



Escaping monolithic hell

2



Decomposition strategies 33

3



Interprocess communication in a microservice
architecture 65

4



Managing transactions with sagas 110

5



Designing business logic in a microservice
architecture 146

6



Developing business logic with event sourcing 183

7



Implementing queries in a microservice architecture 220

8



External API patterns 253

9



Testing microservices: Part 1

292

10



Testing microservices: Part 2

318

11



Developing production-ready services 348

12



Deploying microservices 383

13



Refactoring to microservices 428

vii

1



contents
preface xvii
acknowledgments xx
about this book xxii
about the cover illustration xxvi

1

Escaping monolithic hell 1
1.1

The slow march toward monolithic hell 2
The architecture of the FTGO application 3 The benefits of the
monolithic architecture 4 Living in monolithic hell 4




1.2
1.3
1.4

Why this book is relevant to you 7
What you’ll learn in this book 7
Microservice architecture to the rescue 8
Scale cube and microservices 8 Microservices as a form of
modularity 11 Each service has its own database 12
The FTGO microservice architecture 12 Comparing the
microservice architecture and SOA 13






1.5

Benefits and drawbacks of the microservice
architecture 14
Benefits of the microservice architecture 14
microservice architecture 17

ix



Drawbacks of the


CONTENTS

x

1.6

The Microservice architecture pattern language 19
Microservice architecture is not a silver bullet 19 Patterns and
pattern languages 20 Overview of the Microservice architecture
pattern language 23




1.7

Beyond microservices: Process and organization 29
Software development and delivery organization 29 Software
development and delivery process 30 The human side of
adopting microservices 31




2

Decomposition strategies 33
2.1

What is the microservice architecture exactly?

34

What is software architecture and why does it matter? 34
Overview of architectural styles 37 The microservice architecture
is an architectural style 40


2.2

Defining an application’s microservice architecture 44
Identifying the system operations 45 Defining services by
applying the Decompose by business capability pattern 51
Defining services by applying the Decompose by sub-domain
pattern 54 Decomposition guidelines 56 Obstacles to
decomposing an application into services 57 Defining service
APIs 61








3

Interprocess communication in a microservice architecture 65
3.1

Overview of interprocess communication in a microservice
architecture 66
Interaction styles 67 Defining APIs in a microservice
architecture 68 Evolving APIs 69 Message formats 71




3.2



Communicating using the synchronous Remote
procedure invocation pattern 72
Using REST 73 Using gRPC 76 Handling partial failure
using the Circuit breaker pattern 77 Using service discovery 80






3.3

Communicating using the Asynchronous messaging
pattern 85
Overview of messaging 86 Implementing the interaction styles
using messaging 87 Creating an API specification for a
messaging-based service API 89 Using a message broker 90
Competing receivers and message ordering 94 Handling
duplicate messages 95 Transactional messaging 97
Libraries and frameworks for messaging 100











CONTENTS

3.4

xi

Using asynchronous messaging to improve
availability 103
Synchronous communication reduces availability
Eliminating synchronous interaction 104

4

103

Managing transactions with sagas 110
4.1

Transaction management in a microservice
architecture 111
The need for distributed transactions in a microservice
architecture 112 The trouble with distributed
transactions 112 Using the Saga pattern to maintain
data consistency 114




4.2

Coordinating sagas 117
Choreography-based sagas

4.3

118

Orchestration-based sagas 121

Handling the lack of isolation 126
Overview of anomalies 127
lack of isolation 128

4.4





Countermeasures for handling the

The design of the Order Service and
the Create Order Saga 132
The OrderService class 133 The implementation of the Create
Order Saga 135 The OrderCommandHandlers class 142
The OrderServiceConfiguration class 143




5

Designing business logic in a microservice architecture 146
5.1

Business logic organization patterns 147
Designing business logic using the Transaction script pattern 149
Designing business logic using the Domain model pattern 150
About Domain-driven design 151

5.2

Designing a domain model using the
DDD aggregate pattern 152
The problem with fuzzy boundaries 153 Aggregates have
explicit boundaries 154 Aggregate rules 155 Aggregate
granularity 158 Designing business logic with aggregates 159








5.3

Publishing domain events 160
Why publish change events? 160 What is a domain
event? 161 Event enrichment 161 Identifying domain
events 162 Generating and publishing domain events 164
Consuming domain events 167









CONTENTS

xii

5.4

Kitchen Service business logic

168

The Ticket aggregate 169

5.5

Order Service business logic
The Order Aggregate

6

175



173

The OrderService class

180

Developing business logic with event sourcing 183
6.1

Developing business logic using event sourcing 184
The trouble with traditional persistence 185 Overview of event
sourcing 186 Handling concurrent updates using optimistic
locking 193 Event sourcing and publishing events 194
Using snapshots to improve performance 195 Idempotent
message processing 197 Evolving domain events 198
Benefits of event sourcing 199 Drawbacks of event
sourcing 200












6.2

Implementing an event store

202

How the Eventuate Local event store works 203
client framework for Java 205

6.3



The Eventuate

Using sagas and event sourcing together 209
Implementing choreography-based sagas using event sourcing 210
Creating an orchestration-based saga 211 Implementing an
event sourcing-based saga participant 213 Implementing saga
orchestrators using event sourcing 216




7

Implementing queries in a microservice architecture 220
7.1

Querying using the API composition pattern 221
The findOrder() query operation 221 Overview of the API
composition pattern 222 Implementing the findOrder() query
operation using the API composition pattern 224 API
composition design issues 225 The benefits and drawbacks
of the API composition pattern 227








7.2

Using the CQRS pattern 228
Motivations for using CQRS 229 Overview of CQRS 232
The benefits of CQRS 235 The drawbacks of CQRS 236




7.3

Designing CQRS views 236
Choosing a view datastore 237 Data access module design 239
Adding and updating CQRS views 241


7.4

Implementing a CQRS view with AWS DynamoDB 242
The OrderHistoryEventHandlers module 243
Data modeling and query design with DynamoDB 244
The OrderHistoryDaoDynamoDb class 249


CONTENTS

8

xiii

External API patterns 253
8.1

External API design issues 254
API design issues for the FTGO mobile client 255
issues for other kinds of clients 258

8.2



API design

The API gateway pattern 259
Overview of the API gateway pattern 259 Benefits and
drawbacks of an API gateway 267 Netflix as an example
of an API gateway 267 API gateway design issues 268






8.3

Implementing an API gateway 271
Using an off-the-shelf API gateway product/service 271
Developing your own API gateway 273 Implementing an
API gateway using GraphQL 279


9

Testing microservices: Part 1 292
9.1

Testing strategies for microservice architectures 294
Overview of testing 294 The challenge of testing
microservices 299 The deployment pipeline 305




9.2

Writing unit tests for a service 307
Developing unit tests for entities 309 Writing unit tests for value
objects 310 Developing unit tests for sagas 310 Writing
unit tests for domain services 312 Developing unit tests for
controllers 313 Writing unit tests for event and message
handlers 315










10

Testing microservices: Part 2 318
10.1

Writing integration tests 319
Persistence integration tests 321 Integration testing REST-based
request/response style interactions 322 Integration testing
publish/subscribe-style interactions 326 Integration contract
tests for asynchronous request/response interactions 330






10.2

Developing component tests 335
Defining acceptance tests 336 Writing acceptance tests using
Gherkin 337 Designing component tests 339 Writing
component tests for the FTGO Order Service 340




10.3



Writing end-to-end tests 345
Designing end-to-end tests 345
Running end-to-end tests 346



Writing end-to-end tests 346


CONTENTS

xiv

11

Developing production-ready services 348
11.1

Developing secure services 349
Overview of security in a traditional monolithic application 350
Implementing security in a microservice architecture 353

11.2

Designing configurable services 360
Using push-based externalized configuration 362
based externalized configuration 363

11.3



Using pull-

Designing observable services 364
Using the Health check API pattern 366 Applying the Log
aggregation pattern 368 Using the Distributed tracing
pattern 370 Applying the Application metrics pattern 373
Using the Exception tracking pattern 376 Applying the Audit
logging pattern 377








11.4

Developing services using the Microservice chassis
pattern 378
Using a microservice chassis
service mesh 380

12

379



From microservice chassis to

Deploying microservices 383
12.1

Deploying services using the Language-specific packaging
format pattern 386
Benefits of the Service as a language-specific package pattern
Drawbacks of the Service as a language-specific package
pattern 389

12.2

Deploying services using the Service as a virtual machine
pattern 390
The benefits of deploying services as VMs 392
deploying services as VMs 392

12.3

388



The drawbacks of

Deploying services using the Service as a container
pattern 393
Deploying services using Docker 395 Benefits of deploying
services as containers 398 Drawbacks of deploying services
as containers 399




12.4

Deploying the FTGO application with Kubernetes 399
Overview of Kubernetes 399 Deploying the Restaurant service
on Kubernetes 402 Deploying the API gateway 405
Zero-downtime deployments 406 Using a service mesh
to separate deployment from release 407







CONTENTS

12.5

xv

Deploying services using the Serverless deployment
pattern 415
Overview of serverless deployment with AWS Lambda 416
Developing a lambda function 417 Invoking lambda
functions 417 Benefits of using lambda functions 418
Drawbacks of using lambda functions 419




12.6

Deploying a RESTful service using AWS Lambda
and AWS Gateway 419
The design of the AWS Lambda version of Restaurant Service
Packaging the service as ZIP file 424 Deploying lambda
functions using the Serverless framework 425

419



13

Refactoring to microservices 428
13.1

Overview of refactoring to microservices 429
Why refactor a monolith?

13.2

429



Strangling the monolith 430

Strategies for refactoring a monolith to
microservices 433
Implement new features as services 434 Separate presentation
tier from the backend 436 Extract business capabilities into
services 437




13.3

Designing how the service and the monolith
collaborate 443
Designing the integration glue 444 Maintaining data
consistency across a service and a monolith 449 Handling
authentication and authorization 453




13.4

Implementing a new feature as a service: handling
misdelivered orders 455
The design of Delayed Delivery Service 456 Designing the
integration glue for Delayed Delivery Service 457


13.5

Breaking apart the monolith: extracting delivery
management 459
Overview of existing delivery management functionality 460
Overview of Delivery Service 462 Designing the Delivery Service
domain model 463 The design of the Delivery Service integration
glue 465 Changing the FTGO monolith to interact with Delivery
Service 467






index

473



preface
One of my favorite quotes is
The future is already here—it’s just not very evenly distributed.

—William Gibson, science fiction author
The essence of that quote is that new ideas and technology take a while to diffuse
through a community and become widely adopted. A good example of the slow diffusion of ideas is the story of how I discovered microservices. It began in 2006, when,
after being inspired by a talk given by an AWS evangelist, I started down a path that
ultimately led to my creating the original Cloud Foundry. (The only thing in common
with today’s Cloud Foundry is the name.) Cloud Foundry was a Platform-as-a-Service
(PaaS) for automating the deployment of Java applications on EC2. Like every other
enterprise Java application that I’d built, my Cloud Foundry had a monolith architecture consisting of a single Java Web Application Archive (WAR) file.
Bundling a diverse and complex set of functions such as provisioning, configuration, monitoring, and management into a monolith created both development and
operations challenges. You couldn’t, for example, change the UI without testing and
redeploying the entire application. And because the monitoring and management
component relied on a Complex Event Processing (CEP) engine which maintained
in-memory state we couldn’t run multiple instances of the application! That’s embarrassing to admit, but all I can say is that I am a software developer, and, “let he who is
without sin cast the first stone.”

xvii


xviii

PREFACE

Clearly, the application had quickly outgrown its monolith architecture, but what was
the alternative? The answer had been out in the software community for some time at
companies such as eBay and Amazon. Amazon had, for example, started to migrate away
from the monolith around 2002 (https://plus.google.com/110981030061712822816/
posts/AaygmbzVeRq). The new architecture replaced the monolith with a collection
of loosely coupled services. Services are owned by what Amazon calls two-pizza teams—
teams small enough to be fed by two pizzas.
Amazon had adopted this architecture to accelerate the rate of software development so that the company could innovate faster and compete more effectively. The
results are impressive: Amazon reportedly deploys changes into production every 11.6
seconds!
In early 2010, after I’d moved on to other projects, the future of software architecture finally caught up with me. That’s when I read the book The Art of Scalability:
Scalable Web Architecture, Processes, and Organizations for the Modern Enterprise (AddisonWesley Professional, 2009) by Michael T. Fisher and Martin L. Abbott. A key idea in
that book is the scale cube, which, as described in chapter 2, is a three-dimensional
model for scaling an application. The Y-axis scaling defined by the scale cube functionally decomposes an application into services. In hindsight, this was quite obvious,
but for me at the time, it was an a-ha moment! I could have solved the challenges I was
facing two years earlier by architecting Cloud Foundry as a set of services!
In April 2012, I gave my first talk on this architectural approach, called “Decomposing Applications of Deployability and Scalability” (www.slideshare.net/chris.e
.richardson/decomposing-applications-for-scalability-and-deployability-april-2012). At
the time, there wasn’t a generally accepted term for this kind of architecture. I sometimes called it modular, polyglot architecture, because the services could be written in
different languages.
But in another example of how the future is unevenly distributed, the term microservice was used at a software architecture workshop in 2011 to describe this kind of
architecture (https://en.wikipedia.org/wiki/Microservices). I first encountered the
term when I heard Fred George give a talk at Oredev 2013, and I liked it!
In January 2014, I created the https://microservices.io website to document architecture and design patterns that I had encountered. Then in March 2014, James Lewis
and Martin Fowler published a blog post about microservices (https://martinfowler
.com/articles/microservices.html). By popularizing the term microservices, the blog
post caused the software community to consolidate around the concept.
The idea of small, loosely coupled teams, rapidly and reliably developing and delivering microservices is slowly diffusing through the software community. But it’s likely
that this vision of the future is quite different from your daily reality. Today, businesscritical enterprise applications are typically large monoliths developed by large teams.
Software releases occur infrequently and are often painful for everyone involved. IT
often struggles to keep up with the needs of the business. You’re wondering how on
earth you can adopt the microservice architecture.


PREFACE

xix

The goal of this book is to answer that question. It will give you a good understanding of the microservice architecture, its benefits and drawbacks, and when to use it.
The book describes how to solve the numerous design challenges you’ll face, including how to manage distributed data. It also covers how to refactor a monolithic application to a microservice architecture. But this book is not a microservices manifesto.
Instead, it’s organized around a collection of patterns. A pattern is a reusable solution
to a problem that occurs in a particular context. The beauty of a pattern is that
besides describing the benefits of the solution, it also describes the drawbacks and the
issues you must address in order to successfully implement a solution. In my experience, this kind of objectivity when thinking about solutions leads to much better decision making. I hope you’ll enjoy reading this book and that it teaches you how to
successfully develop microservices.


acknowledgments
Although writing is a solitary activity, it takes a large number of people to turn rough
drafts into a finished book.
First, I want to thank Erin Twohey and Michael Stevens from Manning for their
persistent encouragement to write another book. I would also like to thank my development editors, Cynthia Kane and Marina Michaels. Cynthia Kane got me started and
worked with me on the first few chapters. Marina Michaels took over from Cynthia
and worked with me to the end. I’ll be forever grateful for Marina’s meticulous and
constructive critiques of my chapters. And I want to thank the rest of the Manning
team who’s been involved in getting this book published.
I’d like to thank my technical development editor, Christian Mennerich, my technical proofreader, Andy Miles, and all my external reviewers: Andy Kirsch, Antonio
Pessolano, Areg Melik-Adamyan, Cage Slagel, Carlos Curotto, Dror Helper, Eros
Pedrini, Hugo Cruz, Irina Romanenko, Jesse Rosalia, Joe Justesen, John Guthrie,
Keerthi Shetty, Michele Mauro, Paul Grebenc, Pethuru Raj, Potito Coluccelli, Shobha
Iyer, Simeon Leyzerzon, Srihari Sridharan, Tim Moore, Tony Sweets, Trent Whiteley,
Wes Shaddix, William E. Wheeler, and Zoltan Hamori.
I also want to thank everyone who purchased the MEAP and provided feedback in
the forum or to me directly.
I want to thank the organizers and attendees of all of the conferences and meetups
at which I’ve spoken for the chance to present and revise my ideas. And I want to
thank my consulting and training clients around the world for giving me the opportunity to help them put my ideas into practice.

xx


ACKNOWLEDGMENTS

xxi

I want to thank my colleagues Andrew, Valentin, Artem, and Stanislav at Eventuate,
Inc., for their contributions to the Eventuate product and open source projects.
Finally, I’d like to thank my wife, Laura, and my children, Ellie, Thomas, and Janet
for their support and understanding over the last 18 months. While I’ve been glued to
my laptop, I’ve missed out on going to Ellie’s soccer games, watching Thomas learning to fly on his flight simulator, and trying new restaurants with Janet.
Thank you all!


about this book
The goal of this book is to teach you how to successfully develop applications using
the microservice architecture.
Not only does it discuss the benefits of the microservice architecture, it also
describes the drawbacks. You’ll learn when you should consider using the monolithic
architecture and when it makes sense to use microservices.

Who should read this book
The focus of this book is on architecture and development. It’s meant for anyone
responsible for developing and delivering software, such as developers, architects,
CTOs, or VPs of engineering.
The book focuses on explaining the microservice architecture patterns and other
concepts. My goal is for you to find this material accessible, regardless of the technology stack you use. You only need to be familiar with the basics of enterprise application architecture and design. In particular, you need to understand concepts like
three-tier architecture, web application design, relational databases, interprocess communication using messaging and REST, and the basics of application security. The
code examples, though, use Java and the Spring framework. In order to get the most
out of them, you should be familiar with the Spring framework.

xxii


ABOUT THIS BOOK

xxiii

Roadmap
This book consists of 13 chapters:
























Chapter 1 describes the symptoms of monolithic hell, which occurs when a
monolithic application outgrows its architecture, and advises on how to escape
by adopting the microservice architecture. It also provides an overview of the
microservice architecture pattern language, which is the organizing theme for
most of the book.
Chapter 2 explains why software architecture is important and describes the
patterns you can use to decompose an application into a collection of services.
It also explains how to overcome the various obstacles you typically encounter
along the way.
Chapter 3 describes the different patterns for robust, interprocess communication in a microservice architecture. It explains why asynchronous, messagebased communication is often the best choice.
Chapter 4 explains how to maintain data consistency across services by using
the Saga pattern. A saga is a sequence of local transactions coordinated using
asynchronous messaging.
Chapter 5 describes how to design the business logic for a service using the
domain-driven design (DDD) Aggregate and Domain event patterns.
Chapter 6 builds on chapter 5 and explains how to develop business logic using
the Event sourcing pattern, an event-centric way to structure the business logic
and persist domain objects.
Chapter 7 describes how to implement queries that retrieve data scattered
across multiple services by using either the API composition pattern or the
Command query responsibility segregation (CQRS) pattern.
Chapter 8 covers the external API patterns for handling requests from a diverse
collection of external clients, such as mobile applications, browser-based JavaScript applications, and third-party applications.
Chapter 9 is the first of two chapters on automated testing techniques for microservices. It introduces important testing concepts such as the test pyramid, which
describes the relative proportions of each type of test in your test suite. It also
shows how to write unit tests, which form the base of the testing pyramid.
Chapter 10 builds on chapter 9 and describes how to write other types of tests in
the test pyramid, including integration tests, consumer contract tests, and component tests.
Chapter 11 covers various aspects of developing production-ready services,
including security, the Externalized configuration pattern, and the service
observability patterns. The service observability patterns include Log aggregation, Application metrics, and Distributed tracing.
Chapter 12 describes the various deployment patterns that you can use to
deploy services, including virtual machines, containers, and serverless. It also


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×