Last week I was asked by a client to talk about microservices, discuss their characteristics and highlight what the implications were on the organization, the way existing applications could be transformed with microservices, where that transformation made sense and several other topics in the area. Over the coming weeks, I’ll take some time to describe parts of these discussions in multiple blog entries. Today let’s start with an important topic.
But before doing that, let’s define what we call a microservices architecture. I found two definitions in some of Martin Fowler’s posts:
· The first one describes Microservices Architecture as a style of architecture that promotes business alignment by developing applications as set of small independent and self-contained services that directly caters to an atomic business activity.
· The second one, Microservices is a software architecture style in which complex applications are composed of small, independent processes communicating with each other using language-agnostic APIs.
Both are actually quite complementary. The first deals mainly with the development of services to support business activities within a business process. It goes well with the move to a more digital economy where parts of business processes are automated. It shows the link between microservices, SOA and object orientations. I do know some of you may not like me highlighting this link and would argue about the differences. They are obviously right, the three concepts are not identical, but they are part of the same approach, the splitting of monolithic applications in a series of independent “modules” that each support a single business activity. The second definition is more technical. It speaks of APIs and language independence. So, each “module” should be self-contained, using the best technology to perform the job at hand, and be able to communicate with others regardless of which technologies they use.
Microservices should be self-contained. In other words, they should not depend on other microservices to execute. A microservice waiting for another one to finish a job, is heresy. This means that if a transaction has to take place it is either completely embedded in one microservice, or an external “choreographer” handles the transaction by invoking multiple microservices one after each other and taking care of the transfer of data. The first may result in very large microservices, which may end up being impractical, the second implies a use of a business process management system or something equivalent.
There might be another approach consisting in rethinking the concept of a transaction. We are used to think about a transaction as a set of consecutive steps that are tightly linked and executed in a well-defined order. Information about this transaction is up to date in the appropriate data structure, so you know exactly what is happening. Is that the only way things could work? I believe not and let me explain you how different approaches can be taken by using a simple analogy.
Let’s go and have a coffee.
When you go to a bar to drink a coffee, the first thing you’ll have to do is to place an order. In many American bars you will open the tab by handing over your credit card. Your transaction is started. Your session ID is your table number. You enjoy the moment and drink your coffee. Maybe you order a second one after a while, the tab increases. Once you have drank enough coffee for the day, you go to the cashier and close the transaction. You pay and recover your credit card.
This works exactly like a typical transaction. Each step takes some time. A session ID ensures all steps are properly tracked to the same transaction. The cost goes up at each step and you know exactly where you are at each moment. Pretty standard.
Let’s go to Starbucks.
A couple weeks ago I ran into an article from Gregor Hohpe, titled “Starbucks does not use two-phase commit”. And it daunted on me. Let me explain.
When you go to Starbucks and order a coffee, your experience is very different from what I just described above. You first go to a cashier and order a coffee. You pay and receive a receipt. The cashier then takes a cup, writes your name and your order. This is the first microservice.
The cashier will put your cup in a queue writing your name and order on it.
In a totally asynchronous manner, the barrister will pick up cups, make orders and put the full cup in another queue on the other side of the machine. In case of heavy demand, a second barrister picks up cups in the same queue and uses a second machine. This is another microservice, with load balancer and duplication in case of heavy demand.
A third person will take the full cups, read the name loudly and hand you over your order. Third microservice.
I’ve never been in a situation where there was a problem, but I assume that in case your order cannot be made, there is a procedure for the cashier to reimburse you. He would start from your receipt to inverse the transaction.
What’s the difference?
In the regular bar, the transaction takes the duration of your consumption and a session ID is maintained in the system. The transaction is state-full and managed as a whole. This allows an external observer to know exactly where you are in the transaction at any time.
At Starbucks, the transaction is divided in three independent microservices that execute regardless of the others. Once they have executed their part of the job, they forget about you. One piece of data, your name, links them back together.
The cashier has information on this transaction in the register, the barrister executes and then forgets about your order all together as does the person that dispatches the orders. The only way you know the transaction has been fulfilled is because you do not find a reimbursement transaction in the register.
The transaction has been fundamentally redesigned to enable the decoupling of the steps and to make the steps stateless (A stateless app is an application program that does not record data generated in one session– such as information about user settings and events that occurred — for use in the next session with that user). The question for you is whether you can do this with the transactions you are executing today.
Microservices facilitate re-use but forces to rethink applications are written and transactions are executed. I do hope you considered my analogy useful and it helped you understand what is ahead of you if you want to transform your business to use microservices. Feel free to react, share your experience and describe how you tackled the challenges.
This blog entry was originally published on the CloudSource blog. I am referring to it new material and republish it here as the original blog has been dismantled.