If I have to name a single biggest hype in software architecture land then it would be "microservice". They are supposed to be small and focused, can be deployed independently, can work with any technology and will solve all your monolithical problems. But we all know that silver bullets don't exist, plus technology should never be a goal, but merely a means to an end. Nonetheless, following the path towards real microservices is a great strategy for decomposing a monolith without the deployment complexity of the first. So how do you do that? What technologies does the .NET realm offer for us? In this talk, I'll show you some of the pros and cons of micro-services and its ingredients to leverage modern-day .NET and Event Sourcing to move your monolith into a bright new future.
5. Hybrid of
Technologies
Multiple patterns
for the same problems
Long compile
time
Large source control
repositories
Long-running
unit tests
Too much
coupling
Limited
team scalability
Devs need to
know everything
NoIsolation.Productivity
drops over time.
Proof of success!
6.
7. Application
Functional Module Functional Module Functional Module Functional Module
Composition
Each module
owns/exposes its
master data
Does not
depend on
anything
except for
curated
shared APIs
Owns
schema and
storage
(may use
shared
database
abstraction)
DRY within
module, not
outside
May use an
internal
container
Does not
touch other
module’s
data directly
Shared Services
Connects the
modules and
serves as anti-
corruption layer
Only services you
really think should
not be duplicated
Designed according to
Dependency Inversion Principle
Covers
front-end
and back-
end
is the scope
of unit &
integration
tests
Align folder
structure
with
boundaries
Defines the
contracts
for the host
as well as
any services
it exposes
Aligned with
Bounded
Context.
12. Very scalable, very
reliable
Very difficult to
debug distributed
problems
Unreliable network
requires resiliency
techniques
Requires message
bus/broker/
gateway
End-to-end testing
very unpractical
Very mature
DevOps culture is a
prerequisite
Advanced monitoring
and visualization is a
must
High operational
maintenance
Can be deployed/upgraded
independently
Explosion of
network activity.
15. Monolith
Functional Module
Functional Module
Functional Module
HTTP API
HTTP API
HTTP API
Released as NuGet packageNo network I/O at all
Own database instance, / shared with
monolith / or shared storage service
Owns the schema
Separate repos with
distinct owners
Runs in-process, thus
easier debugging
New version
requires
redeployment of
the monolith.
Loose coupling through
HTTP
Less scalability
options
HTTP is not the
fastest serialization
format
Designed for minimum
dependencies
19. Monolith
Functional Module
HTTP API
Module Registry
Contract documented
through OpenAPI
Webhook
Functional Module
Functional Module
Provides HTTP
abstraction to connect to
module
Event payload exposed as
OpenAPI
Subscribers register
HTTP abstraction
Consumers use liberal
JSON interpretation
Subcribers can request
resending history.
Payload includes unique
ID to help idempotency
Each request requires correlation
ID that flows through all APIs,
webhooks and module
20.
21. Dennis Doomen | @ddoomen | The Continuous Improver
Application
Domain
NoSQL / RDBMS
OR/M / DAL
Web UI, HTTP API,
etc
Lucene Index
Document Projector
Web UI, HTTP
API, etc
Web UI, HTTP API, etc
Domain
Commands
Events
Event StoreProjections
Projectors
Uses Event
Sourcing
Uses
traditional
CRUD
architecture
Indexing-based
architecture
Subcribe
to webhooks
Coarse-
grained
HTTP
requests.
Bus
Subscribe
Publish coarse-
grained event
22.
23. Domain is persistency
ignorant
For modules that provide
a (partial) UI or
management screen
Aggregates
Command
Handlers
Commands
Events
Upconverters
Value Objects
Query
Handlers
Schema
Migrations
Projectors
Data
Importers
Query API
Projections
HTML
CSS JS
API
Controllers
Projectors
Projections
Registrations
Webhook API
Command
API
Event
Storage
Domain
Services
Payload
Definitions
Can be tested
independently
Based on Domain Driven
Design
Outer layers depend on
inner layers
Master data
24. Application
Command
Service
Correct
Customer
Email Handler
Customer
Unit of
Work
Projector
Data
Access
Layer
Read
Database Write
Database
CorrectCustomerEmailCommand
HTTP API / In-process invocation
Get<Customer>(identity)
Correct Email
Event Store
Load(events)
Apply
Get changes
CustomerEmailCorrectedEvent
Submit changes
History
Dennis Doomen | @ddoomen | The Continuous Improver
NES
Aggregates.NET
SimpleDomain
NStore
EventStore
NEventStore
SQLStreamStore
NStore
NES
Marten
Handelier
Brighter
MediatR (*)
Projac
LiquidProjections (*)
25. Monolith
Functional Module
HTTP API
Event Store
Events
Payload
Projector
Subscription
Request
Payload
‘event store’
Have their own
checkpoints
Projects fine-grained
events into payload
projections
Projector
Projector
Projector
Webhook Projectors
Separate instance
per subscription
Subscriber
Callback API
‘Project’ payload
‘events’ into HTTP
calls
Projected Data
Uses the incoming
payloads as an
‘event store’.
Payload
SQL DB Schema
changes using code
or using NoSQL
Subscription
Request
26.
27. - Module owns ‘schema’
- Supports upgrading and downgrading
- NoSQL preferred, but RDBMS can
work too.
37. Service Host
Monolith
Functional Module
Functional Module
Functional Module
HTTP API
HTTP API
HTTP API
Apply routing
conventions
Versioning
using Accept Headers,
Response Headers or
Routes
Optimize body using
AVRO or Protobuf
Cross-service tracing
using OpenTracing
Replace HTTP with gRPC
Common contracts for
diagnostics, monitoring
HTTP Proxy
Child process
of monolith (e.g.
LitteForker)
Hides the externalized
state of the module (e.g.
ProxyKit)
38.
39. 1 Build a (container-based) cloud
capability.
2 Deploy monolith to the cloud.
3 Automate your delivery pipeline.
4 Full end-to-end responsibility
5 Evaluate status-quo on micro-services
(products, platforms, etc)
6 Slide-and-dice microservices one-by-
one
7 Break-up delivery teams and code.
41. • Liquid Projections
https://www.liquidprojections.net
• Bliki: MonolithFirst
https://dzone.com/articles/martin-fowler%E2%80%94bliki
• In-process gRPC
https://github.com/grpc/grpc-go/issues/906
• Ingredients for well-designed OWIN components
https://www.continuousimprover.com/search/label/OWIN%20
Recipes
• The good, the bad and the ugly of Event Sourcing
https://www.continuousimprover.com/search/label/event%20s
ourcing
45. Events
Transaction 6
Transaction 5
Transaction 4
Transaction 3
Transaction 2
Transaction 1
Temporal
Projector
Read
Store
Time
Projected until
this point
Immutable, thus
auditable and SOX
compliance
Dennis Doomen | @ddoomen | The Continuous Improver
47. Dennis (v4)
Persisted State Changes
Dennis (v3)
Role Granted
PasswordChangedEvent
Dennis (v4)
Dennis (v3)
User Created
Role Granted
Phone Number Added
Password Changed
Dennis (v5)
Role Revoked
Dennis (v6)
Role Granted
Time
Dennis (v7)
Password Changed
Dennis Doomen | @ddoomen | The Continuous Improver
58. Driven by invariants, not
composition
Only consistent within
aggregate
Small aggregates
Reference by identity
59.
60. • Column constraints (e.g. data truncation)
• Changes in data invariants (null vs non-
null in event versions)
• Unexpected projection dependencies
• Partial replays.
61. • Causing duplicate child records
• Causing large event streams
• Incorrect caching strategy (e.g. on
lookups)
• Identity case-sensitivity
• Incomplete SQL-backed event store
reads.
62. • Side by side rebuilding
• Functional archivability and archiving
• Projection tracking and ETAs
• Prioritization
• Partitioning.
63. • After bugs, schema changes, etc
• Manual or automatic (e.g. hashes)
64.
65. Microservice
Bunch of classes that
should be used directly
X
No inheritance
Uses composition
over inheritance
internally
Convenience classes
that don’t hide the
magic
Library
Abstract Package
Interfaces
Delegates
DTOs
Only depend
on abstract
packages…
Stable Package
…or depend on more
stable packages
Auxiliary
Package
Classes that are not
used together do not
belong togetherOptional
Dependency
Dependency
Package
Consumers should
not be faced with
optional
dependencies
72. • The network is reliable
• Latency is zero
• Bandwidth is infinite
• The network is secure
• Topology doesn't change
• There is one administrator
• Transport cost is zero
• The network is homogeneous.
https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing