How Api gateway combine responses form microservices - microservices

According to article https://dzone.com/articles/building-microservices-using there is a statement:
The API Gateway is responsible for request routing, composition, and protocol translation. All requests from clients first go through the API Gateway. It then routes requests to the appropriate microservice. The API Gateway will often handle a request by invoking multiple microservices and aggregating the results.
I'm wondering, based on Zuul example, how the API Gateway achiving this?
Let's imagine we have a 2 microservices, one which retrives all available product names and second one which returns descriptions of products. In monolithic architecture we would have only one request to get all needed data. In microservice architecture API gateway should combine responses (from both microservices) and return one response.
How this funcionality should be implemented? Are there any guidelines or articles on that?

Not all API gateway supports aggregation. This is an example of aggregating response of two service for a single client call using nginx.
The side effect of this being it introduces coupling at the API gateway layer.
Another possible solution is to use aggregation microservice. The main responsibility of this service is to provide a client side api. It can make multiple calls to other microservices to formulate the response for the client.See sample below
#RequestMapping(path = "/product", method = RequestMethod.GET)
public Product getProduct() {
var product = new Product();
String productTitle = informationClient.getProductTitle();
Integer productInventory = inventoryClient.getProductInventories();
if (productTitle != null) {
product.setTitle(productTitle);
} else {
product.setTitle("Error: Fetching Product Title Failed"); //Fallback to error message
}
if (productInventory != null) {
product.setProductInventories(productInventory);
} else {
product.setProductInventories(-1); //Fallback to default error inventory
}
return product;
}
Full example here

Related

How to test contracts that somehow cannot be tested by feign client?

We have the following contract in provider:
Contract.make {
request {
method GET()
url('/something/a/b/c') {
}
}
response {
status 400
}
}
This is a contract for an endpoint which has a required query parameter. If the query parameter is missing, then the application returns 400 (BAD_REQUEST).
Now, in the consumer, we use feign client for service interactions. When trying to test this contract, we can't find a way to test this specific contract because feign is a little bit restrictive.
The feign client endpoint:
#GetMapping("/b/c")
public List<Function> getFunctionsBy(#RequestParam #NotNull LegalFormType legalFormType) {
return facade.getBy(legalFormType);
}
How the right way would be? I was thinking at 2 things:
Create contracts that can be tested (this seems like a bad idea because we won't have contracts for every case)
Do not use the application's client (feign client) and use another tool to make the requests (I think this will introduce one more thing to take into account, the tool used).

Web API - Handling the long running call when aggregating the calls

I have a web api project which works as a GateWay for other Mobile clients. When the mobile client makes a call to this Gateway it internally calls the existing services which are hosted by another project and it aggregates the results and return to the client. I have recently come across a situation when my gateway is internally making 3 calls first 2 are returning the data fast but the 3rd call is taking lot of time I want to know the best way to handle this scenario.
Ensure that the return type of API action methods is async Task<YourModelDataType>.
For example, let's say you have a HomeController controller as follows:
public class HomeController : ApiController
{
public async Task<YourModelDataType> Index()
{
return new YourModelDataType()
{
Property1 = await ApiService1.GetData(),
Property2 = await ApiService2.GetData(),
Property3 = await ApiService3.GetData(),
};
}
}
Ensure that calls to the other API projects are awaited. This improves scalability on the server side. i.e. server resources are free to serve other requests while awaiting response from other API services.

Update clients in asp.net core 2.0 using SignalR

I am going through several examples on Asp.net Core WebAPI with SignalR where most of them are demonstrating simple chat application where this is what Hub returns:
return Clients.All.InvokeAsync("Send", message);
And this is how it gets called in Startup.cs
routes.MapHub<Chat>("chat");
The above example is good if message is not be send and updated to all the clients. In my case I have several APIs to be called whenever a data is changed:
Like Bank Transaction is done, I have to update ledger and several other reports at client side. But I don't see any option to pass Json.
Not finding exactly how to do this so that WebAPI gets refreshed everytime a change is there in the database.
As far as I understood, here "chat" is the endpoint which will be called from the frontend.
In this case what will happen to the endpoint I have created so far. Have a look at the below code example:
This api is to be called every time an entry is done:
public async Task<object> GetMarket(string marketshortcode)
{
Markets market = new Markets(marketshortcode);
return market.GetMarket();
}
and this the entry:
[Authorize]
[HttpPost]
public async Task<object> sellCurUser([FromBody] SellCur model)
{
if (model != null)
{
SellCurUser suser = new SellCurUser();
suser.sellcur = model;
my addition code...
}
return ....
}
There are several more endpoints which needs to be called at certain update/creation.
Now the point is how these apis will be changed or even not changed at all.
Do anyone have any example to understand it simply.

Admin on rest - RestClient & Create operation return params + id instead of response.data

In the two REST client (simple & json) provided in the module, on the CREATE operation we have this :
case CREATE:
return { data: { ...params.data, id: json.id } };
params is the data sended by the client to the server, json is the data that the server returned.
Why is better to return client data than server response ?
In the two REST clients, we assume that we can't prejudge what the server will return to us, but the new element's id.
And we're assuming that the data provided for creation will allow the correct display of the list.
But of course, if this is not your case (i.e. you know exactly what the server will return, including some information not requested at creation), you can decorate an existing client or create your own.

Web API 2 - Unity IOC - Shared instance per request variable

I am using web api with unity IOC.
web api client passes client-id in request header and based on this value dependencies are resolved to create a external dll's method instance.
creation of this instance take around 6-7 seconds which is creating performance issues in web api.
What I want is to prevent instance creation for call with same client-id in header.
This is how I have implemented till now:-
//========================== ArchiveFactory ==========================
ArchiveFactory archiverFactory = (HttpRequest httpRequest) =>
{
container.RegisterType<IArchive, Archive>("Archive",
new HierarchicalLifetimeManager(),
new InjectionConstructor(
new ResolvedParameter<IStoreClient>(),
Helper.GetArchiveContext(httpRequest))
);
return container.Resolve<IArchive>("Archive");
};
container.RegisterInstance(archiverFactory);
To be specific in my requirement - I am calling amazon services to retrieve images and there is a corporate dll which invokes amazon.
You can use caching mechanism at the controller/API layer(e.g Strathweb.CacheOutput.WebApi2) and you can decorate the controller method like this below. It's can cache based on parameter so if request comes in with same parameter, it will return results from cache.
[HttpGet]
[Route("")]
[CacheOutput(ServerTimeSpan = 60, ExcludeQueryStringFromCacheKey = true)]
public IHttpActionResult GetProducts(string clientId)
{
var product = new List<Product>();
return Ok(product);
}
Also, you might want to check the class constructor that you are trying to instantiate for issues that is taking it too slow. You may want to consider using lazy loading too if that will apply.

Resources