Lets say I have a microservice A that is a rest service, and in this service the user can send a request that does some kind of math calculation based on the parameters sent. This microservice A has to call a microservice B in order to get a calculation and microservice A has two steps, first a validation service that does several validations for the request, included to validate the value of the calculation has to be in some kind of range and two, a service that stores in a table the calculation got from microservice B
So, in order to validate this calculation and save it, I have the next options
In the validation service of microservice A, the microservice A calls microservice B to get the calculation and validates it. Then if the validation is OK, the service of microservice A that stores the calculation calls again to microservice B to get the calculation and stores it in the database table
In the validation service of microservice A, the microservice A calls microservice B to get the calculation and validates it. Then if the validation is OK, the calculation is passed in the request for the service of microservice A that stores the calculation. Doing this way the service of microservice A that stores this calculation, does not have to call again to microservice B to get the calculation
I am using option 1 to separate concerns because I think validation service has just to validate, nothing else, and I mean by this that it doesnt have to "store" in the request the calculation like is done in option 2. But in option 1, you have to call two times to microservice B and I dont know if its a bad design
Thanks
Related
Let's say I have an API Gateway for third parties to create orders in my system. As a part of order creation I need to validate that the request model I have been provided is correct - not just statically but by checking foreign keys are valid - that the product id’s are valid in the order, the account id is valid. If not I want to return a 400 to let the caller know they have passed an erroneous request.
What I would expect to do is to create an orders::createOrder lambda function, which would make parallel calls to products::listProducts, accounts::listAccountsForCustomer and other microservices to retrieve the information needed for validation, before I am happy to create the order in the system. This validation needs to happen synchronously as it’s a request/response from a third party to create the order.
I would usually want the logical domains - customers, products, orders, accounts to be separate microservices, and I usually have some logic in an API Gateway layer for orchestration / mapping to the microservices below. I've been reading that calling Lambda from Lambda is a bad idea..
How do I correctly model this on serverless?
For your case it'll be best to keep all this logic within one lambda. Splitting it into multiple smaller functions will add latency, so you have worse user experience and you'll multiply your cost since you have multiple functions running. You can also try Step Functions if you want such split. But it's also pretty expensive, I don't recommend it for such simple case.
I'm in the process of designing a micro-service architecture and I have a performance related question. This is what I am trying out with my design:
I have a several micro-services which perform distinct actions and store those results in their own data-store.
The micro-services receive work via a message queue where they receive requests to run their process for the specific data given. The micro-services do NOT communicate with each other.
I have an API gateway which effectively has three journeys:
1) Receive a request to process data which it then translates into several messages which it puts on the queue for the micro-services to process in their own time. The processing time can be in minutes or longer (not-instant)
2) Receives a request for the status of the process, where it returns the progress of the overall process.
3) Receives a request for combined data, which is some combination of all the results from the services.
My problem lies in #3 above and the performance of this process.
Whenever this request is received, the api gateway has to put a message request onto the queue for information from all the services, it than has to wait for all the services to reply with the latest state of their data and then it combines this data and returns to the caller.
This process is obviously rather slow as it has to wait for every service to respond. What is the way of speeding this up?
The only way I thought of solving this is having another aggregate service/data-store where duplicate data is stored and queried by my api gateway. I really don't like this approach as it duplicates data and is extra work/code.
What is the 'correct' and performant way of querying up-to-date data from my micro-services.
You can use these approach for Querying data across microservices. Reference
Selective data replication
With this approach, we replicate the data needed from other microservices into the database of our microservice. The only coupling between microservices is in the data replication configuration.
Composite service layer
With this approach, you introduce composite services that aggregate data from lower-level microservices.
Let's say we have two services A and B. B has a relation to A so it needs to know about the existing entities of A.
Service A publishes events every time an entity is created or updated. Service B subscribes to the events published by A and therefore knows about the entities existing in service A.
Problem: The client (UI or other micro services) creates a new entity 'a' and right away creates a new entity 'b' with a reference to 'a'. This is done without much delay so what happens if service B did not receive/handle the event from B before getting the create request with a reference to 'b'?
How should this be handled?
Service B must fail and the client should handle this and possibly do retry.
Service B accepts the entity and over time expect the relation to be fulfilled when the expected event is received. Service B provides a state for the entity that ensures it cannot be trusted before the relation have been verified.
It is poor design that the client can/has to do these two calls in the same transaction. The design should be different. How?
Other ways?
I know that event platforms like Kafka ensures very fast event transmittance but there will always be a delay and since this is an asynchronous process there will be kind of a race condition.
What you're asking about falls under the general category of bridging the gap between Eventual Consistency and good User Experience which is a well-documented challenge with a distributed architecture. You have to choose between availability and consistency; typically you cannot have both.
Your example raises the question as to whether service boundaries are appropriate. It's a common mistake to define microservice boundaries around Entities, but that's an anti-pattern. Microservice boundaries should be consistent with domain boundaries related to the business use case, not how entities are modeled within those boundaries. Here's a good article that discusses decomposition, but the TL;DR; is:
Microservices should be verbs, not nouns.
So, for example, you could have a CreateNewBusinessThing microservice that handles this specific case. But, for now, we'll assume you have good and valid reasons to have the services divided as they are.
The "right" solution in your case depends on the needs of the consuming service/application. If the consumer is an application or User Interface of some sort, responsiveness is required and that becomes your overriding need. If the consumer is another microservice, it may well be that it cares more about getting good "finalized" data rather than being responsive.
In either of those cases, one good option is a facade (aka gateway) service that lives between your client and the highly-dependent services. This service can receive and persist the request, then respond however you'd like. It can give the consumer a 200 - OK response with an endpoint to call back to check status of the request - very responsive. Or, it could receive a URL to use as a webhook when the response is completed from both back-end services, so it could notify the client directly. Or it could publish events of its own (it likely should). Essentially, you can tailor the facade service to provide to as many consumers as needed in the way each consumer wants to talk.
There are other options too. You can look into Task-Based UI, the Saga pattern, or even just Faking It.
I think you would like to leverage the flexibility of a broker and the confirmation of a synchronous call . Both of them can be achieved by this
https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html
How to make microservices call async when microservice B depends on the response of A and microservice C depend on response B?
You should avoid chaining calls from one microservice to another in order to fulfill a client's request. It doesn't matter if the calls are synchronous or asynchronous. This can lead to cascade failures so the availability of the system is affected.
Instead, you should gather all the needed data in background (i.e. using cron or events) before the clients' requests. In this way, if service A is down, service B continues to work.
We want to show alternate of a product like most of the e-commerce websites does. In our case, we need to fetch data from multiple microservices.
Products - Stores all product information
Prices - In our case prices are complex and subject to user's location and other parameters. Hence we made it a separate microservice.
Reviews - It manages ratings and reviews about a product.
The end product will be List<AlternateProduct> which would have an image, description, rating out of 5 and a number of reviews.
In microservice architecture, what is the right place to compose a response from multiple microservices?
Approatch 1:
MVC/Rest API approaches APIGateway
API Gateway make an async call to all microservices
The response will be returned to MVC/WebAPI. Where the composition of response can be performed.
Approatch 2:
MVC/Rest API approaches APIGateway
API Gateway make an async call to Products microservice.
Products microservice will call other microservice and perform composition and returns List<UlternateProduct>
Please help me decide!
In this case I would go for Approach 1 sine you can download the list of Products you need and than run 2 other request in parallel for downloading Prices and Reviews.
After your receive response from all 3 requests than you build the model and return it.
I think that Gateway API should be smart enough to make calls to different services and build the result that need to return.