Gunicorn Version :20.x

def app(environ, start_response) :
        data = b"Hello, World! \n"
        start_response("200 OK", [("Content-Type"."text/plain"),
            ("Content-Length".str(len(data)))
        ])

        return iter([data])
Copy the code

1. Gunicorn entry point

When using gunicorn as the server, run the following command: gunicorn -w 2 Gunicorn_app :app corresponds to the setup.py entry point in Gunicorn

[console_scripts]
    gunicorn=gunicorn.app.wsgiapp:run
Copy the code

Wsgiapp :run -w 2 gunicorn_app:app

2. Execute the process

2.1. Preparation parameter configuration phase

def run() :
    """\ The ``gunicorn`` command line runner for launching Gunicorn with generic WSGI applications. """
    from gunicorn.app.wsgiapp import WSGIApplication
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
Copy the code

WSGIApplication(init) — > Application(run) — > BaseApplication(init, run) first executes the initialization method of the Base class,

 def __init__(self, usage=None, prog=None) :
        self.usage = usage
        self.cfg = None
        self.callable = None
        self.prog = prog
        self.logger = None
        self.do_load_config()

def do_load_config(self) :
        """ Loads the configuration """
        try:
            self.load_default_config()
            self.load_config() This is an override method of the subclass WSGi Application
            1. Parse () uses argparse to generate the command line arguments. Parse_args () parses parameters 2. Run init of wsGI class to set app app_uri='gunicorn_app:app' 3. Chdir Working directory 4. Loading the configuration: 1. Run -c to specify the file. Or the GUNICORN_CMD_ARGS variable in the system environment; Or the gunicorn.conf.py file in the current directory. 2. If yes, the file is loaded. If no, the input command line parameters are loaded. If both the file and command parameters are configured, the configuration is overwritten by the command parameters. "" "
        except Exception as e:
            print("\nError: %s" % str(e), file=sys.stderr)
            sys.stderr.flush()
            sys.exit(1)

def load_default_config(self) :
        # init configuration 
        self.cfg = Config(self.usage, prog=self.prog) Load the configuration item Settings using the metaclass

def run(self) :
        try:
            Arbiter(self).run()
        except RuntimeError as e:
            print("\nError: %s\n" % e, file=sys.stderr)
            sys.stderr.flush()
            sys.exit(1)
Copy the code

2.2. Perform the run

def run(self) :
        if self.cfg.print_config:
            print(self.cfg) The __str__ method of the config class is executed

        if self.cfg.print_config or self.cfg.check_config:
            try:
                self.load()
            except Exception:
                msg = "\nError while loading the application:\n"
                print(msg, file=sys.stderr)
                traceback.print_exc()
                sys.stderr.flush()
                sys.exit(1)
            sys.exit(0)

        if self.cfg.spew:
            debug.spew()

        if self.cfg.daemon:
            util.daemonize(self.cfg.enable_stdio_inheritance)

        # set python paths
        if self.cfg.pythonpath:
            paths = self.cfg.pythonpath.split(",")
            for path in paths:
                pythonpath = os.path.abspath(path)
                if pythonpath not in sys.path:
                    sys.path.insert(0, pythonpath)
       
        If the preceding condition is not met, execute the parent method directly
        super().run() # Arbiter run method
Copy the code

Arbiter class mainly does several things:

  1. Arbiter.__init__
   self.setup(app) Gunicorn.app.Application instance
   1.Assign some configuration data to the Arbiter attribute2.Set the env environment variable with raw_env self.master_name ="Master"  
Copy the code
  1. Arbiter.run()
self.init_signals()  #Initialize master signal handling. Most of the signals are queued. Child signals only wake up the master
self.LISTENERS = sock.create_sockets(self.cfg, self.log, fds)  Create a socket and listen. Retry the socket up to 5 timesSelf.manage_workers (), the completed task1.Spawn_worker () : spawn_worker (); spawn_worker () : spawn_worker (); Spawn_worker does the following: I. Loads and instantiates the worker_class, i.e., a different worker class II. The parent process forks the child processreturnExecute worker.init_process(), the worker starts to work, and the supporting worker starts to process the request IV. When the worker is finished, sys.exit(0) exit.Copy the code
  1. Workers Sync, EVENTlet, gevent, gEVENT_WSGI, gEVENT_PYWSgi, Tornado, GTHREAD
  2. Init Initializes the parent process PID, address, socket, and CFG
  3. Init_process function
Init_signals () initializes load_wsgi() by calling application run()# Implemented by a subclass, i.e. the concrete worker, handle_REQUEST receives requests and handles them in the same way as Werkzeug.
Copy the code

3. Summary

A master process is created by Gunicorn, and the master process creates the child process and passes in the parent socket. When the process is alive, it loops through accept requests to be processed by the WSGI application.