Design and Implementation of Microservices by @samnewman (@NDC_Conferences) [ 1 / 4 ]

This June, I had the opportunity to partake in Sam Newman's microservices workshop at NDC in Oslo. The attendees represented 10 different countries, including France, Germany, Iceland and the USA. I learnt a lot; here are my notes and reflections:

Format and facilitator

Sam started out by letting each participant to briefly introduce themselves and tell their fellow participants what they'd like to get out of the class, writing down each topic on a magic whiteboard, so that he could adjust his workshop based on our wishes! He then proceeded to check off each subject as he addressed them. Needless to say, I was impressed how he snipped bits out of 5 other presentations to get us the most value out of our workshop. He was also very honest about subjects where he didn't have enough knowledge in the subject matter, enabling the class to "learn together", i.e. have an open discussion and contribute, sharing knowledge amongst the participants.


What are Microservices?

Martin Fowler argues that the microservice architectural style is an approach to developing a single application as a suite of small services. To the question how small is small, Sam asked the class "Who here has a system that is too big?", arguing that small is the opposite of that. He continued by saying that transaction costs have come down, making writing microservice based systems (or modularized software) both easier and cheaper, transitioning to his definition of microservices as

Small autonomous services that work together, modelled around a business domain.

Just as the XP and Scrum methodologies are implementations of Agile, Sam argued that Microservices is an implementation of SOA; i.e. arguing that Microservices is not about reinventing the wheel, but instead about reflecting on what we've been doing that has been working and distilling that into a reusable strategy. We're lucky to live in a time where people are sharing details about their successes - Netflix [2], Orbitz, REA Group [2], Gilt - which means, that we can learn from other people's mistakes and benefit from their successes, evolving as a group!

Melvin Conway introduced the idea in 1968 that organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations. Therefore, we should align our organization around the service design, wherever possible, ensuring that a team of skilled individuals are responsible for any given service, avoiding "shared services" which have multiple reasons to change. Sounds a bit like the S in the SOLID principles, doesn't it?

We should be able to deploy a new version of a service in production without any orchestration or dependencies. This comes with benefits such as faster time to market, individual scalability, the ability to adopt new technologies more quickly and, importantly, granulated security: How secure are microservices? Many organizations have a security mentality that states that "once you get in", you have access to everything in the organization, arguing that you cannot protect your organization from disgruntled employees and other trustees. However, securing each service individually, rather than relying solely on perimeter security, we have the potential of a more secure system than a system built to a monolith. We also get a reason to discuss - and gain the freedom to decide - which parts of the system that cause damage if compromized (and what kind of damage), rather than adopting the very laborious and futile mentality of trying to "protect everything".

A semi-recent capability that can aid us with this deployment scenario is container technology, such as Docker. If you're a Windows developer, please see the recent announcements from Build -
Windows Containers: What, Why and How and Thinking in Containers: Building a Scalable, Next-Gen Application with Docker on Azure, the latter stating that

Docker has exploded over the last two years as an enabler of micro-service architecture.

Capabilities

We don't know where our software will be used. We might have an idea from the outset that we're creating a web solution, but then there are phones that will want a specialized rendering / set of data if our product or service takes off; there are tablets... What information will we want to display on a small device such as a watch? Will any part of our data be relevant for fitness trackers? What about beacons? Microservices lets us design our system around its core capabilities, rather than design a system that specifically target today's requirements.

Complexities

Although it's easier today than it was just a few years ago, designing a microservices based system is still not easy. For starters, you have more up-front choices to consider. The bottom line, is that it takes time to get to a microservices based system! Therefore, Sam urged us to start small, pointing out that the REA Group extracted their first two services in three months, during which they experienced a lot of pain, mostly around automation. After the first two microservices were in place, they reached fifteen in 9 months, followed by sixty sometimes after 2 years.

I recall similar advice from Udi Dahan in his SOA course, where he stated that startups might as well forget about designing a SOA based system as they are trying to establish their business, since they don't know their business until it's running. You refactor into SOA, you don't create it from the get-go.

You will have to learn a lot as you take on a microservices architectural style (as evident by the two slide shares from REA above): Testing techniques, monitoring techniques and mitigation of cascading failures - the network is not reliable. Without thought, you will end up designing a more fragile system with microservices than you would have with a monolith! To be successful, we need to learn to understand infrastructure, so do get ops onboard.

Service Modelling

Things that change together should stay together
Does a new feature affect several teams and/or services? Does your consumers depend on internal data structures? Are there more than one consumer that is dependent on the same structural representation?

To quote Martin Fowler: "As you try to model a larger domain, it gets progressively harder to build a single unified model. Different groups of people will use subtly different vocabularies in different parts of a large organization. ... So instead DDD divides up a large system into Bounded Contexts, each of which can have a unified model - essentially a way of structuring MultipleCanonicalModels."

Consider the image below: Some things - the Customer and Product in this case - we want to share between the identified two contexts, but some things - Territory in Sales and Ticket in Support - we want to keep separate.

Martin Fowler: Bounded Context

What we have found, said Sam, is that these business boundaries tend to be stable across other company restructurings, meaning that these structures are a sound investment of our time. Analyzing the bounded contexts and identifying sharable and non-sharable information teaches us that we must avoid serializing and exporting internal state without thinking it over first.

What are the capabilities that our software support? What things does it do that gives value to our customers? - Identify the capabilities/things and then group these into things that change together.

At this point, Sam introduced us to a simplified variant of Event Storming. The basic idea of event storming is to identify business events, business commands and then aggregate these into roots. It went something akin to this: "Given an online music shop, model the services: I want to be able to view the inventory of CDs, buy any number of them and then have them shipped to me." We self-organized into groups of five, got a sheet of magic whiteboard, a block of post-it notes and a marker pen and got to it.

After the exercise, the groups reviewed each other's results, discussing our different thoughts after which Sam advised us to spend more than 15 minutes on this exercise when we got back to our respective organizations, revisiting it regularly; as often as bi-weekly!

"Think through the problem first, before thinking about technologies - be aware of (your own) technology fetishes".

Simcity

When compared to physical structures in the world, designed by architects, we realize that we are probably less of an "architect" in our current role and more of a "town planner". In Simcity, you plan and lay out Zones - Commercial Zones, Residential Zones - and design communications - Roads, Rail, Air. There's much more focus on the Zones than the individual buildings.

Growing our music shop

If we were to extract a recommendation service from our music shop, we could easily just create a new service and let it access the same database as before:


However, we must never do this! It's not so much that we want to be able to easily change database provider, it's about not being able to rename a column, adding an index - do basic database maintenance! The rule of thumb is: If I have a service that relies on a data storage, I need to deploy them together. They belong in the same boundary.


Sync vs. Async Collaboration Styles

Stop thinking about the technical implications of synchronicity and start to reason about collaboration styles instead. Does your service naturally collaborate using a request/response pattern, where a consumer would send a request and expect a response back, or is it event based, where there's no direct feedback on actions, but multiple autonomous parts of your system reacts on an event being fired? Request/response (RPC-style) can be both synchronous and asynchronous, ex. using a message driven / actor approach. Ask yourselves - "which collaboration style fits in this context?" Only then, should you start reasoning about whether or not your API should be (a)synchronous. "Start small! Keep it simple!" RPC-style interaction is generally understood and, thus, make code and systems easy to reason about. What are some of the downsides with RPC-style interactions?

  • Change management is hard
    If you want to change a method on your server, you will likely need to change your clients as well (or design for backwards compatibility. It is, regardless, something you have to consider).
  • RPC hides a lot of complexities!
    Is the reason your method suddenly stops working because something is wrong on the server? On the client? Due to network interruptions? Because of changes in serialization, causing your client and server no longer understanding each other?
  • RPC often requires every interacting partner to have a common, shared library which is a hardship to manage. Change management again.
When discussing collaboration styles, it's valuable to remember Postel's law:
Be conservative in what you do, be liberal in what you accept from others

Because of this, you might want to design your interactions so that they accept more than they need today. Udi Dahan talks about "potentially good input" in his SOA class, as to get his students to stop designing APIs that just spews exceptions whenever things are not pristine. Sam recommended his attendees to look at Protobuf or Thrift, which are both aiming to solve serialization challenges between services and their clients, even across different systems and languages.

Continue to part 2...

Comments

Popular posts from this blog

Auto Mapper and Record Types - will they blend?

Unit testing your Azure functions - part 2: Queues and Blobs

Testing WCF services with user credentials and binary endpoints