5

I have to serve an API that sends multiple requests to other APIs and merge their responses as the output.

What will be the most optimal way to do that? Is this some async await scenario? Appreciate the advice.

from fastapi import FastAPI
import requests

app = FastAPI()

@app.post('/api')
def main_api():
    JScontent = json.loads(request.json())
    input = JScontent['content']
    response1 = requests.post(url1, json={"input":input})
    response2 = requests.post(url2, json={"input":input})
    response3 = requests.post(url3, json={"input":input})
    response4 = requests.post(url4, json={"input":input})

    prediction = fuse_responses(response1, response2, response3, response4)
    return prediction

I am currently using Flask for development, but figured it might not have the capability, or will be a hassle to manage such a scenario, hence, open to changing to FastAPI.

[UPDATE]

Did some digging came across this link. I guess it can be applied similarly to FastAPI? I have no prior experience in async & await so appreciate the validation.

from fastapi import FastAPI


app = FastAPI()

async def send_requests(url, input_):
    res = await app.post(url, input_)
    return res
    

@app.post('/api')
async def main_api():
    JScontent = json.loads(request.json())
    input_ = JScontent['content']

    res1 = await send_requests(url1, input_)
    res2 = await send_requests(url2, input_)
    res3 = await send_requests(url3, input_)
    res4 = await send_requests(url4, input_)

    prediction = fuse_responses(res1, res2, res3, res4)
    return prediction
Jake
  • 2,482
  • 7
  • 27
  • 51
  • 3
    You could create a thread for each request i guess. But please, don't name your variable `input`. input is a built-in function in python. – Joel Apr 17 '21 at 13:15
  • Would u be able to show an example? pardon, still noob at this~ noted on the input, i was just using pseudocodes for a quick example – Jake Apr 17 '21 at 13:17
  • 1
    Here's a few examples to get you started: https://stackoverflow.com/questions/15752973/python-how-can-i-send-multiple-http-requests-at-the-same-time-like-fork – Joel Apr 17 '21 at 13:22
  • Might be helpful https://stackoverflow.com/questions/63872924/how-can-i-send-an-http-request-from-my-fastapi-app-to-another-site-api/ – alex_noname Apr 19 '21 at 07:50

2 Answers2

3

The aggregation of multiple microservice calls can be done by the aggregation pattern mentioned above in both frameworks.

FAST API is a high-performing, asynchronous, non-blocking framework to build API's This is similar to the node framework in the Javascript full-stack world. You can definitely use async callbacks on each of the API calls and aggregate them once you have the results. FAST API is blazingly fast compared to FLASK. If you need a high performant system, FAST API might be a good job. Having said that, always remember that your API will be as performant as the lowest denominator within the API chain. Look at the documentation : https://fastapi.tiangolo.com/advanced/openapi-callbacks/ .

Flask is a reliable, time-tested, synchronous API framework with python. Mulitple enterprises have used flask to build the API's. All the code is written will be executed sequentially unless explicit thread management is used.

https://creativedata.stream/multi-threading-api-requests-in-python/

Do reply if you need additional help or have questions.

  • I am more geared to something more code friendly then manually coding out the multithreads in Flask. I took a look at the FastAPI docs u gave, that page seems more concerned about creating an openapi doc based on callbacks, and not sending multiple requests though. I just updated my post with an async await e.g., do u think this code works as I intended? – Jake Apr 18 '21 at 01:54
  • If you aren't sure if it is going to work, simply test it. If you get a 500 or 4xx error, you know something is wrong. – astrochun Apr 18 '21 at 03:18
1

Yes, using the asynchronous functionality is the correct way of dealing with such kind of problems.

What you're trying to achieve, though, is called AGGREGATOR PATTERN, where one service receives the request and calls all the different services. It is frequent in the case of microserves, where a page contains information that comes from multiple microservices. It is sometimes implemented in the gateway (a.k.a. API AGGREGATION PATTERN), but most of the time I see this pattern in a dedicated service.

Below a couple of links that may be useful:

https://learn.microsoft.com/en-us/azure/architecture/patterns/gateway-aggregation

And here, which uses asynchronous code to achieve what you are trying to achive

https://dzone.com/articles/microservices-aggregator-design-pattern-using-aws

NOTE You can always spawn new threads from the flask app to carry out the requests. Alternatively, you can always create an asynchronous function that will call all the URLs asynchronously, wait for their responses, aggregate them and return the result.

Here's a short tutorial on how you can achieve your goal running asynchronous code from synchronous code.

https://realpython.com/async-io-python/

lsabi
  • 3,641
  • 1
  • 14
  • 26