Please enable JavaScript.
Coggle requires JavaScript to display documents.
Sam Newman Building Microservices O'Reilly Media 2015 (Integration…
Sam Newman
Building Microservices
O'Reilly Media 2015
Architecture
How small is 'small'?
Something that can be rewritten in two weeks
Small enough and no smaller
If something not feels too big
Features
General
Primarily modeled around business domains
Finely grained services with own lifecycles
Key benefits
Autonomous
You can deploy microservice without changing its consumers
API should be technology-agnostic
Can be deployed as an isolated service - PAAS
Technology Heterogeneity
Quick check of new technologies
Different storage for different services/needs
Resilience
Can degrade functionality, but not failed completely
Scaling
Independent scaling of bottlenecks
Ease of Deployment
Changes can be deployed separately with lower impact and can be easily rolled beck if needed
Organizational Alignment
Smaller teams
Smaller codebases
Can shift service ownership between teams
Composability
Each service introduce different seam
Each service can be consumed by different consumers
Optimizing for Replacability
Cost of replace is small
Shared Libraries
Modules
Downsides
Increased complexity
Hard to determine borders between services
Architect responsibilities
Vision
Empathy
Collaboration
Adaptability
Autonomy
Goverance
Whats makes good service?
Loose Coupling
Change in one service shouldn't require change in another
Service should know as less as it needs
High Cohesion
Related behaviour should sit together
Splitting the Monolith
Split by bounded contexts
Bounded context
Avoid Premature Decomposition
Detect Modules & Services
Detect Shared & Hidden Models
Take into consideration pace of change
Think about teams structure
Think about security
Think about technologies
Tangled dependency: the Database
Do not afraid to broke foreign keys
Typically concerns around performance are now raised. I have a fairly easy answer to those: how fast does your system need to be? And how fast is it now? If you can test its current performance and know what good performance looks like, then you should feel confident in making a change. Sometimes making one thing slower in exchange for other things is the right thing to do, especially if slower is still perfectly acceptable.
It leads to introducing other systems to maintain relationship and address possibility of showing lost data
Static data, used by different boundries
Duplicate it
Deploy it as file with static data to service or maybe just as enumeration
If it big and complex enough: build a service around it
Shared mutable data
Look for lost Domain concepts here. Shared mutable data often means that in fact those concepts implicitly modeled in the database
Split schema first and only then split monolith to microservices
Transnational boundaries
Use queue and retry where it makes sense
Consider making compensation transaction if you have to reject first transaction when second failed
Distributed transactions
Is that transaction really needed? Can we refactor system to gain eventual consistency?
Reporting subsystem (vital)
Consider have different reporting database with periodic sync
Retrieve data via Service calls if it is appropriate, maybe use middle service like FTP to stream large amounts of data
Consider using
Data Pumps
: push data to reporting system instead of pull it
It may be something as simple as console app triggered by Cron
Consider
Event Data Pump
Services should expose state change events
Integration
Choose integration technology carefully
Avoid breaking changes
Keep your API technology-agnostic
Make your services simple for consumers
Hide internal implementation details
Avoid shared databases (avoid database integration at all costs)
Prefer Context Capability over Data (Avoid CRUD)
Different approaches
Synchronous vs Asynchronous
Request/Response
Simplier
RPC
Leads to technology coupling
Local calls are not like remote calls
Brittle
Event-based
We say that something has happened
We expect that other parties knows what to do
Technology choices
Message brokers (RabbitMQ and so on)
Need to consider: message hospital / dead letter queue - where messages got sent if they failed
ATOM
Increased complexity
Orchestration vs Choreography
Orchestration leads to small number of 'god' services telling the anemic CRUD services what to do
Extremely brittle
High change cost
Choreography leads to position in which explicit busyness process become only implicitly reflected in our system
Services should be smart enough
Additional work is needed to ensure that you can monitor and track that the right things have happened
REST & HTTP
Well-defined and well-understood, good for work with each other
HATEOAS - Hypermedia As The Engine Of Application State
Piece of content contains links to various other pieces of content in variety of formats
Decouples client and server
Downsides
Not all frameworks work well with all HTTP verbs
There can be performance issues. HTTP has a lot of overhead.
JSON, XML, or something else?
Stick with JSON or XML
Consider reactive extensions (Rx)
Do not violate DRY within microservice, but be relaxed about violating DRY across all services
Client Libraries
Can bring more coupling, which leads to upgrading all client libs on every server upgrade
Need to keep chance to release our services independently
Clients have to be in charge of when to upgrade their client libraries
Reference to object in memory
Sometimes resource send to service should be re-read from service, so we loose reference
Consider sending URI of resource rather than resource itself
Sometimes we need to know previous state of an object
Sharing code between client and server can be very dangerous
3rd Party Software
Lack of control
May be hard to customize
Better hide them behind facades
Versioning
Defer It for as long as possible
Postel's law
Catch breaking changes early
Use consumer-driven contracts
Use semantic versioning (SemVer)
May be applied to service
May be applied to individual endpoint
Concurrent versions
Co-exists different end-point within one service
Hard to version entities (namespace do little help)
Use version numbers in requests or use different URI (ex. /v2/customer/)
Run multiple concurrent service versions
Use it if cost of changing older consumers is too high
Useful for short migrations (few hours), useful for blue/green deployments and canary releases
User Interface
Constraints
Different view sizes
Mobile interface
Desktop clients
API composition
Different services provides different data for UI
Could be chatty
API gateway can help
Brittle. One change could make several different teams to make changes
UI Fragment Composition
Different services provides part of UI itself
Could end up in making changes faster
Same team who maintains one service do all things from service to UI considering that service
Not applicable for thick clients and native applications
Backends for Frontends
Monolithic API gateway could cause problems
Better is to create different API gateways for different Frontends
Should only contain behavior specific to delivering a particular user experience
Deployment
Different services have to have different repositories, build pipelines, different CI/CD strategies
Compile->UT->Integr.T->UAT/E2E->Perform.T->Production
Consider automation using Chef, Puppet, Ansible and alike
Keep service configuration data separate
Service-to-Host mapping
Multiple services per host
Can lead to cumbersome monitoring, hard to calculate CPU usage for single service for example
Different services could ask contradictory dependencies
Inhibit autonomy of teams
Can limit our deployment artifact options
Application containers
Constrains technology choices
Consider Nancy for .NET
Single service per host
PaaS (such as Azure)
Docker
Automation
is essential
Strategies
Blue/green deployment
Smoke-tests at this stage
Canary releasing
Testing
Pyramid
Service tests (scope of OS process)
We need to stub out all downstream services
Consumer-driven tests
Stub all collaborators
Just check single consumer
Affect on pyramid
End-to-End tests
Call from calling system to far end
Single set of E2E tests to entire microservices set
Can be flaky and brittle
Flaky tests have to be fixed ASAP
Do not allow other (test-team) team to write such tests - you should write them by yourself
Teams have to share such tests but with joint ownership
Unit tests
Trade-offs
How many tests?
Avoid inverted pyramid
Performance tests
Do it not long after starts developing
Start with tests that check core journeys
Monitoring
We need to understand what is 'healthy'?
How many memory is consumed?
What the CPU load is?
Response time from service (bare minimum)
What to check
Error rate
Response time
You need business metrics for application
Synthetic transactions
Requests have to have CorrelationIDs
Log messages (formats) should be standardized
Security
Authorization & Authentication
Authentication: is the process by which we confirm that a party is who she says she is -
principal
Authorization: is the mechanism by which we map from principal to the action we are allowing her to do