We have a application landscape with many micro services and use a backend for front-end for the UI to aggregate data.
Would you put the aggregation logic (combine data from multiple micro services) in the domain or application layer of the Front End For Backend Application?
It feels like business logic, however, there is no persistance only data retrieval, so I am in doubt where to put it?
Backend-for-front-end implementations shouldn't need to contain any real business logic as they only serve as gateways which are focused on specific front-end clients (mobile, desktop, web, etc.).
So of course there is logic in your BFFs but it will rather be the aggregation logic. Taking care of processing the front-end client requests and managing the workflow to communicate with the involved microservices - be it via synchronous or asynchronous communication - as well as aggregating the data and serving it back to the client.
What you usually end up with are some kind of controllers handling the API requests (e.g. via REST), some services containing the aggregation logic, some kind of anemic models (i.e. without logic) representing the client requests and responses and stuff like that.
I don't know what technology stack you are on but you can have a look at some sample BFF implementations in a microservices architecture at the Microsoft powered eshopOnContainers project.
Note: if you are really sure there is business logic required in your BFF I guess you might have to consider if this should rather be part of an already existing microservice or if you even might not have discovered a new bounded context yet this logic rather fits in.
Ideally Backend for frontend should not have any business logic. It should do authentication/authorization & routing logic.
If you are willing to do lots of aggregation and lots of frontends (need different set of data) then you may use GraphQL.
Related
I am developing an application where there is a dashboard for data insights.
The backend is a set of microservices written in NodeJS express framework, with MySQL backend. The pattern used is the Database-Per-Service pattern, with a message broker in between.
The problem I am facing is, that I have this dashboard that derives data from multiple backend services(Different databases altogether, some are sql, some are nosql and some from graphDB)
I want to avoid multiple queries between front end and backend for this screen. However, I want to avoid a single point of failure as well. I have come up with the following solutions.
Use an API gateway aggregator/composition that makes multiple calls to backend services on behalf of a single frontend request, and then compose all the responses together and send it to the client. However, scaling even one server would require scaling of the gateway itself. Also, it makes the gateway a single point of contact.
Create a facade service, maybe called dashboard service, that issues calls to multiple services in the backend and then composes the responses together and sends a single payload back to the server. However, this creates a synchronous dependency.
I favor approach 2. However, I have a question there as well. Since the services are written in nodeJs, is there a way to enforce time-bound SLAs for each service, and if the service doesn't respond to the facade aggregator, the client shall be returned partial, or cached data? Is there any mechanism for the same?
GraphQL has been designed for this.
You start by defining a global GraphQL schema that covers all the schemas of your microservices. Then you implement the fetchers, that will "populate" the response by querying the appropriate microservices. You can start several instances to do not have a single point of failure. You can return partial responses if you have a timeout (your answer will incluse resolver errors). GraphQL knows how to manage cache.
Honestly, it is a bit confusing at first, but once you got it, it is really simple to extend the schema and include new microservices into it.
I can’t answer on node’s technical implementation but indeed the second approach allows to model the query calls to remote services in a way that the answer is supposed to be received within some time boundary.
It depends on the way you interconnect between the services. The easiest approach is to spawn an http request from the aggregator service to the service that actually bring the data.
This http request can be set in a way that it won’t wait longer than X seconds for response. So you spawn multiple http requests to different services simultaneously and wait for response. I come from the java world, where these settings can be set at the level of http client making those connections, I’m sure node ecosystem has something similar…
If you prefer an asynchronous style of communication between the services, the situation is somewhat more complicated. In this case you can design some kind of ‘transactionId’ in the message protocol. So the requests from the aggregator service might include such a ‘transactionId’ (UUID might work) and “demand” that the answer will include just the same transactionId. Now the sends when sent the messages should wait for the response for the certain amount of time and then “quit waiting” after X seconds/milliseconds. All the responses that might come after that time will be discarded because no one is expected to handle them at the aggregator side.
BTW this “aggregator” approach also good / simple from the front end approach because it doesn’t have to deal with many requests to the backend as in the gateway approach, but only with one request. So I completely agree that the aggregator approach is better here.
We want to figure out, is it a good practice to split the REST API and App Server. We code both of them with NodeJs and host it on AWS, also note that we want to connect other clients (Android/iOS) with the API and have separate database server.
Our main questions are:
it is more secure ?
better performance ?
there are special features of the development, which we must consider?
that is then the REST server is down? do we have to cache the data on the App Server ?
we also have some simple logic on the client side like "password forget", which server handle this ? (App- or REST server)
which of them handle the authentication ?
it is more secure ?
No. It is not. In fact, it is less secure as the attack surface is larger. And you need to individually authenticate and authorize each services.
better performance ?
Nope. Function calls with in the same application is much faster than serializing -> network latency(http(s) overhead) -> deserializing -> processing -> serializing -> network latency(http(s) overhead) -> deserializing
there are special features of the development, which we must consider?
Yes, deployment strategy, service discovery, graceful degradation in case of upstream service unavailability.
that is then the REST server is down? do we have to cache the data on
the App Server?
This depends on the situation, there is no universal answer to this question. Trust me, nobody other than your team/product owner can answer this question. Mostly this decision will be driven by the contract that you establish with your consumers. I would suggest to read about circuit breaking/ graceful degradation/ http response codes for partial response etc
we also have some simple logic on the client side like "password
forget", which server handle this ? (App- or REST server) which of
them handle the authentication ?
From this question, I am assuming that you don't have a clear separation for individual responsibilities of each service yet. That begs the question, why split these into 2 at this point of time. Why can't all the functionality reside in one application to begin with. As you evolve, as you start feeling the pain of a monolithic application, you can revisit your architecture and break it into small pieces as it deems fit. In my opinion, for smaller applications, monolithic architecture is much more manageable than microservices.
Just one humble suggestion, I wouldn't name one service REST and other App server, that may give an impression that you may be looking this from an incorrect angle.
In my opinion, if I am coming to a point where my monolithic app is not manageable anymore, I would split it based on functionality (look at unrelated entities and take them out as a separate service)
Are Logic Apps considered microservices? If so, is making HTTP API calls from Logic Apps, whether it's using HTTP/Function/APIM connectors, not a violation of direct HTTP communication between microservices?
If possible, never depend on synchronous communication (request/response) between multiple microservices, not even for queries. The goal of each microservice is to be autonomous and available to the client consumer, even if the other services that are part of the end-to-end application are down or unhealthy. If you think you need to make a call from one microservice to other microservices (like performing an HTTP request for a data query) in order to be able to provide a response to a client application, you have an architecture that will not be resilient when some microservices fail.
Moreover, having HTTP dependencies between microservices, like when creating long request/response cycles with HTTP request chains, as shown in the first part of the Figure 4-15, not only makes your microservices not autonomous but also their performance is impacted as soon as one of the services in that chain is not performing well.
Source: https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/architect-microservice-container-applications/communication-in-microservice-architecture
Yes, Logic Apps are primarily Http based services. Whether or not it's 'micro' really doesn't matter because 'micro' is too abstract to have any real meaning. It was a useful marketing term at one point but it's tour on the tech fashion runway has ended. So, don't even think about that. ;)
What the authors are trying to express is that you should avoid chaining dependencies in an app's architecture. A waits for B which waits for C which waits for D which waits for E, etc... That's the first line in the graphic.
Instead, Basket can check Catalog on it's own, then call Ordering, while Inventory is checked in the background. You only one level deep instead of 4.
I'm planning a non-trivial realtime chat platform. The app has several types of resources: Users, Groups, Channels, Messages. There are roughly 20 types of realtime events having to do with these resources: for instance, submitting a message, a user connecting or disconnecting, a user joining a group, a moderator kicking a user from a group, etc...
Overall, I see two paths to organizing all this complexity.
The first is to build a REST API to manage the resources. For instance, to send a message, POST to /api/v1/messages. Or, to kick a user from a group, POST to /api/v1/group/:group_id/kick/. Then, from within the Express route handler, call io.emit (made accessible through res.locals) with the updated data to notify all related clients. In this case, clients talk to the server through HTTP and the server notifies clients through socket.io.
The other option is to not have a rest API at all, and handle all events through socket.IO. For instance, to send a message, emit a SEND_MESSAGE event. Or, to kick a user, emit a KICK_USER event. Then, from within the socket.io event handler, call io.emit with the updated data to notify all clients.
Yet another option is to have certain actions handled by a REST API, others by socket.IO. For instance, to get all messages, GET api/v1/channel/:id/messages. But to post a message, emit SEND_MESSAGE to the socket.
Which is the most suitable option? How do I determine which actions need to be sent thorough an API, and which need to be sent through socket.io? Is it better not to have a REST API for this type of application?
Some of my thoughts so far, nothing conclusive:
Advantages of REST API over the socket.io-only approach:
Easier to organize hierarchically, more modular
Easier to test
More robust and elegant
Simpler auth implementation with middleware
Disadvantages of REST API over the socket.io-only approach:
Slightly less performant (source)
Since a socket connection needs to be open anyways, why not use it for everything?
Slightly harder to manage on the client side.
Thanks for reading !
This could be achieve this using sockets.
Why because a chat application will be having dozens of actions, like ..
'STARTS_TYPING', 'STOPS_TYPING', 'SEND_MESSAGE', 'RECIVE_MESSAGE',...
Accommodating all these features using rest api's will generate a complex system which lacks performance.
Also concept of rooms in socket.io simplifies lot of headache regarding group chat implementation.
So its better to build everything based on sockets[socket.io or web cluster].
Here is the solution I found to solve this problem.
The key mistake in my question was that I assumed a rest API and websockets were mutually exclusive, because I intended on integrating the business and database logic directly in express routes and socket.io handlers. Thus, choosing between socket.io and http was important, because it would influence the core business logic of my app.
Instead, it shouldn't matter which transport to use. The business logic has to be independent from the transport logic, in its own module.
To do this, I developed a service layer that handles CRUD tasks, but also more specific tasks such as authentication. Then, this service layer can be easily consumed from either or both express routes and socket.io handlers.
In the end, this architecture allowed me not to easily switch between transport technologies.
I am building two sets of services on a website (all written in NodeJS on the server), both are using a RESTful approach. For the sake of modularity I decided to make both services separate entities. The first service deals with the products of the site and the second specifically deals with user related functions. So the first might have functions like getProducts, deleteProduct etc... The second would have functions like isLoggedIn, register, hasAccessTo etc... The product module will make several calls to the user module to make sure that the person making the calls has the privilege to do so.
Now the reason I separated them like this, was because in the near future I foresee a separate product range opening up, but will need to use the same user system as the first (even sharing the same database). The user system will use a database that spans the entire site and all subsequent products
My question is about communication between these projects and the users project. What is the most effective way of keeping the users module separate without suffering any significant speed hits. If the product API made a call to the user API on the same server (localhost), is there a signifcant cost to this, versus building the user API into each of the subsequent projects? Is there a better way to do this through interprocess communication maybe? Is simply having the users API run as its own service an effective solution?
If you have two nodes on same server (machine) then you have not bad performance in terms of network latency because both are on localhost.
Then, nodes will be communicating using a rest api, so on the underground, you will use node js sockets. You could use unix sockets instead of http sockets because are faster BUT are worst to debug, so I recommend you don't to that (but it's ok know alternatives).
And finally, your system looks like an "actor design pattern". At first glance this design patter is a little difficult to understand but you could have a look at this if you want more info about actor model pattern:
Actor model for NodeJS https://github.com/benlau/nactor
Actor model explanation http://en.wikipedia.org/wiki/Actor_model