We had the opportunity to talk to Richard about microservices from a practical perspective. His latest book, "Tao of Microservices", covers this subject with many use cases in this area. You can meet Richard at The Developers conference, on the 19th of April, Cluj-Napoca where he will attend as speaker with a presentation, "The Algebra of Microservices": The microservice architecture has become an established and powerful way to structure large scale systems, providing a component model that scales both at the human and system levels. It is by nature an architecture that has lots of small parts. And it's easy to make a big mess with lots of little parts. That's why we need an algebra—a set of rules for combining microservices together to build big systems. How is this different from design patterns? Design patterns are Babylonian mathematics (where we get our 360 degree circles from!), powerful, but ultimately just a list of problems with sample solutions. What you really need is a set of axioms to solve any problem. That's an algebra!
Richard Rodger - @rjrodger / richardrodger.com - author of The Tao of Microservices
How would you define a microservice?
Richard Roger> This is a dangerous question! I have yet to come across a useful answer. By useful, I mean something that software developers can use to make decisions about how to write code and build systems. You can write a small Python script that exposes a HTTP endpoint, wrap it in a Docker container, and deploy it using Kubernetes, and you will certainly have a "microservice" in your system. However, if you write twenty microservices like that, you will have a mess! This is the most common anti-pattern that I see in many organizations - lots of little web servers all talking to each other and no-one knows what is going on.
It is more useful to ask for the essential characteristics of the microservice architecture. These are: flexible message routing and transport independence. Flexible message routing means that each service has no knowledge of other services, and interacts with the rest of the system only with messages that it receives and messages that it sends. The microservice does not concern itself with where those messages come from and where they are sent to. This, far more than infrastructural features, such as independent deployability with containers, is what gives you the powerful decoupling that is one of the key benefits of microservices. Transport independence means that your services should not know how messages are sent. You should write a message abstraction layer to hide that detail. This means you can send messages using point-to-point HTTP, over intelligent proxies (nginx is good!), or via message buses (like Kafka), or even via custom protocols such as Google's gRPC. The message abstraction layer also makes it easy to test and develop services locally, as you can mock up the rest of the system without needing to run lots of services locally.
With these characteristics, a microservice is anything that plays by these rules. Many of them will be small units of code. Others might be parts of a legacy migration, or just naturally big—these are sometimes called "macroservices". So long as you maintain the flexibility to easily handle and route messages, you have a microservice architecture.
From a practice perspective, how do you see network usage overload with messaging requests/responses between microservices? What available alternatives are there?
Richard Roger> This is a classic objection to microservices, and all the more effective for being true! There is no question that the microservice architecture introduces additional latency into your system. That is just physics. But you have to step back and ask the question: "What are you trying to achieve at the business level? What is the purpose of your code?" When you are writing new code, you do not have all the answers, most of the times. Business requirements keep changing, because the business people do not have all the answers. Most of the software is not designed, it evolves. Moreover, it survives if it makes money, regardless of the quality of the code.
Unfortunately, we as software developers try to build perfect software from the start, and we bake in many data model and structural assumptions. If our code survives, it ends up with high levels of technical debt, and is very costly to maintain. So let us trade some latency for lower technical debt!
The microservice architecture is extremely flexible, by design. It allows you to adapt to changing requirements and bad specifications. The tradeoff is a slower system. However, that is not as bad as it sounds, because it is often the case that only 20% of the system takes 80% of the traffic. You do not need high performance in many places, and it is a waste to put effort into a globally performant system. Instead, once you have solved the business problems and the system actually does need to scale, then you can look at merging those microservices that are on the critical path into single processes to avoid network overhead.
In your latest book, "The TAO of Microservice", you mentioned that components do not offer reusability due to their connections with other components and the reuse of business logic is rarely achieved. Considering this, how a microservices approach will force developers to create reusable components ?
Richard Roger> In my book, I argue that many attempts at designing component architectures have failed, because they do not provide sufficient composability. You need to be able to flexibly combine functional elements in multiple ways. Mainstream object-oriented platforms have fundamentally failed to do this. I offer the mere existence of object-oriented "design patterns" as conclusive evidence - why are they necessary? Surely the basic features of objects (inheritance, encapsulation, polymorphism, etc) should be sufficient! However, they are not, as the mountains of unmaintainable spaghetti code that we see every day shows.
Contrast object-oriented code bases a component model that does work: the Unix command line. It works, because you have just about the simplest interface possible - a stream of bytes. That is all you can take in, and all you can send out. Therefore, all Unix commands are compatible with each other, and that is the key to making a component architecture work. We can use message the same way we use microservices, but only if we take a very easy-going approach. We have no schemas, we ignore messages we do not understand, and we use simplistic pattern matching on the message contents to route them to the right microservices.
You can then compose microservices together. Your shopping cart microservice does not need to know that the messages it sends and receives are passing through validation, auditing and scaling services as well. It does not need to know that it is not the only shopping cart, which you have an entirely separate cart for the US market, because there are so many different tax rules that trying to create a general solution and set of data structures is too hard. Therefore, you just write another service with a simpler code base.
People fixate a little on the "reusable" aspect of software architectures, but this is actually a consequence of effective composability.
It was very interesting to read the second chapter where you tackled the case study of a digital newspaper edition, especially from our newspaper perspective. Did you ever build such a model in production and could you give us some production details?
Richard Roger> Yes! It comes directly from my personal experiences building a platform for a national newsletter in Ireland in 2011 and 2012. We launched a new website, as well as mobile and tablet apps in just three months. We used many of the techniques in the book, but also made many mistakes. The system I describe in the book is the system I should have built - it solves many of the mistakes we made in production!
That system was built using JavaScript as the core language for everything, from the mobile apps (PhoneGap, as it was then) all the way to the database (Mongo), with Node.js in the middle. We thought that using a single language would bring about significant efficiency, but it was not as effective as we thought. We still created a lot of complex APIs that were not composable.
One of the most powerful things we did learn was that if you do use composable message-based APIs (we built these by accident using Redis pub-sub), you get a lot of flexibility and can develop much more quickly.
Richard Roger> Do you think we will see a microservice concept evolution? What do you think is missing right now?
I think that people are far too focused on choosing implementation platforms, that they are trying to create rules, and that they are not spending enough time understanding where the real power lies. Building large software systems is about taming complexity. You do get some benefits with containers, and internal REST APIs, but you also end up with the same problem complexity as before if you are not careful. You should always ask the question: "How does this reduce complexity?" Think about Roman numerals versus decimal notation. The same human brain can handle a lot more complexity (e.g. long division) using decimals. Our software platforms should give us the same benefits. Composable components are a first step on that path.
Tell us about the product you just launched: Voxgig.com.
Richard Roger> I am building a new Software-as-a-Service platform using microservices from day one! It is a search engine and community for conference speakers and organizers — helping everybody find the best events and talks. Some people say that you should start with a monolith and only later move to microservices, because the cost of building a deployment system is too high in the early days. This is nonsense with modern tools like Kubernetes, Terraform, Chef, or all the other systems tools we have now. Saying that you should start with a monolith fundamentally fails to understand that the purpose of microservices is to make it easier to develop more functionality faster!
Richard Rodger is the author of The Tao of Microservices, a new book from Manning focused on the design and management of microservice architectures. Richard is the host of the Dublin Microservices Meetup, and the maintainer of the open source senecajs.org microservice framework. His first book Mobile Application Development in the Cloud (Wiley, 2010) is one of the first major works on the intersection of Node.js, Cloud, and Mobile.
Richard Rodger is curator of the Metsitaba Newsletter for tech conference speakers. He is the founder and CEO of voxgig.com, a professional network and tool suite for speakers and event organizers. Built using microservices, of course! Richard was previously a co-founder and COO of nearForm.com, the world's largest specialist Node.js consultancy delivering next-generation enterprise software, with a focus on Node.js and microservices. Before that, Richard was the CTO of FeedHenry, a mobile application platform provider that was acquired by RedHat in 2014.
Richard holds degrees in Mathematics, Philosophy, and Computer Science.