Tuesday, September 15, 2020

Microservice Architectures with Azure Functions

 

Synchronous Requests

If you want to communicate synchronously from a client to a function (HTTP request with HTTP response), then functions offer the possibility to be called via HTTP triggers. 
But the initially simple thought, is followed by some some issues regarding asynchrony concerning a microservice architecture.

As shown, it is technically possible to make functions communicate directly (synchronously) with each other (using HTTP triggers). 

However, this does not correspond to the official Microservice-Patterns, since direct dependencies are created here. 
Microsft even calls this an ANTI-PATTERN:

(Source: https://docs.microsoft.com/de-de/dotnet/standard/microservices-architecture/architect-microservice-container-applications/communication-in-microservice-architecture)

If you still want a connected client to be able to retrieve data directly from a function synchronously, the logical idea is that the functions call each other asynchonously (via HTTP trigger, EventHub or ServiceBus). 
However, the good idea initially disappoints quickly, because it is not technically possible due to the statelessness of the functions to wait asynchronously for a response from one or more functions.

Thus a synchronous call of a function by a client can only responded synchronously if the requested function don´t need to speak with any other functions at all. 
While this is basically possible, the practical use cases of micoservices show, that a state in which a microservice does not have to talk to other services does not last long. 
Progressive development and new features quickly create new dependencies that require communication between the microservices.

REPORT THIS AD

Due to the mentioned points, the synchronous communication of clients with the functions based on a microservice architecture is not recommended and principles for an asynchronous communication should be used.

2. Asynchronous Communication via Broker/Hub

So if asynchronous communication within functions is not possible, the first logical idea is to set up the architecture without functions.
First, you have to consider how to make it possible for the client (frontend) to get replies asynchronously. The usual approach for this is real time web frameworks, such as eg. SignalR, Grpc and others. 
Although Grpc itself can hardly be surpassed in terms of latency and speed, it is difficult to integrate it into a React or Angular web app with the usual board tools. Common methods for this are currently the detour via an Envoy Proxy. 
However, during the development of such an environment, it soon becomes apparent that this technology does not seem to have matured yet. 
For example, generating the prototype files for TypeScript involves significant problems. For sustainable and stabile environments you should better resort to battle-proofed technologies. Here is SignalR quite a good choice

Now that the return channel to the client has been clarified, the question is how the individual services communicate with each other. 
To ensure complete asynchrony of the services it should be advantageous if the services do not know each other. 
Consequently, a distribution point would make sense here. Here, the PUB / SUB pattern is a popular method. GRPC would therefore need its own GRPC broker and SignalR would need its own HUB.
Without going too deeply into detail, you quickly realizes that such an architecture always involves a single point of failure.

3. Asynchronous Communication One-to-One

If now the communication of the services via a broker/hub is not considered meaningful, a direct (but asynchronously) communication of the services with each other is the only thing that remains.
After some research, you quickly gets the idea to use EventHub triggers or ServiceBus triggers in combination with functions. Here, a message is passed through as a relay race to the involved functions on the appropriate trigger and returned at the end again by SignalR.

Passing messages like a relay race, can quickly lead to problems. If you think to an aggregation function, data must be collected from other services and thus it is difficult to treat the message in the sense of a relay race.

The officially microsoft recommended technology for asynchronous communication within functions are so-called durable functions.
However, there were significant lags in the perfomance test. 2 out of 10 calls showed response times of over 15 seconds. And event the other 80 percent of the requests take up to 0,7 sec for a response. Due to this fact, durable functions were not considered further.

In order to realize ideas like an aggregation function, stateful services are required which are capable of waiting asynchronously for a response message. 
With the idea of ​​direct service communication without a broker / hub, the idea of ​​peer to peer services lends itself. For this GRPC is a very good choice.

To overcome the problem of the Envoy Proxies, we simply use a function that acts as a gateway to send messages to the Grpc serives. 
Thus, you can also be prevented that a client must know all the service addresses, these can be very well processed in the sense of a gateway here. 
Because Azure’s functions/gateways scale horizontally and Azure ensures high availability, we do not consider such a gateway a single point of failure.

To find the way back to the client, we use a function in the same way to return the messages on the SignalR channel.

4. Result

You can say that functions have their justification, eg. the approach of database-triggers is quite a smart approach to bring events to the client quickly without the effort of extra business logic to operate.
However, you can not ignore the fact of their latency (especially with Durable Functions). In view of the asynchronicity of a microservice environment, they are not to be regarded as a panacea. Much more they should be chosen for a meaningful combination of stateful services together with stateless functions.

Here an idea of a meaningful architecture combined with statefull container services and sateless functions.

Werbeanzeigen

No comments:

Post a Comment