Mariusz Richtscheid: Masz już dosyć swojego monolitu? Rozważasz rozbicie go na mikroserwisy? Nie tak prędko. Zanim zaczniesz zmieniać architekturę, warto dowiedzieć się jakie problemy się z tym wiążą. Na szczęście większość bolączek można rozwiązać stosując odpowiednie wzorce i techniki, których część zostanie omówiona w trakcie prezentacji.
2. About me
• Full-Stack Developer in The Software House
• richtscheid@gmail.com
• linkedin.com/in/richtscheid
• github.com/barograf
Mariusz Richtscheid
3. Agenda
• Why microservices?
• Communication patterns
• Data management patterns
• Reliability and observability patterns
• Testing
4. Monolith
• Can be difficult to understand and modify
• Development and deployments slow down over time
• Modularity breaks down over time
• Quality of the code declines over time
• It is hard to change technology stack
5. Why microservices?
• Smaller services are easier to understand and test
• Services can be deployed more frequently
• Development in multiple teams
• Improved fault isolation
• Every service can have different technology stack
6. A lot of issues to address
How to decompose into services?
How to deploy?
How to handle configs, logging,
tracing, health checks, metrics?
How to communicate between services?
How do external clients
communicate with the services?
What about service discovery?
How to prevent failures?
How to maintain data consistency?
How to handle security? How to test it?
How to troubleshoot problems?
How to display data from multiple
services?
10. API Gateway
• One entry point for the entire system
• Handles security - other services communicate freely
• Knows how to call other services - statically defined or with service
discovery
• Should not contain business logic
11. API Gateway - message format
export interface ISocketMessage {
serviceName: string;
serviceOperation: string;
payload: object;
}
30. Saga
• A service which coordinates sequence of local transactions across
multiple microservices
• Each local transaction updates the database
• If local transaction fails then the saga executes a rollback for all related
microservices
31. Rollback in saga
Service 1
Operation 1
Operation 2
Operation 3
Saga
Service 2
Service 3
Service 4
❌
✅
✅
Service 4Rollback✅ Error
Data changed
Data changed
35. Circuit breaker
• Mechanism for fast fail of requests towards unhealthy services
• Prevents unnecessary traffic and cascading fails
• Unhealthy services can recover safely
38. Distributed tracing
• Logging is not enough in distributed system
• Tracing gives insight into code execution across services
• With tracing we know what, where and when something fails
40. • Standard for distributed tracing
• Defines interfaces and data model for many programming languages
• Has no real implementation
41. • OpenTracing compatible implementation for distributed tracing
• Released as open source by Uber Technologies
• Available in Node, Go, Java, Python and C++
• Provides useful UI
47. Creating new span
const span = tracer.startSpan('name of the span');
span.addTags({ type: 'foo' });
/*
some code
*/
span.finish();
48. Sending tracing ID
import { FORMAT_HTTP_HEADERS } from 'opentracing';
const headers = {};
tracer.inject(span, FORMAT_HTTP_HEADERS, headers);
const tracingId = JSON.stringify(headers);
/*
send tracing ID to other service (with headers, as string value etc.)
*/
49. Receiving tracing ID
/*
receive tracing ID from other service
*/
const tracingIdString = '{"uber-trace-id":"d7ee8bcc3f4a1033:d7ee8bcc3f4a1033:0:1"}';
const spanFromOtherService = tracer.extract(
FORMAT_HTTP_HEADERS,
JSON.parse(tracingIdString)
);
const span = tracer.startSpan('name of the span', { childOf: spanFromOtherService });
/*
some code
*/
span.finish();
51. Testing
• Specs are not enough
• Write integration tests for parts of your infrastructure
• Run your infrastructure with one command
• Can be achieved with Docker Compose or PM2 ecosystem
• Different definitions for different parts of infrastructure