4 ms·
I'm working on a large system with is based on microservice architecture. We primarily use microservices to decompose the system into modules and enforce module
by orless 10y ago
I'm working on a large system with is based on microservice architecture. We primarily use microservices to decompose the system into modules and enforce module boundaries. Things like scaling or performance is not so much of the problem, the monolyth would most probably work just as well.
Technically we write Spring Boot-based microservices which mainly exchange messages over RabbitMQ and in some rare cases call REST interfaces of each other.
Below a few problems I have with this architecture:
* Code duplication. For instance, we have to implement more-or-less the same DTO on both sending microservice as well as receiving microservice.
* Refactoring across microservices takes a lot of effort. In several cases we didn't cut in the right places and had to move functions across microservices. That was always quite difficult, and we also had to implement migration routinges (for databases as well as unprocessed messages which may be still in queues).
* Versioning and synchronization of messages. Our system receives events from the number of external data sources which trigger processing in the microservices and finally produce results. Since message exchange is asynchronous, older messages may overtake newer messages so we have to version them in order to not output obsolete results. Another problem is that messages travel different paths in the system, so it may happen that a microservice receives two messages which are based on partially obsolete data. Consider two sources A and B which produced events a0, a1, b0, b1. Later in the system a microservice receives two messages p and q based on p(a0, b1) and q(a1, b0) respectively. These messages are not compatible and cannot be processed together. But in order to detect this we have to track version of incoming events (a0, a1, b0, b1) all along the processing.
* A hell to debug. At the moment we have a network of around 40 microservices which process data from ca. 6 sources and feed 3-4 receiving systems. Microservices are quite complicated, the work with often incomplete or incorrect data, employ a lot of heuristics and make a number of assumption which are sometimes proven wrong. If any of the receiving systems report a problem we have pretty hard time identifying which of the few dozen microservices failed. Reasoning about asynchronous message processing is very difficult and approaches like remote debugging actually change the behaviour of the system.
* Tools. We employ maybe a dozen of different tools and custom scripts solely for the purpose of configuring, deploying and running our microservices. We'd most probably only needed a small part of them for a monolytic system.
From the other hand our system is a fourth attempt to solve a very difficult and important problem for our company, the problem which persisted for more than 30 years. And it is the first attempt which is so far successful.