Exploring the World of Microservices: A Look Inside
Exploring the World of Microservices: A Look Inside
The general view of Microservices presented mainly remark on its “advantages” over methods of designing and developing against different approaches, such asthe most classic comparison – the monolithic app architecture. As often happens, people in the industry get enthusiastic about these “advantages” and subsequently the hype around it. As Microservices grow and spread as a practice across more and more organizations around the world, people begin to wonder if they are missing the chance to “belong” to those who have adopted it and sometimes even try to make a rushed implementation (this is common in smaller organizations, who might lack the proper amount of collaborators to perform microservices as they should, more on this later). They feel adopting this as a trend has a quality of status that would be beneficial for them without fully understranding the true benefits. .
It is important to identify why we want to get aboard the Microservices train. It is important to understand the implications of doing so which will allow us to leverage everything that microservices has to offer instead of joining the microservices world just because it is the buzzword of the moment.
This, as mentioned, will likely result in us leveraging all the tradeoffs moving towards microservices and reducing the headaches and misuses that might be caused otherwise.
So, What Are Microservices?
A microservice architecture is a variant of the service-oriented architecture. An architectural pattern arranges an application as a collection of loosely coupled, fine-grained services communicating through lightweight protocols.
This being said, it is generally spread that microservices bring lots of *advantages*, and many times, these are among those mostly listed:
- Scalability improvements, more atomic and specific to different services/flows of business
- Program language and technology agnostic
- Simpler to deploy
- Better Unit testing
- Faster time-to-market
- Simpler logging due to services having their independent logs
- Easier to implement experimental versions and MVPs by alternating services
- Team optimization, since ideally, teams owning services become smaller according to the service size
These advantages are the ones that make microservices so appealing. To leverage them fully and ideally prevent them from backfiring, we must be prepared to adopt them. For our team, this is a well-known aspect companywiseand many aspects have been considered for the organization to implement microservices successfully.
From The Code Perspective
In the microservices world, it is quite common to have new services appearing regularly. New services are created as new problems arise, requiring new organisational solutions. This may feel odd for those coming from more monolithic approaches and seem counterintuitive. Still, we must pay special attention to this aspect to avoid having microservices so big that they become small monoliths. Ideally, a microservice should only have one responsibility and interact with other services (even creating new ones if none existing could provide a solution!) when needing to perform something that the service cannot do. I like to think about it as we are taught to do with classes and objects: every type should have a single responsibility, and the same goes for our services. In the general picture of our services, we can abstract enough to consider them as classes or objects that interact with each other.
As you might have already assumed, we frequently create new services for the reasons explained. For this, it becomes a bit crucial to have a template project, template repository, scaffolding tool, or similar solution that can provide us with the initial boilerplate that will set our new service up for success, ideally removing the repetitive bit of configuring repeated tasks as logging configuration, dockerization, framework versioning, and so on. This would give us both more time to focus on the actual business logic of the service and prove to be very helpful when updating all our services, for instance, to a new logging infrastructure version or a new docker image utilized across all our services.
We have a different set of model repositories from which we can create our services, depending on the kind of service it will be: varying from DB (SQL, NoSQL, etc.) connections if it is going to be a proper service or a service worker instead (publishing messages vs polling, i.e.). Initial configuration for our terraform implementation. Initial setup of environment variables for our support environments (Dev, UAT, Staging, Prod). Different docker setups (different versions of the NET framework).
As a consequence, you will find services created this way have normalized different aspects of them, which makes them easier to maintain: terraform, docker and environment variables will be in the same directories, keep the same structures, and the experience of performing modifications needed in them is going to be the same in all the services we have created this way. Depending on the language of your choice, the same will happen for configuration files involved in the platform you develop. The startup configuration is in the same place for all our services, including the initial design for loggers, tracers, and other infrastructure assets.
This will allow us to have some knowledge of services we didn’t have actual development experience with. For instance, if you have to update a certain environment aspect of a service you have never worked with before, you’ll already know where to look for its terraform configuration, environment variables or any other part you might be interested in modifying, given the task at hand.
From The Team and Human Perspective
It is very important to understand, despite the microservices itself, the technical ability and knowledge that the team has. You virtually use any language and platform to create services since the only real limitation, is that the interacting services must be able to communicate through the same protocol. Depending on your needs and conditions, http, RPC, or just publishing messages into a queue will get dealt with by another service. Anyway, the fact that this freedom on technologies is true and possible, as mentioned above, we must know the technical conditions of the team when deciding which language to use: if your team has little to no experience with, let’s say, Golang, despite it being a great language it might not be the best decision since it would be more challenging to work on by the team if their experience is, for instance, JAVA or NET. I would advise following the team’s experience when making this decision and considering using another language when the situation makes the language a better choice despite the experience. For instance, if you need to work heavily with data, it would be to good to go with Python. While working with files and read and write operations,Nodejs would be a good alternative. Unless you have a very specific need that ties you to choose a particular language, it would be beneficial for the organization to have most of the services in the language they have the most experience in. For our team, we mainly work with NET and JAVA. This is great for us since we have a lot of experience working with them, and they are widely used in the software industry, so it will make things easier when looking for new people to join our team/organization.
Microservices propose advantages of ease of deployment at atomic business domains -since each service works on a single responsibility, many other benefits come from the “micro” part of microservices. This is true, but it also implies that your organization might need a well-capable big infrastructure team with experience working with cloud providers. CI/CD pipelines, and make infrastructure accessible to developers that will maintain and support it from the Terraform and environment variables we previously discussed.
At our client, we have a great team of developers, as we also have a great group of DevOps that always give us support and help us by providing configurations, instructions and documentation to stay up to date with the organization-wise decisions and requirements we have to meet. This way, they can lead the way we need to go in terms of infrastructure by taking the decisions related to that matter, and we can easily propagate that into our services by tuning terraform, docker, and environment variables to meet such needs. The key here is that developers can do part of that work. In contrast, DevOps, despite doing its part of the infrastructure work, can also indicate how the organization must work accordingly in terms of infrastructure.
There are many examples in which access and availability to the DevOps time is critical and useful. A few examples of this come to mind: updating Terraform versions, moving over to Terra Grunt (a Terraform wrapper), getting access tokens, API keys, and integration aspects key to third-party providers we consume to make our services capable of sending emails, monitoring, tracing, logging, and provide observability to our services.
This way, the responsibility of keeping and maintaining infrastructure becomes shared between the DevOps and developers’ teams. This has many advantages since every development team is responsible for keeping services up to date according to what the DevOps team dictates, and also gets everyone involved and invested in maintaining healthy services ready for production. It also ensures that the work that needs to be done can be achieved sooner rather than later since it is not only the DevOps team responsible for getting the job done.
Microservices Can Go Wrong.
All points exposed in this post are true. Yet, still, there are aspects we must consider for our organization to leverage the advantages of microservices instead of suffering from poor or lacking implementation.
The main aspects to consider are the team size, the team knowledge and expertise, the infrastructure and how clear the responsibilities are. Let’s go through these a bit deeper.
It is important to have enough people in the organization to cover the different aspects of the microservices. Unfortunately, it is not only enough to part your monolithic app into smaller pieces of software but to assign teams to own each of them and be responsible for its development. In addition, having enough people in the DevOps or operations team is crucial to make resources available to different groups owning these services. Once the services are in place, there is also a need for the teams to develop their capacity to identify when it is needed to create a new service and determine what falls under the responsibility of each of them.
Team Knowledge and Experience
As we discussed, the team must have the expertise to work on their services. This could be translated into having teams with the proper knowledge of docker, terraform, the language chosen to build the service originally, and the capacity to learn or already know the technologies that might interact with the service, such as SQS, Elastic Search, key-value storage systems, etc.
It is crucial to succeed with microservices to have a proper platform to deploy, run and work your services. Cloud providers, such as AWS, Google Cloud, Azure or VPS, such as Digital Ocean, or maybe your own managed cluster, must be set up and operated by a team(DevOps or operations) that can make the infrastructure easily accessible to the development teams. Sometimes, they may achieve it manually; others may opt for Terraform, AWS CloudFormation, Ansible, etc. Your organization must count on people to understand your platform and how to manage and make it accessible for the developers.
This becomes crucial when going with a distributed approach such as microservices since their development and implementation imply a fair distribution of the work. As mentioned above, developers, DevOps and operations teams should work and collaborate to achieve a smooth experience with microservices. Despite owning the development process of the service or the infrastructure involved to get it deployed, every team should know the scope of their work and how to collaborate with and communicate with other groups when a concern needs to be addressed.
Our client had reached a point in which these points the thoughts exposed in this post become a priority for the organization. Every team member has a sense of belonging with the adaption of microservices, which is crucial to the success of our mission of building a distributed platform that grants the solutions required by the organization’s customers. As a developer, it is a great experience to work in an organization that has this collaboration happening so organically.
by Patricio Rodriguez