I classify client-server interaction from A to Kafka

Hello everyone, my name is Alexander Kartashov, I am a Java backend developer at Alfa-Bank. I work in the Alfa Business Mobile project, a mobile application for legal entities. As part of the project, I often had to integrate with different banking systems, with different technology stacks, and this is how this article was born, as an attempt to streamline everything.

To summarize, client-server interaction can be considered the entire transmission path from service A to service B.

There are many options for how to do this: different approaches, architectures, technologies, protocols.

Large projects often use different combinations of different tools, as in the picture below.

But why were these particular tools chosen and not others? What is the difference between them, how are they related to each other and why are there so many of them?

How are technologies chosen?

The answer is that each tool has a specific pool of tasks that solve them best. Depending on the task, a combination of tools is selected for the most productive solution.

How exactly are they selected? To understand the choice of this or that technology, let's go through this scheme:

  • define the conditions of the problem;

  • Let's look at the classification of the solution to this problem;

  • and select an implementation.

Let's start with the conditions.

Conditions

Conditions are requirements and properties.

  • The solution may have certain requirements, for example, to withstand a certain level of load, support a certain type of client, and be fault-tolerant.

  • Properties usually include some characteristics of messages and the importance of the request – how important it is to process it.

Classification

You can classify client-server interactions in different ways, but I chose the main ones:

  • by the nature of the request: synchronous/asynchronous;

  • and by data exchange method: request-response and publish-subscribe.

Now a little more detail.

According to the nature of the request.

The synchronous nature of the request is when all calls are made in one thread.

Let's say service A must call services B and C. It makes a request to them and while the services are processing, A does nothing and just waits.

This wait is called thread blocking, which is not very good.

Asynchronous means that we will not have a block, that is, service A calls services B and C, but continues its work without waiting for a response.

If our services B and C are also synchronous, then they will also not do work in the main thread, but transfer an additional thread to generate a response.

And once they finish, they return the answer. Our service A receives it and processes it already specially created for this flow. This way we avoid blocking.

The advantage of a synchronous connection is, first of all, ease of implementation and determinism, when each request corresponds to one response. The disadvantages are blocking and performance, since we do not spend resources very correctly.

The advantage of an asynchronous connection is that, on the contrary, it does not block, so it is more productive. But speaking of cons, it is more difficult to implement and more difficult to debug.

We can conclude that the synchronous approach is suitable for simple systems without high load, and asynchronous for systems with high load.

By data exchange method.

Request-response works on the principle “the client makes a request to the server and receives a response.”

Publish-subscribe works on the principle that we add a third element – message broker (message broker). Our client first sends the request to him, and then our service, which must receive this request, either requests it from the broker, or the broker himself transmits it to him.

This third layer adds advantages such as data distribution: our request can be received by several services at once or by a group, whatever you like. This group is easier to scale because we can increase the number of brokers and increase the number of requests that can be accepted. This system is also more reliable, because in this case it is more difficult to lose a request: even if one server fails, there will be another, which also saves all these requests.

Among the disadvantages, it is worth noting the complexity of implementation and difficulty of debugging.

As for the advantages of request-response, like synchronous ones, they are ease of implementation and determinism. The disadvantages are that it is easier to lose a request and limited performance.

We can conclude that request-response is, in principle, suitable for any system, and publication-subscription is suitable for systems with a high load, where it is important not to lose the request.

Let's move on to implementation.

Implementation

I have identified the following hierarchy (in order of importance):

  • First comes the architecture – a set of recommendations about what the system as a whole should look like.

  • Technologies – implementation of sending data via protocol.

  • Next, the protocol is a set of rules that describe the interaction of the network.

  • And the data format – “what” we will transmit.

As a result, we get such a diagram, answers to questions will lead to the right choice.

Now let's go through our plan, and to make it easier to understand how to choose technologies, I will show how to work with the plan using the example of a couple of Alfa-Bank projects.

ISS

Let's start with the MKS project – a microservice corporate standard.

A little background. There is such a project – NIB, New Internet Bank.

This is a bank web application for legal entities. It has a front part and a back end. The backend part is divided into domains and the MCS is one of the domains.

It belongs to platform conditions in the sense that it solves problems that are not directly related to business logic, and other domains use it as a client of their own.

And we need to understand, in fact, how to interact with this domain.

Let's start with the conditions

Let's highlight the requirements.

  • First of all, it is important to withstand a high load, because we will have many clients.

  • Clients are also diverse because they can be written in different languages.

  • But integration with them should be easy.

Properties:

  • It can be noted that responses and requests are generated in a small size.

  • Responses are generated quickly.

Let's classify the solution

Let's choose a request-response because we don't have requirements that every request must be processed, so we'll choose a simpler option. And since one of the conditions is that the answers must be generated quickly, we will even choose this option.

Due to the nature of the connection, we will have to choose a more complex asynchronous option, since it is necessary to withstand a high load.

Implementation

We've sorted out the classification, now we need to determine the implementation.

I put together a table to make it easier to choose.

I put together a table to make it easier to choose.

What options do we have? The most common is the REST architecture. It involves the use of the HTTP protocol and its method. I didn’t indicate the technology (first column), because any tool that can send an HTTP request is enough for us. This is available in almost every language in the default library.

The data format is also not specified because REST does not imply any specific format.

Another common option is the RPC methodology. And this is precisely a methodology, not an architecture, since it only implies the relationship between client and server: the client must call a specific method on the server.

REST or RPC?

Let's talk a little about what's the difference between them?

  • REST is about creating an HTTP request and sending it somewhere via a URL.

  • RPC is when, for example, we call a specific method of service B from service A and must know specifically what to send there and what will be returned to us.

I chose three RPC implementations: gRPC, Apache Thrift and the Saab implementation. But we will only compare gRPC with REST since it is the most popular option of the three.

So, let's start the comparison with REST.

We must form an HTTP request. The body must indicate (but may not indicate) some data in HTML, JSON. The format is not important, but JSON is usually used.

Using some mechanism, we generate a request and send it.

On the other side we also process it using any mechanism.

Now, as for gRPC, this is an implementation of RPC from Google.

Let's start with the task: we need to call the getColor() method of service B from service A. We describe the contract, indicate the controller of our service B and the models that we will receive and transmit.

Next, the gRPC compiler generates code in the language we need, which we add to our services.

Now service A, using the generated code for the client of service B, will be able to call a method from service B.

gRPC comes bundled with their protobuf protocol. It uses the HTTP/2 application protocol (but this is not a requirement).

By the way, this is a binary protocol, so we need to have two mechanisms for serialization and deserialization. Accordingly, we form a request, serialize it into bytes, transfer them to HTTP and deserialize them on the other side back into the model.

As a result, we will indicate the pros and cons.

We cannot directly compare REST and gRPC, since they are at different levels of abstraction, so we will compare it with a specific implementation of REST – the REST API, which uses JSON as a data format.

So, let's note the pros and cons.

Pros of REST:

  • ease of implementation;

  • support for different programming languages;

  • readability of requests and responses, since JSON is a text format, we can intercept and read it.

Among the disadvantages, it can be noted that there is no certainty (a specific contract) and relatively low performance with gRPC, again, due to JSON.

Note. The disadvantage of “uncertainty” with REST JSON can be eliminated, since REST does not prohibit the use of contracts and there are special libraries that add contracts.

Plus gRPC:

  • performance, because we use a binary data format, and it is much easier to transmit it;

  • certainty due to the contract.

The downside is the complexity: implementation and debugging.

Also both support asynchronous format.

We can conclude that REST JSON is, in principle, suitable for any system, and gRPC is primarily where high performance is needed.

Let's remember our requirements. We were not talking about high performance, rather, on the contrary, about easy integration, so our choice is asynchronous REST on JSON.

Then we make asynchronous REST APIs our service.

We are creating a library with clients for our services to make integration easier.

We integrate it into our clients or, if necessary, the client himself will write the code to send under our contract. And now clients can interact with the ISS.

We have covered all the requirements – it can withstand high loads, client diversity and easy integration.

ABM notification

This is a project about sending various notifications, push notifications, emails, SMS and so on.

ABM is Alfa Business Mobile, a mobile application for legal entities. There is a front part, a back end part. By the way, this is a neighbor of NIB, but NIB is a web version, and ABM is a mobile one.

ABM is also divided into domains and we need to somehow solve the issue of sending notifications to clients.

To do this, you need to send a request to Android and iOS – we will separate them into a separate domain, which will already be knocked on by other domains and other systems to send notifications.

But since NIB and ABM work with the same clients, it is logical to move this domain somewhere into one place. This place became the NIB.

We have a corp_notifications domain, where other domains go to send various notifications.

Accordingly, we need to understand how to interact with it.

Conditions

Let's look at our requirements – this is the diversity of clients and we must not lose the request, since notification is very important.

From the properties, it can be noted that small requests and responses are not required.

Let's classify the solution

In this case, we will have to use publish-subscribe due to the requirements, and the nature of the connection, in principle, can be left synchronous.

Implementation

The scheme we worked with was about request-response, and now we have publication-subscription.

There is no architecture in this case, since all these message broker technologies do not have any specific architecture. But I indicated the type for them – the data transfer model.

How does this even work?

If during a request-response we simply communicate between services, make requests and send them somewhere and receive a response from it, then in a system with message brokers all requests are sent to it and it sends them further. Well, or clients themselves request them from him.

There are two main types of message brokers: point-to-point And Publish/Subscribe.

In point-to-point, each request corresponds to only one client and he will receive it. The sender and recipient of the message are independent of time. The recipient will send a confirmation after successfully receiving the message.

Publish/Subscribe contains different subscribers for each message – the request can be processed by several services from different projects at once. This approach has multiple publishers as well as multiple consumers. There is a time dependency for publishers and consumers.

I chose three different implementations:

  • IBM MQ – Point to Point type;

  • Kafka – Publish/Subscribe;

  • and RabbitMQ – it has no type because it implements both types, and they use different protocols.

The data format, again, is not specifically specified.

A small retreat. I put all the protocols in one cell. But this is a kind of simplification, since they are all at different levels, solve different problems, and this is not entirely correct.

Let's return to our diagram and select the desired service.

According to our architectural scheme, it is clear that we just need to receive requests from clients, temporarily store them somewhere so that they do not get lost, and process them.

In principle, any technology is suitable for us. But probably the best solution would be some kind of Point to Point. I would choose RabbitMQ because it supports Point to Point, it is an Open Source technology, has a lot of documentation, is easy to implement and, in principle, popular.

But we have one key requirement – to implement it safely and quickly into the infrastructure. But on large projects this can be difficult. And the difficulty is that only Kafka is deployed on our project, which means we will have to use it.

Conclusion

A variety of interservice communication tools and protocols have emerged in response to the unique needs of each project. But, I hope, using the examples of Alfa-Bank, I was able to convey how their selection occurs in our case and how the correct choice of tools affects the efficiency and reliability of the system. It is the flexibility of choice that provides the optimal solution for each specific task.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *