In this article, the master process is referred to the signal processing function, where two of the signals are more interesting.
SIGHUP: Used for hot update (RELOAD) applications
SIGUSR2: For online upgrade (upgrade on the fly) Gunicorn below for a detailed look:
SIGHUP:
Reload The configuration, start the new worker processes with a new configuration and gracefully shutdown Older workers.
The sigup corresponding signal processing function is arbiter.reload. The simplified core code is as follows:
1 defReload (self):2Old_address =self.cfg.address3 4 #Reload conf, reload configuration5 self.app.reload ()6 Self.setup (Self.app)7 8 #Reopen log Files9 self.log.reopen_files ()Ten One #Do we need to change listener?, handling the situation of monitoring port changes A ifOld_address! =self.cfg.address: - #Close all listeners -[L.close () forLinchSelf . LISTENERS] the #Init new Listeners -Self. LISTENERS =create_sockets (self.cfg, Self.log) -Listeners_str =",". join ([STR (L) forLinchSelf . LISTENERS]) -Self.log.info ("Listening at:%s", Listeners_str) + - #spawn new workers, starting a fresh worker (quantity and type from the new configuration) + forIinchRange (self.cfg.workers): A Self.spawn_worker () at - #manage workers, this will kill the original worker. -Self.manage_workers ()
Mentioned in the above reference, will "
Elegance(graceful) to kill the old worker process. The implementation is also very simple, arbiter for each fork out of the worker process to set a self-increasing "worker_age", the smaller the worker, this property indicates that the older worker. In Manage_workers, if the number of worker processes that have been started is greater than the number in the configuration, the older worker process is killed. The code is as follows
1 defmanage_workers (self):2 """3 Maintain the number of workers by spawning or killing4 As required.5 """6 ifLen (self. Workers.keys ()) <self.num_workers:7 self.spawn_workers ()8 9Workers =Self . Workers.items ()TenWorkers = sorted (workers, key=LambdaW:w[1].age)#Sort by worker's age order One whileLen (Workers) > Self.num_workers:#Num_workers is the number of worker configured A(PID, _) =workers.pop (0) -Self.kill_worker (PID, signal. SIGTERM)
SIGUSR2
Upgrade The Gunicorn on the fly. A separate
term signal should is used to kill the old process.
The corresponding signal processing function is arbiter.reexec, the function will fork out the new master-workers process, but will not affect the original Master,worker process, so the above mentioned need to kill the original process.
1 defreexec (self):2 """3 relaunch the master and workers.4 """5 ifSelf.reexec_pid! =0:6Self.log.warning ("USR2 signal ignored. Child exists.")7 return8 9 ifSelf.master_pid! =0:TenSelf.log.warning ("USR2 signal ignored. Parent exists") One return A -Master_pid =os.getpid () -Self.reexec_pid =os.fork () the ifSelf.reexec_pid! =0: - return - - self.cfg.pre_exec (self) + -Environ =self.cfg.env_orig.copy () +FDS = [L.fileno () forLinchSelf . LISTENERS] Aenviron['GUNICORN_FD'] =",". join ([STR (FD) forFdinchFDS]) # Some environment variables are set to distinguish between starting gunicorn normally or restarting with fork. atenviron['Gunicorn_pid'] =Str (master_pid) - -Os.chdir (self. start_ctx['CWD']) - - #exec the process using the original environnement -Os.execvpe (self. Start_ctx[0], self. start_ctx['args'], environ)
Below do the experiment, two terminal, terminal 1th running code, Terminal 2nd sends a signal.
Step1: Terminal 1th start Gunirorn:gunicorn-w 2 Gunicorn_app:app, terminal 2nd looks at the Python process:ps-ef | grep python, 1 terminal output [2017-01-19 15:21:23 +0000] [6166] [info] starting gunicorn 19.6.0[2017-01-19 15:21:23 +0000] [6166] [info] listening at: http:// 127.0.0.1:8000 (6166) [2017-01-19 15:21:23 +0000] [6166] [info] using worker : sync[2017-01-19 15:21:23 +0000] [6171] [info] booting worker with pid: 6171[2017-01-19 15:21:23 +0000] [6172] [info] booting worker &NBSP;WITH&NBSP;PID:&NBSP;6172&NBSP;2 Terminal Output hzliumi+ 6166 5721 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6171 6166 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app: apphzliumi+ 6172 6166 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/local/ bin/gunicorn -w 2 gunicorn_app:app can see that
the PID of the master process is 6166 , then the PID of the two worker processes is 6171, 6172, respectively. The following PID is required for master process
Step2: Terminal 2nd sends a signal:KILL-SIGUSR2
6166 , and then view the Python process 1 terminal append output [2017-01-19 15:27:08 +0000] [6166] [info] handling Signal: usr2[2017-01-19 15:27:08 +0000] [6629] [info] starting gunicorn 19.6.0[2017-01-19 15:27:08 +0000] [6629] [info] listening at: http:// 127.0.0.1:8000 (6629) [2017-01-19 15:27:08 +0000] [6629] [info] using worker : sync[2017-01-19 15:27:08 +0000] [6634] [info] booting worker with pid: 6634[2017-01-19 15:27:08 +0000] [6635] [info] booting worker &NBSP;WITH&NBSP;PID:&NBSP;6635&NBSP;2 Terminal Output hzliumi+ 6166 5721 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6171 6166 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6172 6166 0 15:21 pts/0 00:00:00 /usr/bin/python /usr/ Local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6629 6166 3 15:27 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6634 6629 0 15:27 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6635 6629 0 15:27 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:app As can be seen from Terminal 1th, the basic is to restart the Gunicorn, but from terminal 2nd output can be seen,
The new master process (PID 6629) is a child of the old master process (PID 6166)
Step3: Terminal 2nd sends a signal:kill-sigterm
6166 , wait a few seconds to view the Python process: 1 terminal append output [2017-01-19 15:29:42 +0000] [6166] [info] handling signal: term[2017-01-19 15:29:42 +0000] [6171] [info] worker exiting (pid: 6171) [2017-01-19 15:29:42 +0000] [6172] [info] worker exiting (pid: 6172) [2017-01-19 15:29:42 +0000] [6166] [info] shutting down: Master[2017-01-19 15:29:42 +0000] [6629] [INFO] Master has been PROMOTED.&NBSP;2 Terminal Output hzliumi+ 6629 1 0 15:27 pts/ 0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6634 6629 0 15:27 pts/0 00:00:00 /usr/bin/python /usr/local/bin/gunicorn -w 2 gunicorn_app:apphzliumi+ 6635 &nbsP;6629 0 15:27 pts/0 00:00:00 /usr/bin/python /usr/local /bin/gunicorn -w 2 gunicorn_app:app can see that the old master process (6166) and its fork-out worker subprocess (PID is 6171, 6172) has been killed references:http://docs.gunicorn.org/en/stable/signals.html
Gunicorn signal Processing (SIGHUP,SIGUSR2)