I am using gunicorn to run my Flask application, however when the Flask application exits because of an error, gunicorn will create a new worker and not exit.
sample Flask application:
$ vim app.py
# main file
import sys
import os
import logging
from flask import Flask
from views import views
def create_app():
app = Flask(__name__)
app_name = os.environ.get('FLASK_APP_NAME', None)
if app_name is None:
logging.error("Failed to load configuration")
sys.exit(2)
app.config['APP_NAME'] = app_name
console = logging.StreamHandler(sys.stdout)
logging.getLogger().addHandler(console)
logging.getLogger().setLevel(logging.INFO)
logging.info("Starting Flask application")
app.register_blueprint(views)
return app
app = create_app()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=False, threaded=True)
$ vim views.py
# views
from flask import request, jsonify, Blueprint
from flask import current_app as app
views = Blueprint('views', __name__)
@views.route("/", methods=["GET"])
def indexz():
return jsonify(app=app.config['APP_NAME'], msg='OK'), 200
I tried using gunicorn's worker_exit server hook:
$ vim gunicorn-config.py
import sys
workers = 2
def worker_exit(server, worker):
sys.exit(2)
# server.halt()
But this just throws an error and continues to spawn workers:
# error when using sys.exit(2)
[2016-12-10 01:28:53 +0000] [11916] [INFO] Booting worker with pid: 11916
ERROR:root:Failed to load configuration
[2016-12-10 01:28:53 +0000] [11915] [INFO] Worker exiting (pid: 11915)
[2016-12-10 01:28:53 +0000] [11915] [WARNING] Exception during worker exit:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 576, in spawn_worker
self.cfg.worker_exit(self, worker)
File "gunicorn-config.py", line 6, in worker_exit
sys.exit(2)
SystemExit: 2
# error when using server.halt()
[2016-12-10 01:30:15 +0000] [12202] [INFO] Booting worker with pid: 12202
ERROR:root:Failed to load configuration
[2016-12-10 01:30:15 +0000] [12197] [INFO] Worker exiting (pid: 12197)
[2016-12-10 01:30:15 +0000] [12197] [INFO] Shutting down: Master
[2016-12-10 01:30:15 +0000] [12197] [WARNING] Exception during worker exit:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 576, in spawn_worker
self.cfg.worker_exit(self, worker)
File "gunicorn-config.py", line 7, in worker_exit
server.halt()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 331, in halt
self.stop()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 378, in stop
self.kill_workers(sig)
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 600, in kill_workers
self.kill_worker(pid, sig)
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 616, in kill_worker
self.cfg.worker_exit(self, worker)
File "gunicorn-config.py", line 7, in worker_exit
server.halt()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 338, in halt
sys.exit(exit_status)
SystemExit: 0
Edit: modified the exit code for my application to: sys.exit(4)
as per https://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L37 . This time the application does not infinitely restart but when there are 2 or more workers, this throws an exception:
[2016-12-10 18:45:52 +0000] [22195] [INFO] Worker exiting (pid: 22195)
Traceback (most recent call last):
File "/usr/bin/gunicorn", line 11, in <module>
sys.exit(run())
File "/usr/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 74, in run
WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
File "/usr/lib/python2.7/site-packages/gunicorn/app/base.py", line 192, in run
super(Application, self).run()
File "/usr/lib/python2.7/site-packages/gunicorn/app/base.py", line 72, in run
Arbiter(self).run()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 218, in run
self.halt(reason=inst.reason, exit_status=inst.exit_status)
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 331, in halt
self.stop()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 381, in stop
time.sleep(0.1)
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 231, in handle_chld
self.reap_workers()
File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 506, in reap_workers
raise HaltServer(reason, self.WORKER_BOOT_ERROR)
gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>
How can I make the application exit without any exceptions being triggered.
这退出了 gunicorn:
sys.exit(4)
For the sake of completeness use standard errcodes: https://docs.python.org/3/library/errno.html#errno.EINTR
so:
import sys, errno
sys.exit(errno.EINTR)
Look at the preload_app option in gunicorn
configuration. This will load your application in the parent. It should then be able to raise an exception and gunicorn
will not start.
I'm using (inside Gunicorn config file) ...
server.halt(reason="DB Connection failed.", exit_status=4)
Sintaxis is here: https://github.com/benoitc/gunicorn/blob/1299ea9e967a61ae2edebe191082fd169b864c64/gunicorn/arbiter.py#L340
And, here the logger:
[2021-07-08 17:16:09 -0400] [44647] [INFO] Reason: DB connection failed.
[2021-07-08 17:16:09 -0400] [44647] [INFO] Master process exiting...
Last line is generated from " on_exit()
"...
def on_exit(server):
...
server.log.info("Master process exiting...")
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.