
Microservices are all the rage these days and while I am not sure that they are apt for every product – especially during the early stages – they ARE popular and for good reason.
The Service Oriented Architecture (aka. microservices) have become popular because they enable us to split a monolithic code base into decoupled services, each managed and working independently from another. The parts of the application that need to be scaled can be scaled on their own. And teams can take ownership of specific services.
While I read this book a few months ago, and I was able to appreciate and immediately apply its what now seems like straight-forward principles. I have worked on microservices at TransferWise, and currently at Maple Inside with great success.
Here are some of Sam Newman’s key concepts that were the most important to me:
- Microservices should be as small as possible, but not smaller
- It’s very hard to create distributed ACID transactions. 2 Phase Commit is probably one of the better ways to do it if you really wanted to, but it is best to avoid it all together.
- Microservices are hard
“Microservices should be as small as possible, but no smaller.”
Microservices should be as small as possible, keyword “as possible”. While at first it might be hard to find where the boundaries lie, it’s often possible to split the code base into components with a very limited ranges of responsibility (Netflix has over 900 microservices).
For instance, an eCommerce company might use an email service with a simple interface that takes in a from, to, and a body. The same company might also have an order service that reads and edits orders based on userId. To retrieve an order, you might first have to query your user service for the user (using the user email) and then use that user’s id to make a second request to the order service. Although it will add latency to your app, it shouldn’t add that much time to answer the request with proper database indexes and if your services on the same local area network.
Some services however cannot be split. Or with so much difficulty that it is simply not worth it. Those services are best kept attached together, because they are already as small “as possible”. Read the next section to understand when that might be the case.
“It’s very hard to create distributed ACID transactions. 2 Phase Commit is probably one of the better ways to do it if you really wanted to, but it’s often best to avoid it all together.”
It’s incredibly hard to revert a transaction across multiple services if it fails for whatever reason. I believe the consensus is that it is better to use 2 phase commit if you want to go down the route of having transactions, but 2 phase commits algorithms don’t guarantee ACID transactions, they only increase the likelihood of them succeeding. The way 2 PC works is that it simply checks that every service that needs to be involved in the transaction is able to do the transaction before doing it, thus reducing the risks of a transaction failing.
The best approach is however to not split up parts of your application that require ACID transactions over several areas of responsibility.
“Microservices are hard”
Microservices add complexity: communicating between microservices, deciding which standards to use, understanding where the boundaries lie, making the system resilient, debugging distributed errors, deploying microservices, monitoring, logging, every thing is harder.
In monolith first, Martin Fowler makes the case that is might be preferable for some projects to start off as a monolith. Especially until the project has been confirmed to be useful. The main advantage is the time saved between iterations, and also because their is no need at that point to split a huge monolith up into a SOA. It also gives the team the time to learn more about the domain problem, and gain the domain knowledge that will help them create more stable boundaries between areas of responsibility.
“Other”
The book talks in some detail about problems common to all microservices: logging, monitoring, analytics. Because the application is split up, so are logs, errors, and databases. And as logging, monitoring and analytics are vitally important to production systems, a good deal of thought has to go into how to centralize logs split across multiple services, monitoring multiple services and merging the contents of SQL and NoSQL databases for analytics.
The book also read about the “SOA bus”, which is sort of similar to the CPU bus in the sense that it’s an efficient way to make your parts talk together. At Maple Inside, for instance, we are using Google PubSub and an event driven architecture (EDA) so that services can publish events for other services, and while other services are able to subscribe to specific events. An example might be a user service who publishes a “User Created” event that the email service (and others) might be subscribed to, so that it can send out a welcome email.
All in all it’s one of the best books currently out there about microservices. It took me about 20 hours to read, and I highly recommend anyone new to the topic to read it.