The term "module" (module) is taken from the article Modules vs. microservices . Similarly, to describe something in between microservices and monoliths, sometimes the terms microlith (monrolith) or monoservice are used. But, despite the fact that the term "module" is already loaded with well-known meaning, in my opinion, it fits better than other options. Update: In the lega commentary I used the term "embedded microservice" - it describes the essence of the approach better than the "module".
Monolith and microservices are very different approaches, so in any attempt to take the best from both, the balance is crucial - what to take and what not. Otherwise, you get a monster like OSGi .
I’m writing microservices since 2009, but I haven’t tried to use modules instead of microservices in real projects - everything described later is my assumption about what the above balance should be, and it needs both theoretical criticism and testing practice.
A module is something like microservice, only implemented within a single application consisting of a group of such modules and a very small part, which is engaged in the initialization and launch of all these modules.
Although formally such an application can be called a monolith, this approach has much more in common with microservices, so it makes sense to compare it with the microservice approach. Like microservice, each module:
Unlike microservices, the module:
Unlike conventional libraries, the module:
In most cases, modules do not need any service registry — instead of registering themselves and searching for other modules, they get the interfaces they need from other modules when they are started, when the starting application calls the initialization function of each module (in the order determined by the dependencies between the modules). As a side effect, this will allow you to immediately detect cyclic dependencies between modules, if they appear (and, if possible, change the architecture so as to get rid of them).
There is a constant added complexity ( accidental complexity ), the same in every microservice (registration / discovery of services, connection and reconnection to them, authorization between services, (de) marshaling and traffic encryption, use of loopback requests interrupters, implementation of query tracing, etc.). There is a similar constant added operational complexity (the need to automate testing and rollout, the implementation of detailed monitoring, log aggregation, the use of service services for registering and finding services, for storing service configurations, for auditing, etc.). You can put up with it, because you can do it all once, as the number of microservices grows, this complexity does not grow, and the advantages of microservices more than compensate for these costs.
But there is a complexity that depends on the business logic of a particular application and increases as the application develops, from which I would like to get rid of at least in those applications that do not require scalability and high availability (or at least that part of the code of such applications that does not have explicit need to interact with external services):
The correct modular approach allows you to retain many of the benefits of microservices (with the necessary support at the level of language and / or development tools), but besides the loss of scaling capabilities and high availability that are not necessary in this application, there are also other ones:
Also, the modular approach has new advantages:
In general, the approach looks quite tempting - we get the opportunity to write a monolithic application in the form of a handful of really well isolated parts (and the language and / or tools, rather than internal discipline), developed in microservice style (in including different teams in different repos), which can be turned into real microservices with a “flick of the wrist” if there is a real need for it ... But for now there is none - we can use the exchange of messages between fashion s within the application as a simple and very quick replacement of the RPC, eliminating the complexity of asynchrony, eventual consistency and handling of network errors.
The necessary support for this approach is currently far from being found in all languages, but in some there is: the author of the article "Modules vs. microservices" wrote about support for modularity in Java 9, Go has been supporting internal packages for a couple of years, in Erlang judging by article on the same topic Dawn of the Microlith - Monoservices with Elixir everything is fine, .... I'm not sure how much it is possible in scripting languages ​​to provide real isolation of modules, but there are attempts: micromono on NodeJS, in the lega comment link to the approach for Python, ...
If you have ideas on the topic (or even better - the experience of a real project on similar principles) or additional links to articles / projects on the topic - write in the comments, I will try to complement the article.
Source: https://habr.com/ru/post/340898/
All Articles