'What is a lifecycle of Aiohttp application when used together with Gunicorn?

A project I'm working on uses Gunicorn and Aiohttp to implement a web server. It all starts with something like this:

# main.py    

class GunicornApp(gunicorn.app.base.Application):
    def __init__(self, ...):
        ...
    def load_config(self):
        ...
    def load(self):
        return create_aiohttp_app(...)

if __name__ == "__main__":
    GunicornApp(...).run()

where create_aiohttp_app is defined as something like this:

def create_aiohttp_app(...) -> web.Application:
    app = web.Application(...)
    app.router.add_get(...)
    app.on_startup.append(start_app)
    app.on_cleanup.append(stop_app)
    return app

start_app performs certain initialisation actions and then launches an async task which is supposed to execute indefinitely, thus becoming the server's main payload:

async def start_app(web.Application) -> None:
    app["payload_obj"] = PayloadClass(...)
    app["payload_task"] = create_task(app["payload_obj"].run()) # infinite loop inside

stop_app just does some cleanup:

async def stop_app(app: web.Application) -> None:        
    app["payload_task"].cancel()

With all of the above, there are a few things that I would like to understand:

  1. How many times is GunicornApp.load() supposed to be called? Is this called once per Gunicorn worker, or is it called once during the whole lifetime of the Gunicorn application? In other words, how many web.Application are expected to be created?
  2. What's the expected lifetime of a web.Application instance returned by create_aiohttp_app? When is it disposed of? Does it live until the Gunicorn worker executing it stays alive, or can it outlive it?
  3. How many start_app/stop_app cycles can there be for a web.Application instance? Are these methods only called once each or many times?
  4. What exactly is the relationship between Gunicorn workers and web.Application instances? Does web.Application maintain an infinite event loop inside (thus ensuring that it runs forever and app["payload_task"] doesn't go out of scope, or is there something more complex here?


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source