The micro-service architecture, which structures an application as a set of small, narrowly focused, independently deployable services, is becoming an increasingly popular way to build applications. This approach avoids many of the problems of a monolithic architecture. It simplifies deployment and letâs you create highly scalable and available applications. In this talk we describe the micro-service architecture and how to use it to build complex applications. You will learn how techniques such as Command Query Responsibility Segregation (CQRS) and Event Sourcing address the key challenges of developing applications with this architecture. We will also cover some of the various frameworks such as NodeJS and Spring Boot that you can use to implement micro-services.
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
Â
Developing applications with a microservice architecture (svcc)
1. Microservices: Decomposing
@crichardson
Applications for
Deployability and Scalability
Chris Richardson
Author of POJOs in Action
Founder of the original CloudFoundry.com
@crichardson
chris@chrisrichardson.net
http://plainoldobjects.com
2. Presentation goal
How decomposing applications into
@crichardson
microservices
improves deployability and scalability
and
simplifies the adoption of new
technologies
4. @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, ...
5. @crichardson
Agenda
The (sometimes evil) monolith
Decomposing applications into services
Client â service interaction design
Decentralized data management
7. @crichardson
Traditional application
architecture
StoreFrontUI
Product Info
Service
Recommendation
Service
Tomcat
Browser/
Client
WAR/EAR
MySQL
Database
Review Service
Simple to
develop
test
deploy
Load
balancer
scale
Spring MVC
Spring
Hibernate
Order Service
HTML
REST/JSON
10. @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
12. @crichardson
Obstacle to scaling
development
I want
to update the UI
But
the backend is not working
yet!
Lots of coordination and
communication required
14. @crichardson
Agenda
The (sometimes evil) monolith
Decomposing applications into services
Client â service interaction design
Decentralized data management
16. @crichardson
The scale cube
X axis
- horizontal duplication
Z axis - data partitioning
Y axis -
functional
decomposition
similar
splitting by things
Scale Scale by
splitting
different things
17. @crichardson
Y-axis scaling - application level
WAR
Storefront UI
Product Info
Service
Recommendation
Service
Review
Service
Order
Service
18. @crichardson
Y-axis scaling - application level
Storefront UI
Product Info
Service
Recommendation
Service
Review
Service
Order
Service
19. @crichardson
Y-axis scaling - application level
Product Info
Service
Product Info
Recommendation
Service
Review
Service
Order
Service
Browse Products
UI
Checkout UI
Order management
UI
Account
management UI
Apply X-axis and Z-axis scaling
to each service independently
20. Service deployment options
@crichardson
Isolation, manageability
VM or Physical Machine
Docker/Linux container
JVM
JAR/WAR/OSGI bundle/...
Density/efficiency
21. @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
22. @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
24. @crichardson
More service, less micro
But more realistically...
Focus on building services that make
development and deployment easier
- not just tiny services
25. @crichardson
Real world examples
http://techblog.netflix.com/
~600 services
http://highscalability.com/amazon-architecture
100-150 services to build a page
http://www.addsimplicity.com/downloads/
eBaySDForum2006-11-29.pdf
http://queue.acm.org/detail.cfm?id=1394128
27. @crichardson
Smaller, simpler apps
Easier to understand and develop
Less jar/classpath hell - who needs OSGI?
Faster to build and deploy
Reduced startup time - important for GAE
31. @crichardson
Two levels of architecture
System-level
Services
Inter-service glue: interfaces and communication mechanisms
Slow changing
Service-level
Internal architecture of each service
Each service could use a different technology stack
Pick the best tool for the job
Rapidly evolving
37. @crichardson
Complexity of testing a
distributed system
http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html
38. Complexity of deploying and
operating a distributed
@crichardson
system
http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html
You need a lot of automation
40. @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
41. @crichardson
Agenda
The (sometimes evil) monolith
Decomposing applications into services
Client â service interaction design
Decentralized data management
42. Letâs imagine that you want to
display a productâs details...
Product
Info Reviews
Recommendations
@crichardson
43. Directly connecting the front-end to the backend
@crichardson
View Controller
Model
Product Info
service
Recommendation
Service
Review
service
REST
REST
Thrift
Traditional server-side
web application
View Controller
Model
Browser/Native App
Chatty API
Web unfriendly
protocols
44. @crichardson
Use an API gateway
View Controller
Model
Product Info
service
Recommendation
Service
Review
service
REST
REST
Thrift
API
Gateway
View Controller
Model
Browser/Native App
Single entry point
Client
specific APIs
Protocol
translation
Traditional server-side
web application
45. @crichardson
Optimized client-specific
APIs
Web
application
Mobile
App
NodeJS
API
Gateway
REST
proxy
Event
publishing
Product Info
service
Recommendation
Service
Review
service
REST
REST
Thrift
getProductInfo()
getRecomm...()
getReviews()
getProductDetails()
46. @crichardson
Netflix API Gateway
http://techblog.netflix.com/2013/01/optimizing-netflix-api.html
Device specific
end points
47. @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
49. How does a browser
interact with the partitioned
@crichardson
web application?
50. @crichardson
Partitioned web app â no
longer a single base URL
/products
Browse Products
UI
/checkout
Checkout UI
/orders
Order management
UI
/account
Account
management UI
Browser ?
51. The solution: single entry point
that routes based on URL
@crichardson
/products
Browse Products
UI
/checkout
Checkout UI
/orders
Order management
UI
/account
Account
management UI
http://acme.com/<service>/...
Content
Browser Router
Hidden from
browser
Single entry
point
53. Inter-service communication
options
@crichardson
Synchronous HTTP â asynchronous AMQP
Formats: JSON, XML, Protocol Buffers, Thrift, ...
Asynchronous is preferred
JSON is fashionable but binary format
is more efficient
54. Pros and cons of messaging
Pros
Cons
Decouples client from
Additional complexity of
server
message broker
Message broker buffers
Request/reply-style
messages
communication is more
Supports a variety of
complex
communication patterns
55. Pros and cons of HTTP
Pros
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)
56. @crichardson
Discovery option #1:
Internal load balancer
Load
Balancer
Product Info
Service
Product Info
Service
Product Info
Service
Product Info
Service
Client/
API gateway
Services register
with load balancer
Client talks to
load balancer
Has a well-known
location
http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/USVPC_creating_basic_lb.html
57. @crichardson
Discovery option #2:
client-side load balancing
REST
Client
Product Info
Service
Product Info
Service
Product Info
Service
Product Info
Service
Client
Service
Registry
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
58. @crichardson
Lots of moving parts!
PProrodducutc tIn Ifnofo
Service
Recommendation
Service
Review
Service
Order
Service
Browse Products UI
Checkout UI
Order management
UI
Account
management UI
API
Gate
way
Service registry
Content
Router
HTML
Browser
REST
Client
Ext.
LB
Ext.
LB
59. @crichardson
Agenda
The (sometimes evil) monolith
Decomposing applications into services
Client â service interaction design
Decentralized data management
60. @crichardson
Decomposed services â
decomposed databases
Order management Customer management
Order
Database
Customer
Database
Separate databases â less coupling
62. Untangling orders and customers
Customer management
@crichardson
Order Service
placeOrder()
Order management
Customer Service
availableCredit()
updateCustomer()
Customer
creditLimit
...
Order belongs to has orders
total
Invariant:
sum(order.total) <= creditLimit
available credit= creditLimit -
Trouble! sum(order.total)
63. @crichardson
Problems
Reads
Service A needs to read data owned by service B
e.g. OrderService needs customerâs credit limit
e.g Customer Service needs outstanding order total
Updates
âBusiness transactionâ must update data owned by
multiple services
e.g Creating a User => Create their ShoppingCart
64. You could use two-phase
commit (2PC) but ...
@crichardson
66. UpdateCreditLimitCommand
@crichardson
Event-driven architecture
Customer Service
updateCustomer()
CustomerCreditLimitUpdatedEvent
Message Broker
Order management
Order
total
Customerâ
creditLimit
CustomerCreditLimitUpdatedEvent(...)
Customer management
Customer
creditLimit
...
67. Benefits and drawbacks of
an event-driven architecture
Benefits:
Simple infrastructure, e.g. a message broker
Better availability (than using 2PC)
Drawbacks:
Application has to handle eventually consistent data
Application has to handle duplicate events
@crichardson
69. @crichardson
To maintain consistency the
application must
atomically publish an event
whenever
a domain object changes
70. @crichardson
How to generate events
reliably?
Database triggers
Hibernate event listener
Ad hoc event publishing code mixed into business logic
Domain events - âformalâ modeling of events
Event Sourcing
71. Atomically publishing events
Use distributed transactions to update database and publish
to message
Database and message broker must support 2PC
2PC is best avoided
Use eventual consistency mechanism:
1. Update database: new entity state & event to publish
2. Publish event & mark event as published
âą Difficult to implement when using a NoSQL database :-(
@crichardson
72. @crichardson
Event sourcing
An event-centric approach to designing domain models
Request becomes a command that is sent to an Aggregate
Aggregates handle commands by generating events
Apply events to an aggregate to update state
Persist events NOT state
Replay events to recreate the current state of an aggregate
Event Store â database + message broker
73. Request handling in an event-sourced application
@crichardson
HTTP
Handler
Event
Store
pastEvents = findEvents(entityId)
Account
new()
applyEvents(pastEvents)
newEvents = processCmd(SomeCmd)
saveEvents(newEvents)
Microservice A
74. @crichardson
Event Store publishes events -
consumed by other services
Event
Store
Microservice B
Event
Subscriber
subscribe(EventTypes)
publish(event)
publish(event)
Aggregate
NoSQL
materialized
view
update()
update()
75. UpdateCreditLimitCommand
@crichardson
Using event sourcing
Customer Service
updateCustomer()
CustomerCreditLimitUpdatedEvent
Event Store
Order management
Order
total
Customerâ
creditLimit
CustomerCreditLimitUpdatedEvent(...)
Customer management
Customer
creditLimit
...
76. @crichardson
Customer aggregate
case class Customer(customerId: String, creditLimit: BigDecimal)
extends ValidatingAggregate[Customer, CustomerCommands.CustomerCommand] {
def this() = this(null, null)
override def processCommand = {
case CreateCustomerCommand(customerId, creditLimit) =>
Seq(CustomerCreatedEvent(customerId, creditLimit))
case UpdateCreditLimitCommand(newLimit) if newLimit >= 0 =>
Seq(CustomerCreditLimitUpdatedEvent(newLimit))
}
override def applyEvent = {
case CustomerCreatedEvent(customerId, creditLimit) =>
copy(customerId=customerId, creditLimit=creditLimit)
case CustomerCreditLimitUpdatedEvent(newLimit) =>
copy(creditLimit=newLimit)
}
}
Command
â
Events
Event
â
Updated
state
77. @crichardson
EventStore API
trait 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(...) : ...
..
}
78. Unfamiliar but it solves many
problems
@crichardson
Eliminates O/R mapping problem
Supports both SQL and NoSQL databases
Publishes events reliably
Reliable eventual consistency framework
...
81. @crichardson
Apply the scale cube
Modular, polyglot, and
scalable applications
Services developed,
deployed and scaled
independently
82. Use a modular, polyglot architecture
View Controller Product Info
@crichardson
Model
service
Recommendation
Service
Review
service
REST
REST
AMQP
API
Gateway
Server-side web
application
View Controller
Model
Browser/Native
application