How we write microservices and why we do not do it quickly







Monolith sawing stories often look alike. The team had a hefty clumsy monolith, they decided to cut it into a scattering of regular and smart microservices, everything became cool. The stories differ only in the degree of horror “before”, joy “after” and a number of secondary characteristics.







In RBK.money, we also have microservices. But we came to them a little differently than most. Everything was even worse for us than the monolith - at the start, everything was just bad.







Under the cat about how we, in fact, built microservices, why OpenSource is not only great in principle, but also works as a motivational component to write good code.







So, everything was bad. So much so that fixing it did not make any sense, but it made sense to agree never to recall this horror and just write everything from scratch. And immediately on microservices. At the very first stage of development, we immediately made it a rule to constantly keep in mind the fact that one day we will want to re-sensoryize all this good or part of it. After all, everything is saved in the history of commits, including nicknames of developers, so we just sit down and immediately try to write everything in such a way that later we are not ashamed of our code in front of the community. After all, no one wants to blush for their code or the architecture of the project, so-so history.







Fast vs good



In an ideal world, you always want to write code quickly and write it well. Well, it’s like “Better to be rich and healthy than poor and sick.” Therefore, microservices have become an excellent way out of the situation. The process of writing code was built on business tasks. Suppose a business needs functionality that will take into account funds in counterparty accounts when making payments. This functionality turns into a microservice, codenamed Accounter, which is engaged in accounting tools. With other microservices the same story.







The main thing here was to make sure that each business functionality was so concretized that one person could write it. It greatly depends on the tasks themselves coming to work, and on how the technical director or project translates this to the team. We managed to do this, it immediately gives a couple of good significant advantages.







Firstly, it provides a large parallelization of development. At the start, we had about 10 people, and we managed to write a large amount of code at the same time (and write well). Secondly, it gives you the opportunity to fully rotate. But this is already a little more important than it seems at first glance.







Very often a person begins to shit, not because he was getting this job for you, but because his eyes are corny and his eyes get dull and dull. If one person is constantly sitting on the same microservice, he can start generating govnokod. And this is not so much a matter of professionalism as a matter of time. After 7-8 months, people will get tired of supporting the same microservice, they will look around - and there life is, spring came after winter, my colleagues have some kind of movement, again a new iPhone came out, and you all are sitting on the same microservice . This is how a monolith is born with a single point of failure in the form of this tired person with bags under his eyes.













Or, in general, a person begins to think that everything is only on him and rests on him. She will try to make herself indispensable by surrounding her work with a bunch of “secret knowledge” and strange procedures. At the beginning of my journey, I had situations where the legacy was so wild that it was impossible to understand without this knowledge. For example, you had to start one service. As you usually imagine this:







  1. Launch the service.


As it was:







  1. Go to the Windows registry.
  2. Find a specific key there.
  3. Change it to 1.
  4. Launch the service.
  5. Reset key value to 0.


This is a classic example of complexity for the sake of complexity and “Nothing works here without me.” In fact, without this, everything works. Only faster and better. You can get rid of this by rotation - ideally when a person writes one microservice for about a couple of sprints, and then leaves to do another task. By this we also maintain a constant exchange of knowledge in a team.







Code from protocol









If you take any TK from the business, translate it well into a human one, shake off the husks and evaporate - you get a protocol, a language that the machine will communicate with. That is, we take a business task, understand for ourselves what exactly and how we will do it, and turn it into a specification for thrift or swagger (microservices inside communicate via thrift). The first step is to describe everything in detail: what the microservice will do, what types of data it will receive, what it will respond to, what kind of structures it will be, and so on. This protocol goes through the first review of those who have a clear idea of ​​how everything works (de facto architects). It works like a coarse filter through which some frank bullshit will not pass even at the concept level.







As soon as the protocol appears, you can sit down to write code. And if the protocol is completely self-revised by universal people, then the code itself is in a team of specific people. We write in three languages ​​- JS, Java, Erlang. The main thing is not to rush anyone with either a review or writing code. Yes, business always and everywhere needs to be fast and cool. But I rarely rush the guys as a technical director, because I understand what they want to do well. The result is a situation that I am often encouraged by business customers over time. But practically do not have to blush for quality.







We hurried only once, when the jackpot was superimposed - a super-customer and extremely urgent deadlines, just created our Wallet. Then yes, we lowered our sleeves and did everything faster than we planned (and worse than we wanted, yes). Ideally, everything was conceived as a bunch of neat microservices. It turned out such a piece of monolith. The advantages of the situation are that we once again realized for ourselves that there is no need to rush. And the service itself is already slowly being pulled into separate microservices, as they wanted.













There are 50 microservices in RBK Money, about 20 people write them. Thrift is everywhere inside, for developers it is a rather complicated protocol, debasing is difficult, documentation is also difficult to write. And if I let thrift out in its purest form, they would call me bad words. Therefore, we did not come up with anything - rest JSON, simple and intuitive, plus OpenAPI, jauntily sticks out. To be able to accept these requests from the outside, they must be validated, authorized, and then launched into the platform by other microservices. And we also wrote this whole thing as an independent microservice, which:









Is it convenient to write a payment system on microservices? Of course - here you have parallelization of work, and maintaining the interest of employees, and the absence of a single point of failure. A single microservice broke down or suddenly the person who did it yesterday left — no problem, you can quickly fix something, and put a new person in the pilot’s seat during the new sprint.













But there is an opinion that if one person sits and carefully cuts a particular microservice for a long time, then he definitely does it well. Since we started talking about this, please write in the comments which approach is closer to you. And most importantly - why.








All Articles