[FIXED] Keep alive connection between two "request/response" services

Issue

I have a Django app running on a server in Central Europe and a service provider that has a server in the US and a proxy server with a simple Flask app in the US. The Flask app receives requests from the provider and forwards them to his main Django app. You can’t run Django apps in the US.

Currently, my main Django app is under heavy load, so I’m having an issue where requests (including responses) are taking a little longer than usual. Must be less than 3 seconds. We want to optimize the flow.

Currently, communication between Flask and Django apps is a simple Requests.post for each request from the provider opening a new TCP connection. This may take some time between the US and Europe (because of the handshake).

My idea was to create some sort of “persistent” connection between the two apps. This saves a bit of time by eliminating the handshake for each request.
A simple solution is to create an HTTP server on the Django side and some services (with multiple workers) on the Flask side to create and maintain connections, listen to the Flask proxy, It’s about forwarding requests from the Flask proxy to one that’s already open. A TCP connection to your Django app.

It seems a bit overkill, but it’s also something that should already be implemented. Any suggestions on how to solve this problem as elegantly as possible without touching my Flask or Django app (just to change the URL…)?
Thank you for your feedback

Solution

In the end, we created a requests.Session for each thread and stored it to a threading.local object in the Flask app. With this approach, each worker should keep its own session alive. This works, because the wgsi app does not create a new thread for each request, but reuses existing threads from its thread pool.

thread_data = threading.local()

def get_local_session() -> requests.Session:
    """
    Returns session for a current thread. If no session exists yet, a new session is created.
    """
    if not hasattr(thread_data, 'session'):
        thread_data.session = requests.session()
    return thread_data.session

response = get_local_session().post(URL, data=req_body, headers={'Content-Type': req_content_type}, timeout=REQUEST_TIMEOUT)

We had to change keepalive_timeout setting in nginx (which sits in front of the django app) to keep these connections open for long times.

Answered By – Charlestone

Answer Checked By – Marilyn (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published