Microservices 101

Microservices aren’t new, but the technology to make them feasible at scale is. A microservice channels the Unix philosophy of “do one thing and do it well” into a conceptual unit of a project. By carving the project up into pieces, each one can function independently of the others and are tied together by the main application or front-end.

Microservices have many advantages over more traditional monolithic application development, but aren’t quite right for every solution. They make development easier to test, applications easier to scale, and can be made extremely fault resilient. There are caveats however which can make them easy to misuse in ways which hinder the development process. Specific cases exist where they just don’t make sense.

What a Microservice Is

Image by Arek Socha from Pixabay

It is the embodiment of Object-Oriented Programming at an application and service level. By taking each conceptual unit and splitting it up, one ends up with a more easily testable component which is scalable. An application to book travel could be split up into services to do each given task. There may be a service to search flights, a service to search hotels, a service to connect to the payment processor, and a service to glue everything together seamlessly. When done correctly, if the hotel search goes down, a customer can still book flights.

The figure below breaks this down from an architectural standpoint.

A network request is handled by a primary server (or server farm) and each request is handled transparently from then on out internally. Note: no networking details are included.

A request is received from the internet and is directed through a front-end server (or server farm). Each individual microservice then performs its part as orchestrated by the primary application. The data is processed as necessary by each individual unit and the results are returned to the user transparently by the application. A lot of times, you’ll see these services communicating with each other via a REST API. For our travel example, the flight service may request information about the hotel to check availability dates based on the user’s search in order to more intelligently return flights for a given range.

What a Microservice Isn’t

A microservice isn’t just a failover for a given application or something to glue together many different applications. What makes a microservice a microservice is the cohesiveness of the parts. Each part contributes to the application and should be aware of the other parts without being beholden to them. A server for a given microservice going down doesn’t have to be fatal when each is aware.

Microservices are not a panacea to all scalability issues either. A badly written microservice based application is going to be just as bad, if not worse than a poorly written monolithic application. API security must be considered among other things for internal operations.

What Are the Primary Advantages for Development

Microservices excel from a development perspective. If done right, they can cut the development cycle down for the time to market in some form. By splitting each component out, profitable components can be offered before the full product is complete. For the travel application, once the flight or hotel component and the payment processing is set up, the application can launch in a more limited form. Traditional development cycles may be a little more dangerous for this due to testing constraints.

By making each unit separate, testing is much easier. A bug in one piece of the application doesn’t necessarily affect other units. The data might be wrong, but you don’t have an int passed as a string to break the application. By scoping the application to take standard input and produce standard output, it is much easier to cut down on weird behaviors and bugs from complicated workflows. The division also allows teams to split the units up and a delay in one doesn’t necessarily affect a completely separate component whatsoever.

Since microservices rely on communication with other microservices in the stack, an API has to built from the get-go. The new hotness is to use a REST API for this type of project. Planning and implementing an API forces consideration of the scope and a way to make the microservice interactive. If the application project fails, the individual components can be reused or resold as necessary.

What and Why to Use a REST API

REST stands for REpresentational State Transfer. What makes REST so powerful is that it is stateless and requests are uniform. A given request will return a given bit of data a given way. There is no misunderstanding what can and should happen with a given request. Each request is a completely independent unit as far as the API is concerned. The underlying data may change, but the functionality does not.

Statelessness and Microservices

Uniformity leads to consistency and statelessness leads to better processing of data between many units. Too many cooks in the kitchen don’t matter when each one has a station and a job. We don’t need to worry about data being handed somewhere else and being modified. The data will always be returned in a predictable way (when done correctly obviously). Microservices leverage this to communicate while the primary front-end or application handles the actual state.

We don’t care about user A or user B’s query. We just care what is requested and where it goes. A flight request for a given search will always return the same type of data. A given service does not concern itself with the state of the request, it has a fixed, expected input and applies the output based on whatever rules are required.

Scalability and Microservices

Due to the level of abstraction and the fact that most microservices written nowadays are more or less stateless, they lend themselves to scalability. The statelessness means we don’t care what server is handling the request, just that one is. A microservice can have duplicate units for load-balancing. The units don’t have to be right next to each other in a data center either. They can be deployed wherever is cheap and sane to do so as long as they can communicate easily with one another. This complicates the network setup, but can help with failover.

Technologies like Docker and Kubernetes have made developing and administering these trivial at scale. The complexity of spinning up a virtualized server farm is mitigated with proper containerization. There is obviously a cost for this convenience in performance, but the cost of processing has fallen to the point that it is negligible compared to the cost of development and maintenance. If a microservice’s server goes down or is swamped, another can be spun up quickly and thrown in the ring.

Caveats of Microservices

Image by GormaKuma from Pixabay

Microservices are great for many use cases, but they do have their caveats. The more complicated the workflow and the more microservices involved, the higher the latency of a given request. Stateful microservices can exist, but we won’t even go down that rabbit hole since they are their own special hell. Heavily state dependent applications will typically hurt from a microservice architecture without special considerations and planning.

A microservice based application requires a full stack development team early on. Special consideration must be given to network security and API security. The team needs someone who can help with the load-balancing and traffic shaping for the workflow. There are far more considerations for performance than a monolithic application, and for a lot of them, you can’t just throw more resources at the problem. On top of this, each container is its own OS, so you need someone handling security. You need a lot more than just developers.

Applications employing microservices need more forethought than most monolithic applications. What is the scope of a given piece? If this scope changes, do you change every other service or add a new API version? How do you handle old API versions? How do you handle bug fixes that require an API change and ensure that every reference is fixed? These are all considerations which must be taken into account from day one. If you just wing it, you’re going to drown quickly.

Conclusion

Microservices are powerful, and as long as you take into account the caveats. They can reduce development time and cost to initial launch, as well as lead to easier scalability. The cost of hosting microservices, and the ease of administration has made them more and more attractive for more and more types of projects. By creating independent units, you reduce the time to develop a standalone piece. This makes testing easier, and makes it easier to bring to scale. There are still cases for monolithic applications, but you can add in microservice units to extend functionality and make reusable components. If you’re having problems with scalability, this may just be the technique to save your next application.

Featured image by Susanne Jutzeler, suju-foto from Pixabay