Do you have a monolithic application (for example a complex server-side enterprise application) with big features like support varieties of different clients, API for 3rd parties and some integrations with other web services and message brokers? Code usage is tolerable, but you want to release a smashing feature in the future, though you do not know how to manage the code, the integrations, the changes, etc.?
If you are using monolithic applications, you might have been wondered about the following questions:
- How to manage the codebase?
- How to scale our application for increased rps (request per second)?
- How can we build, test and deploy new features as fast as possible?
- How to use new technologies in our codebase (such as a new programming language or using a second language)?
Although the solution is not easy but is definitely effective and worth the time of your team: The answer to all of your questions is: microservices (microservices to the rescue!):
- It is agile and flexible to change code or behavior rapidly
- The codebase is much smaller (per service), so the developer has less context
- You can create smaller teams for microservices (clearer focus and responsibility)
- Scale much easier, because you can scale per service, not the whole application
- You can use designated solutions for separate operational tasks, for instance, it is a good idea to use low-level programming languages to handle operations they were originally designed for. Such as Java or PHP for Web applications, suitable libraries for communication and tools like, XML or JSON.
Microservices are a real God-send for those who have complex solutions, though you might consider sticking to your monolith structure if your system’s administration proves to be easily manageable using this method.
How can you move your monolith application to the world of microservices?
To refactor your code, follow these phases step by step and finally enjoy the outcome.
The 10 step plan
You must understand what is currently happening in your application, so you need centralized logging and a distributed request tracing system (such as Zipkin or Opentracing). You need metrics, alerts, analytics and so on, to understand your application’s behaviour. If you have an API, you should measure its usage to know which parts are critical and need to devote more time to it.
Add an Intelligent Router in front of all public APIs to get some usage information and perform route mapping and data rewrites. You can route different clients to different services too, so you can decouple clients from specific services. But, of course, it is a SPOF (Single Point of Failure), so it must be highly available.
You should think about version control because you’ll be moving a lot faster in the world of microservices. You will create, change, destroy new services, or modify APIs, so it is worth to start thinking more thoroughly about version control. The main objective is to use one schema that fits your team and/or organization.
Create a template for your ideal microservice that includes:
- Configuration Management
- Distributed request tracking
You can create a template with a Virtual Machine for Monitoring, Analytics, Security, etc., or with container technology, such as Docker or rkt, to use that template as a basis for each new microservice.
Agree on an API Generation approach (do not do it manually!), because you need to generate the API itself, the documentation, the stubs, the clients, etc. For API generation, you have loads of tools, such as Swagger, Apimatic, etc.
EVERYTHING! Please, automate as much as you can. Create CI/CD Pipelines for builds, one click deploys, and a useful dashboard for viewing and managing the processes. Make your build process as simple as possible to add new components anytime or make changes as fast as you can in your codebase or in your pipelines.
Identify boundaries for distinct features or functionalities from your monolith application, and reimplement it as a microservice. Instead of your monolithic application, you will deploy, map your microservice and move new requests to it (via the Router). Deploy your microservice early and often to follow your modifications. The microservices should not share data stores with other microservices, so migrate your data on the fly to avoid maintenance time or outage.
We do not love documentation (others neither), but a good documentation makes life so much easier. All APIs need to have documentation, but if you generate API (as we advised in step 4), you can generate the documentation too. Use tools for documentation generation, such as javadoc, doxygen, perldoc, pydoc, etc., it is only based on the programming language you will use.
As the number of services increases, your initial idea to point HTTP communication will become a bottleneck (and of course, you have a bigger network overhead too). For this problem, you can create event based communication via a Message Bus.
Probably you will have problems with service discovery. When you only have a few microservices, you can put in the whole service scheme that you want to talk into the client service. As your microservices grow they will become more unmanageable, so you’ll need to start thinking about service discovery, such as etcd, or if you use an orchestration tool, you can use it too (such as Kubernetes).
If your UI relies on your monolithic application, you must separate them. The UI elements of a microservice should rely on the service. You might think about frameworks that make it easy to plug components together, like Angular or React. First of all, you may need to split the UI from the monolithic application to one or more microservices.
Dedicate different APIs for each Client (web, mobile, desktop, IoT, etc.), because one general API cannot handle different responses and requests for different clients to the extent we wish. You may want to start thinking about pushing most of your microservices onto the most hosted PaSs (Platform as a Service), something like OpenShift, to make local development and deployment much more simpler.
It is not an easy transition and it takes time to change from monolithic to microservice architecture. It requires a lot of upfront work (refactoring, thinking, building, automating, deploy) but the complexity of your application does not disappear, it just moves. Microservices are not a good fit for everything, so please think twice before making the transition in order not to waste time.
Most importantly, you will need to change your organization’s structure if you want to succeed. You need to think agile and need to make small steps to deliver the changes to your customers as fast as possible.