Hi, I'm experiencing a strange problem. I have the following simple/sample Flask application:
# from __future__ import print_function
import requests
from flask import Flask
PORT = 6556
app = Flask(__name__)
@app.route('/')
def index():
j = {'data': 1}
print('INDEX CALLING API')
response = requests.post('http://localhost:{}/fake_api'.format(PORT), json=j)
print('INDEX CALLED API')
return response.text
@app.route('/fake_api', methods=['POST'])
def fake_api():
print('FAKE_API CALL RECEIVED')
return 'Ok, it works'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=PORT, debug=True)
Basically, what I'm simulating is calling a url (http://localhost:6556/
) and have the route call with requests another url of the same flask app (http://localhost:6556/fake_api
). Being quite banal, it works fine if I simply start the app with python server.py
.
The problem is that when I try to run the server with gunicorn like this
gunicorn -b 0.0.0.0:6556 server:app
the application hangs indefinitely on the request. In fact it prints INDEX CALLING API
and then halts.
I've experienced the same problem with uWSGI. Any idea?
The default type of worker for gunicorn is the sync worker, and the default number of workers is one. sync workers only support a single request at a time:
The most basic and the default worker type is a synchronous worker class that handles a single request at a time. This model is the simplest to reason about as any errors will affect at most a single request.
None of those defaults are being changed here. So you're trying to make a second request, but only one request is supported. Thus gunicorn blocks waiting for the first request to finish before handling the second---which can't happen because the first request is blocked waiting for the second request to finish. You'll need to use a different worker type or number of workers, or use a mechanism supplied by your framework to make an in-app request without spawning a new HTTP socket request (e.g., Pyramid's subrequest).
Ok, thanks. I got it working with:
# pip install gevent
gunicorn -b 0.0.0.0:6556 -k gevent server:app
Most helpful comment
The default type of worker for gunicorn is the sync worker, and the default number of workers is one. sync workers only support a single request at a time:
None of those defaults are being changed here. So you're trying to make a second request, but only one request is supported. Thus gunicorn blocks waiting for the first request to finish before handling the second---which can't happen because the first request is blocked waiting for the second request to finish. You'll need to use a different worker type or number of workers, or use a mechanism supplied by your framework to make an in-app request without spawning a new HTTP socket request (e.g., Pyramid's subrequest).