Principles Of Microservices
“Small *Autonomous* services that work together, modelled around a business domain“ (deployed independently)
-
More choices than a monolith
-
Heroku - http://12factor.net
- Codebase - One codebase tracked in revision control, many deploys
- Dependencies - Explicitly declare and isolate dependencies
- Config - Store config in the environment
- Backing Services - Treat backing services as attached resources
- Build, release, run - Strictly separate build and run stages
- Processes - Execute the app as one or more stateless processes
- Port binding - Export services via port binding
- Concurrency - Scale out via the process model
- Disposability - Maximize robustness with fast startup and graceful shutdown
- Dev/prod parity - Keep development, staging, and production as similar as possible
- Logs - Treat logs as event streams
- Admin processes - Run admin/management tasks as one-off processes
Principles
- Modelled around business domain
- Achieve stability of API
- Easy to be reused
- Culture of automation
- Manage the emergent complexity
- Hide implementation details
- Allow services to evolve independently
- Decentralise all the things
- Also in architectural decision making
- Deploy independently
- Consumer first
- Invert our thinking
- Isolate failure
- Make sure your system is resilient
- Highly observable
- Old monitoring patterns won’t stack up in a distributed systems environment
1. Business domain
- Business domain boundaries are more stable
2. Automation
- Infrastructure automation
- Can I provision machines on demand?
- Automating testing
- Continuous Delivery
- Get software out quickly and know it’s production ready
3. Hide implementation details
- Database coupling between services makes change hard
- Integrate with API calls or events
- Hide your database!
4. Decentralisation of power
- What is autonomy?
- Giving people as much freedom as possible to do the job at hand
- Self service - provision machines and test environments?
- Governance
- Push decision making into teams
- Architecture
- Dumb pipes, smart endpoints
- Use MoM but keep it dumb
5. Deploy independently
- Deploy only the service
- Having to change more than one service to deploy is a problem
- “Lock-step released” are bad
- Eventually, you should adopt a 1:1 Host/Container to Service ratio
- Multiple services per host are hard to verify
- Consumer-driven contracts
- Meet expectations with tests to verify contracts
- Run upstream expectation tests during the build of downstream services
- End-to-end integration tests can be costly and brittle
- Upgrade APIs with co-existing endpoints used for communication
- Give consumers time to migrate over
- Similar to the expand/contract pattern
- Put the power in the hands of the consumer
- Understand the cost of change of APIs
- APIs within a single team are much easier to change
6. Consumer first
- Documentation
- Tooling, like Swagger or HAL
- Service discovery
- Martin Fowler: HumaneRegistry
- A simple wiki page to show information from our services
- Pull in information from other sources
7. Isolate Failure
- Distributed systems are not more resilient or reliable
- Systems are likely to become more unreliable, than reliable
- Resiliency does not come for free
- Strangler Pattern
- Redirect requests from old code to to new code
- Allows incrementally improving services
- Beware of downstream applications failing slowly, tying up resources
- Slow components add latency - timeouts too high?
- Bulkheading downstream connections
- Circuit breaker design pattern
- Protect you from continuous failure
- Fast failure is better
- Automatic and manual?
- Manual switch to help deploys
8. Highly observable
- Not just humans looking at graphs
- Collect information and aggregate
- Log aggregation - get them off the box!
- Stats - centralise them and open them up
- Graphite
- Promethius
- Correlations