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:
- 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
- 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
- Workers Sync, EVENTlet, gevent, gEVENT_WSGI, gEVENT_PYWSgi, Tornado, GTHREAD
- Init Initializes the parent process PID, address, socket, and CFG
- 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.