Well, it’s that time where everyone is talking about Microservice, what they are, how they work, etc, and here I am putting my thoughts out there.

Article Overview

I am going to cover 3 main areas, plus several not very “main” areas.

1. Architecture

I will be talking about Architecture considerations around Microservices and how those considerations fit together to shape our solution.

We will also be looking at some of the patterns to consider more than anything else, but obviously you will need to tweak these patterns and recommendations for your own particular needs.

2. Implementation

I will show you some simple implementations using .Net to give you a better understanding of how things will probably look like.

3. Deployment

This part is where Docker comes to the picture, and we will take a look a the technologies available around DevOps and we will see where we are going as an industry, and how we are going to deal with deployments in a Miroservices environment.

This might be a rather long one, so I recommend go get a cup of coffee (or whatever your poison is), buckle up and let me take you through this journey!

Caveats

1. Maturity level in Software Industry

We as an industry are still on try and error phase, and constantly learning and coming up with new solutions, and sometimes even decide to go back to what we used to do a while ago.

And Microservices approach is no different. Most of the concepts that are used in Microservices, were introduced 10, or maybe 20 years ago, and we thought they didn’t make sense, or didn’t care and now, here we are, looking back at those and saying, “Yeah, that’s actually a good idea!”.

2. People still debating what a “real” Microservices implementation is

I don’t know if anyone has got Microservices 100% right as of today, and that’s fine, but in the path we are in and with this momentum of changes in this area, I believe all of those will have to revisit their implementations in a year or so anyways!

When you talk to people who claim they have built several Microservices, when you get into some details, you would probably easily find some points that are kind of “single point of failure”, which with Microservices implementation should have been eliminated.

Let’s review the typical Microservices definition again:

Small, independent applications, loosely coupled, communicating with each other in an asynchronous manner, and can fail independently, and if one or some fails, the system as a whole still works, though the functionality might be downgraded when there are failures.

Architecture, just like anything else that we have in our industry, is just there to solve a business problem. That’s why it is OK to to get a not perfect Microservices implementation, and if we can solve the business problem, with even a “not perfect” Microservices implementation, in a “good enough” way, then that’s a good Architecture.

3. Docker works on windows, but only in few Windows OS Versions

Good news is, Docker has now native support for Windows Server 2016 and Windows 10. So if you want to use it, you need to use Windows Service 2016 or Windows 10.

Native Windows apps can now be built, shipped and run in containers that work on both Windows Server 2016 and Windows 10, making them more portable, easier to work on and simpler to run. Native Windows apps also have access to the same advanced container management features as Linux-based apps including image scanning, overlay networking, and Secrets management.

Why you should build Microservices?

So the first and the most important reason for it is the most obvious one.

It is cool, and it is this shiny new thing!

Right? I mean we use it a lot to hire talented people to work on the cool new thing, and we also use it as a motivation, for learning, and experiencing cool new stuff for our current developers. So I guess it is a very important reason to consider.

I mean, Netflix uses Microservices, so should we!

But there are also other reasons why we should consider Microservices:

1. Easier to understand Small services

When you have small services, and you are responsible for them, it is easier to understand the boundaries of your services, and it will be easier for you to learn what the service does, as oppose to a monolith, where you will never know where your service ends, and where the other service starts

2. Services are independently deployable

You can deploy services independently. So if you have a feature, that is ready and tested and all, you don’t have to wait for some other components to finish something that is not related to your stuff at all. So you can go live without having to wait for anyone.

3. Easier to adopt to newer technology (retire vs rewrite)

When you have small little Microservices, and if a new technology comes up that is a very good fit for your service purposes, you can easily ditch the service and rewrite it with the new technology, without the need to rewrite the whole system which could cost you a fortune.

The classic case of Monolith applications is that, it is such a hard job to move them forward. That’s why there are still a ton of applications still running in .Net Framework 1.1 in production, and they can’t even move it a bit forward to 2.0, let alone more modern frameworks or technologies.

4. Easier to scale small services

If one or more features in your system are used more than the others, you can just scale up those specific services, and not the whole system or other services that aren’t used as much. This Microservices specification will become more important when you are using Cloud providers like Azure or AWS, where if you scale your whole system up, you are basically wasting money because it is not efficient.

5. No single point of failure

In theory, the services should be completely independent, and all the data and code that they need to execute an operation should be embedded in them, so if some of the services fail, or their database is offline, other services are fully functional.

This is very important, and people seem to overlook this by creating coupling between services because they don’t want to have duplicate data. Some people tend to build “data services”, where each service, if it needs some data that is originated from other services, will access that data through some service interface, which is a essentially what you do in a traditional SOA architecture. Watch out for these anti-patterns!

6. Freedom of technology stack choices

When we build these independent Microservices, we can give decision power to each team and let them decide what technology best fits their needs to deliver the business requirement. i.e. might make sense for one service to use NodeJs and Azure CosmosDb, and the other one should use an Azure table storage.

Though we should be careful, when introducing new technologies, we are adding overhead to our administration and learning, because now our DBA need to know about all the different data store techniques that are used in each service.

7. It is quicker to evolve and release business features

Because we have all these independent services, we are able to evolve each one quicker as independently, because they are smaller and easier to analyze and add features to, without the need to have a big bang release. So hopefully, we will be able to release our business feature more frequently compared to a Monolith.

8. Gives you a path to move away from your legacy code

With the Microservices architecture in mind, when we have a Monolith already, we can start carving off small pieces of functionality and put them into it’s specific dedicated Microservice gradually, without the need to do a big bang rewrite of the whole system.

How you do eat an elephant? One bite at a time.

That’s me trying to add a feature to a Monolith!

The Microservices journey

So let me take you through some steps that will probably happen, when you decide as an organization that, you want to move towards a Microservices architecture:

1. Everyone Reads some articles

First step is, people start reading some articles (Some don’t, cause they know everything or they simply don’t care). More specifically people read the one about Netflix architecture, and you come across Microservices.io website, read just the intoduction and few more pages, and then you are a master!

2. Everyone Reads some books

Reading(mostly just buying though) books will be the second step. Again some people don’t read books, because they know everything or they don’t care, or they have already a “magic” solution in mind, and don’t give a shit about anything anyone else has to say based on their findings in any article or any book!

3. Some meetings to come up with a plan

Now that we are all ready, we start having these meetings to see if we are on the same page about “what a Microservices implementation mean”, and then we come out of the meetings, without anything changed in anyone’s mind!

That means, people who were confused and didn’t know what the hell they are supposed to do, still don’t have a clue, others that had some implementation in mind, still think their “code” will work, and might also “IMAGINE” that all the books and articles agree with their approach (without actually reading the books or articles).

4. Some very high level planning might happen (not really)

At this point we have a high level plan, as high level as: “WEEEE WILL, WEEEEE WILL, BUILD YOU! WEEEE WILL, WEEEEE WILL, BUILD YOU!”. (Sing like with us like Queen!)

5. Some people start coding!

At this point, some people are still confused, and some are excited and also confused, and some people are writing code! I’m not sure what part of the code, for what service, but they are writing something, that everyone will definitely need, and it is a good idea to have that piece of code or piece of service.

Anyways, if you figured out how to stop them, let me know how you did it!

How MOST people are thinking / feeling after this

When we get into some action, and start planning properly (These other guys that I mentioned were coding… still coding by the way!), you will start understanding the service boundaries, and start designing events, and interfaces for the services to communicate.

At this point this is what people are thinking or how they are feeling, in no particular order:

WHAT THE F*CK!

OH MY F*CING GOD! GEEZ!

Ugh! Why are we doing this again?

“BEEEEEEP” (That one was totally censored, sorry, this is a workplace!)

This is gonna be so complex, I can’t even press F5 anymore to run my application

Wasn’t this supposed to be easy?

I don’t think it is going to work!

I bet it used to be less brittle with monolith!

Performance sucks!

I WILL UPDATE MY RESUME TONIGHT!

Yeah, I know. These people in Netflix and Uber and Amazon, talk about how they do things in Microservices way and they make it sound so easy!

The reality is, in a Monolith, all the crap code and complexity is combined in one spot, now with the Microservices, we are basically taking this big ball of crap and distributing it all over the place. So at the first glance, it looks like it is worse, but it is not, it is the same amount of complexity, but just distributed and broken down, now it is more obvious.

Of course, there will be issues which you didn’t have to deal with before, because it was a monolith. Like network calls all over the place, and the bottleneck it creates for you, and you didn’t have such issues before, but overall it is the same can of worms, it is just now open.

Why people feel like that?

Well there are several reasons, but again with no particular order, here are some:

1. Distributed systems are complex

Yeah, they are. Definitely way more complex to design compared to monoliths and people coming from a monolith environment, will face a huge difference, and hence all the “what the f*ck!” that you hear around the office from most of the developer desks.

2. Complexity is all over the place

Before, people used to have this one application, that some parts of it were complex, and now this complexity is all over the system in different services and distributed between multiple services.

3. It is hard to debug and troubleshoot

This one is a big change too. People used to just press F5 and run the whole thing and debug their sh*t, but now when some call happens, one service is called, it sends a message to the “Service Bus”, gets picked up by another “Message Broker”, then does some data updates, and then some other service is notified and does some other stuff, and then posts another message to the “Service Bus” and then … Yeah, things are definitely different now.

4. Multiple Repositories and Multiple Pull Requests

With Monolith, there are very limited number of code repositories, so if you are building a feature, that touches 4 different areas of the system, you used to make all the changes, test it locally and make 1 pull request to merge your changes to the proper code branch. But now, these 4 different areas that you touched, might belong to different services, so you have to make 4 different pull requests for each service, and also make sure the order that they are merged and deployed and etc.

5. Eventual Consistency needs a paradigm shift

With the whole Asynchronous communication between the Microservices and using the Service Bus and Events, you will have to educate almost everyone from end user to the UX designers and managers in the organization, to be familiar with this concept and accept it. Eventual Consistency changes the way the user experience works a lot.

This also means that you need to forget about distributed transactions, and two phase commits, atomic database operations and etc and essentially, just implement workflows that you are able to execute them in reverse order.

What else do we need to deal with?

Obviously there are lots of things going on and it is hard to consider everything, but here are some stuff that people will bring up and we need to deal with, when starting to move our Monolith to a Microservices architecture:

1. What happens to the database?

Yes, this is a big deal (if not the biggest problem to solve, it is definitely one of the complex ones). Do we want to let our database be our single point of failure? Now we have nicely decoupled services, what do we do with our database? If we separate them, them what happens if we need to share some data with some other service? Do we call other services to get the data or do we publish the data and duplicate it in every service that needs to use it?

2. Do we need Distributed transactions or two phase commits?

Distributed transactions and two phase commits is also something to deal with. Do we need them? How to implement them? Do we rely on some technology to give us these sort of feature, or do we build reversible workflows, so that if a workflow that has 2 phase commit failed at some point, it executes the flow in reverse to fix the state of our objects?

3. What’s the Current version of the system?

Now that we deploy each service independently, and each team can release whenever they want, and the version they want, what is the version of our system? What if we deploy 2 different versions of the same service at the same time? Do we need to version our Events and Messages that we publish to “Service Bus”?

Yes, these are some of the questions that we need to deal with in a Microservices environment.

4. How do we handle authentication and authorization?

Should each Mircoservice do security check on all of the incoming calls? Or do we implement a “Trusted Sub System” approach and basically let the calls from other Microservices go through using this “Service to Service Authentication” approach.