Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

81
@crichardson Microservices: Decomposing Applications for Deployability and Scalability Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson [email protected] http://plainoldobjects.com

description

Today, there are several trends that are forcing application architectures to evolve. Users expect a rich, interactive and dynamic user experience on a wide variety of clients including mobile devices. Applications must be highly scalable, highly available and run on cloud environments. Organizations often want to frequently roll out updates, even multiple times a day. Consequently, it's no longer adequate to develop simple, monolithic web applications that serve up HTML to desktop browsers.In this talk we describe the limitations of a monolithic architecture. You will learn how to use the scale cube to decompose your application into a set of narrowly focused, independently deployable services. We will also discuss how an event-based approach addresses the key challenges of developing applications with this architecture.

Transcript of Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

Page 1: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Microservices: Decomposing Applications for

Deployability and Scalability

Chris Richardson

Author of POJOs in ActionFounder of the original CloudFoundry.com

@[email protected] http://plainoldobjects.com

Page 2: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Presentation goalHow decomposing applications

improves deployability and scalability

and simplifies the adoption of new

technologies

Page 3: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

About Chris

Page 4: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

About Chris

Founder of a buzzword compliant (stealthy, social, mobile, big data, machine learning, ...) startup

Consultant helping organizations improve how they architect and deploy applications using cloud computing, micro services, polyglot applications, NoSQL, ...

Page 5: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Agenda

The (sometimes evil) monolith

Decomposing applications into services

Client ⇔ service interaction design

Decentralized data management

Page 6: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Let’s imagine you are building an online store

Page 7: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Tomcat

Traditional application architecture

Browser/Client

WAR/EAR

MySQL Database

Review Service

Product InfoService

Recommendation Service

StoreFrontUI

developtest

deploy

Simple to

Load balancer

scale

Spring MVC

SpringHibernate

Order Service

HTMLREST/JSON

Page 8: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

But large, complex, monolithic applications

⇒ problems

Page 9: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Intimidates developers

Page 10: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Obstacle to frequent deployments

Need to redeploy everything to change one component

Interrupts long running background (e.g. Quartz) jobs

Increases risk of failure

Fear of change

Updates will happen less often - really long QA cycles

e.g. Makes A/B testing UI really difficult

Eggs in one basket

Page 11: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Overloads your IDE and container

Slows down development

Page 12: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Lots of coordination and communication required

Obstacle to scaling development

I want to update the UI

But the backend is not working

yet!

Page 13: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Requires long-term commitment to a technology stack

Page 14: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Agenda

The (sometimes evil) monolith

Decomposing applications into services

Client ⇔ service interaction design

Decentralized data management

Page 15: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Page 16: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

The scale cube

X axis - horizontal duplication

Z axis

- data

partit

ioning

Y axis - functional

decomposition

Scale b

y split

ting s

imilar

thing

s

Scale by splitting

different things

Page 17: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Y-axis scaling - application level

WAR

Storefront UI

Product InfoService

RecommendationService

ReviewService

OrderService

Page 18: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Y-axis scaling - application level

Storefront UI

Product InfoService

RecommendationService

ReviewService

OrderService

Page 19: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Product Info

Y-axis scaling - application level

Product InfoService

RecommendationService

ReviewService

OrderService

Browse Products UI

Checkout UI

Order management UI

Account management UI

Apply X-axis and Z-axis scaling to each service independently

Page 20: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Service deployment options

VM or Physical Machine

Docker/Linux container

JVM

JAR/WAR/OSGI bundle/...

Isolation, manageability

Density/efficiency

Page 21: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Partitioning strategies...

Partition by noun, e.g. product info service

Partition by verb, e.g. Checkout UI

Single Responsibility Principle

Unix utilities - do one focussed thing well

Page 22: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Partitioning strategies

Too few

Drawbacks of the monolithic architecture

Too many - a.k.a. Nano-service anti-pattern

Runtime overhead

Potential risk of excessive network hops

Potentially difficult to understand system

Something of an art

Page 23: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Example micro-service using Spring Boot

For more on micro-services see http://microservices.io

Page 24: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

But more realistically...

Focus on building cohesive services that make development and deployment easier

- not just tiny services

Page 25: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Real world examples

http://highscalability.com/amazon-architecture

http://techblog.netflix.com/

http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf

http://queue.acm.org/detail.cfm?id=1394128

~600 services

100-150 services to build a page

Page 26: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

There are drawbacks

Page 27: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Complexity of developing and managing a distributed

system

Using a PaaS can significantly simplify deployment

http://contino.co.uk/blog/2013/03/31/microservices-no-free-lunch.html

Page 28: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Multiple databases &

Transaction management

Page 29: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Deploying features that span multiple services requires

careful coordination

Page 30: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

When to use it?In the beginning: •You don’t need it •It will slow you down

Later on:•You need it•Refactoring is painful

Page 31: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

But there are many benefits

Page 32: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Smaller, simpler apps

Easier to understand and develop

Reduced startup time - important for GAE

Less jar/classpath hell - who needs OSGI?

Page 33: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Scales development: develop, deploy and scale each service independently

Page 34: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Improves fault isolation

Page 35: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Eliminates long-term commitment to a single technology stack

Modular, polyglot, multi-framework applications

Page 36: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Two levels of architectureSystem-level

ServicesInter-service glue: interfaces and communication mechanisms

Slow changing

Service-level

Internal architecture of each serviceEach service could use a different technology stack

Pick the best tool for the jobRapidly evolving

Page 37: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Easily try other technologies

... and fail safely

Page 38: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Agenda

The (sometimes evil) monolith

Decomposing applications into services

Client ⇔ service interaction design

Decentralized data management

Page 39: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

How do clients of the system interact with the services?

Page 40: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Directly connecting the front-end to the backend

Model

View ControllerProduct Info

service

RecommendationService

Reviewservice

REST

REST

AMQP

Model

View Controller

Browser/Native App

Traditional server-sideweb application

Chatty API

Web unfriendly protocols

Page 41: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Use an API gateway

Model

View ControllerProduct Info

service

RecommendationService

Reviewservice

REST

REST

AMQP

APIGateway

Model

View Controller

Browser/Native App

Single entry point

Client specific APIs

Protocol translation

Traditional server-sideweb application

Page 42: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Optimized client-specific APIs

Web application

MobileApp

NodeJS

APIGateway

RESTproxy

Event publishing

Product Infoservice

RecommendationService

Reviewservice

REST

REST

AMQP

getProductInfo()getRecomm...()getReviews()

getProductDetails()

Page 43: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Netflix API Gateway

http://techblog.netflix.com/2013/01/optimizing-netflix-api.html

Device specific end points

Page 44: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

API gateway design challenges

Performance and scalability

Non-blocking I/O

Asynchronous, concurrent code

Handling partial failures

....

http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html

Page 45: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

How does a browser interact with the partitioned

web application?

Page 46: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Partitioned web app ⇒ no longer a single base URL

Browse Products UI

Checkout UI

Order management UI

Account management UI

/products

/checkout

/orders

/account

Browser ?

Page 47: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

The solution: single entry point that routes based on URL

Browse Products UI

Checkout UI

Order management UI

Account management UI

/products

/checkout

/orders

/account

ContentRouterBrowser

http://acme.com/<service>/...

Hidden from browser

Single entry point

Page 48: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

How do the services communicate?

Page 49: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Inter-service communication options

Synchronous HTTP ⇔ asynchronous AMQP

Formats: JSON, XML, Protocol Buffers, Thrift, ...

Asynchronous is preferredJSON is fashionable but binary format

is more efficient

Page 50: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

Pros and cons of messagingPros

Decouples client from server

Message broker buffers messages

Supports a variety of communication patterns

Cons

Additional complexity of message broker

Request/reply-style communication is more complex

Page 51: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

Pros and cons of HTTPPros

Simple and familiar

Request/reply is easy

Firewall friendly

No intermediate broker

Cons

Only supports request/reply

Server must be available

Client needs to discover URL(s) of server(s)

Page 52: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Discovery option #1: Internal load balancer

LoadBalancer

Product InfoService

Product InfoService

Product InfoService

Product InfoService

Client/API gateway

Services register with load balancer

Client talks to load balancer

Client talks to

Has a well-known location

http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/USVPC_creating_basic_lb.html

Page 53: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Discovery option #2: client-side load balancing

RESTClient

Product InfoService

Product InfoService

Product InfoService

Product InfoService

Client

ServiceRegistry

Services register with registry

Client polls registry

http://techblog.netflix.com/2013/01/announcing-ribbon-tying-netflix-mid.html

http://techblog.netflix.com/2012/09/eureka.html

Page 54: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Lots of moving parts!Product InfoProduct InfoService

RecommendationService

ReviewService

OrderService

Browse Products UI

Checkout UI

Order management UI

Account management UI

APIGateway

Service registry

ContentRouter

HTMLBrowser

RESTClient

Ext.LB

Ext.LB

Page 55: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Agenda

The (sometimes evil) monolith

Decomposing applications into services

Client ⇔ service interaction design

Decentralized data management

Page 56: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Decomposed services ⇒ decomposed databases

Order management Customer management

OrderDatabase

CustomerDatabase

Separate databases ⇒ less coupling

Page 57: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Decomposed databases ⇒ polyglot persistence

IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg

Page 58: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Customer management

Untangling orders and customers

Order management

Order Service

placeOrder()

Customer Service

availableCredit()updateCustomer()

Customer

creditLimit...

has ordersbelongs toOrder

total

Invariant:sum(order.total) <= creditLimit

available credit= creditLimit - sum(order.total)Trouble!

Page 59: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Problems

Reads

Service A needs to read data owned by service B

Updates

Transaction must update data owned by multiple services

Page 60: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Handling reads: requesting credit limit

Order management

placeOrder()

Customer management

getCreditLimit()

Page 61: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Pulling data

Benefits

Simple to implement

Ensures data is fresh

Drawbacks

Reduces availability

Increases response time

Page 62: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Customer management

Handling reads: replicating the credit limit

Order management

Order Service

placeOrder()

Customer

creditLimit...

Order

total

Customer’

creditLimit

changeCreditLimit()

sum(order.total) <= creditLimit

Customer Service

updateCustomer()

Simplified

Page 63: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Useful idea: Bounded context

Different services have a different view of a domain object, e.g.

User Management = complex view of user

Rest of application: User = PK + ACL + Name

Different services can have a different domain model

Page 64: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Replicating data

Benefits

Improved availability for reads

Improves latency

Drawbacks

Additional complexity of replication mechanism

Page 65: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

How to handle updates (including of replicated

data)?

Page 66: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Use distributed transactions

Benefits

Guarantees consistency

Drawbacks

Complex

Reduced availability

Page 67: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Use eventual consistencyHow

Services publish events when data changes

Subscribing services update their data

Benefits:

Simpler

Better availability

Drawbacks:

Application has to handle inconsistencies

Page 68: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

How do services publish events?

Page 69: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

To maintain consistency the application must

atomically publish an event whenever

a domain object changes

Page 70: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Change tracking options

Database triggers

Hibernate event listener

Ad hoc event publishing code mixed into business logic

Domain events - “formal” modeling of events

Event Sourcing

Page 71: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Event sourcingAn event-centric approach to designing domain models

Aggregates handle commands by generating events

Apply events update aggregate state

Persist events NOT state

Replay events to recreate the current state of an aggregate

Event Store ≃ database + message broker

Page 72: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

EventStore APItrait EventStore {

def save[T](entityId: Id, events: Seq[Event]): T

def update[T](entityId: Id, version: EntityVersion, events: Seq[Event]): T

def load[T](entityType: Class[T], entityId: EntityId): T

def subscribe(...) : ... ..}

Page 73: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Using event sourcing

Event Store

CustomerCreditLimitUpdatedEvent

Order management

Order

total

Customer’

creditLimit

CustomerCreditLimitUpdatedEvent(...)

Customer management

Customer

creditLimit...

Customer Service

updateCustomer()

UpdateCreditLimitCommand

Page 74: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Customer aggregatecase class Customer(customerId: String, creditLimit: BigDecimal) extends ValidatingAggregate[Customer, CustomerCommands.CustomerCommand] {

def this() = this(null, null)

override def validate = { case CreateCustomerCommand(customerId, creditLimit) =>

Seq(CustomerCreatedEvent(customerId, creditLimit))

case UpdateCreditLimitCommand(newLimit) if newLimit >= 0 => Seq(CustomerCreditLimitUpdatedEvent(newLimit))

}

override def apply = {

case CustomerCreatedEvent(customerId, creditLimit) => copy(customerId=customerId, creditLimit=creditLimit)

case CustomerCreditLimitUpdatedEvent(newLimit) => copy(creditLimit=newLimit)

}}

Command ⇒

Events

Event ⇒

Updated state

Page 75: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Unfamiliar but it solves many problems

Eliminates O/R mapping problem

Supports both SQL and NoSQL databases

Publishes events reliably

Reliable eventual consistency framework

...

Page 76: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Summary

Page 77: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Monolithic applications are simple to develop and deploy

BUT have significant drawbacks

Page 78: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Apply the scale cube

Modular, polyglot, and scalable applications

Services developed, deployed and scaled independently

Page 79: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Use a modular, polyglot architecture

Model

View Controller Product Infoservice

RecommendationService

Reviewservice

REST

REST

AMQP

APIGateway

Model

View Controller

Server-side web application

Browser/Native application

Page 80: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Start refactoring your monolith

Monolith ServiceAnti-corruption layer

Glue code

Pristine

Page 81: Microservices: Decomposing Applications for Deployability and Scalability (jax jax2014)

@crichardson

Questions?

@crichardson [email protected]

http://plainoldobjects.com