2017-04-22 3 views
0

私はCassandraに接続するFlaskアプリを持っています。このアプリケーションをGunicornの下で実行し、Gunicornをフラスコスクリプトコマンドpython manage.py gunicornとして起動すると、アプリケーションはハングします。しかし、同じアプリをコマンドラインでgunicorn manage:appとして実行すると、成功します。どうして?GunicornとFlaskでCassandraに接続すると、なぜ吊り下げられますか?

答えて

2

説明

Gunicornは着信要求を処理するためにワーカーをフォークします。 Cassandraセッション(接続プール)が、より前にに作成されている場合(たとえば、アプリケーションファクトリパターンを使用したアプリケーション作成中)、Cassandraを使用すると問題が発生します。 DataStaxでは、各作業者が独自のセッションを取得することを推奨しています。の後にセッション作成を延期する必要があります。フォーク。 これは、GunicornとFlaskをカスタムアプリケーションとしてバンドルすると問題になりますが、おそらくコマンドライン上にあります.Gunicornは、Flaskアプリケーションを作成する前に、はっきりと初期化してforkすることができます。

例は、手動で真=悪いに=悪いFalseの変更、2つの動作を参照してください。

from cassandra.cluster import Cluster 
from flask import Flask 
from flask_script import Command, Manager 
from gunicorn.app.base import BaseApplication 
from gunicorn.six import iteritems 


class CassandraClient: 
    def __init__(self, bad=False): 
     self.session = None 
     self.cluster = None 
     if bad: 
      self.connect() 

    def connect(self): 
     self.cluster = Cluster(['127.0.0.1']) 
     self.session = self.cluster.connect('keyspace') 

    def execute(self): 
     if not self.session: 
      self.connect() 
     query = ''' 
      select now() 
      from system.local 
     ''' 
     return self.session.execute(query)[0] 


class GunicornApp(BaseApplication): 
    ''' 
    Bundle Gunicorn and Flask together, so that we can call it as a 
    flask-script command. 

    http://docs.gunicorn.org/en/stable/custom.html 
    ''' 

    def __init__(self, app, options=None): 
     self.options = options or {} 
     self.application = app 
     super(GunicornApp, self).__init__() 

    def load_config(self): 
     config = dict(
      [(key, value) for key, value in iteritems(self.options) 
      if key in self.cfg.settings and value is not None]) 
     for key, value in iteritems(config): 
      self.cfg.set(key.lower(), value) 

    def load(self): 
     return self.application 


class GunicornCommand(Command): 
    ''' 
    Modeled off of flask_script.Server 
    ''' 
    def __init__(self, app, options): 
     self.app = app 
     self.options = options 

    def __call__(self, *args, **kwargs): 
     GunicornApp(self.app, self.options).run() 


app = Flask(__name__) 
app.cassandra = CassandraClient() 
@app.route('/') 
def hello(): 
    return str(app.cassandra.execute()) 


if __name__ == '__main__': 
    manager = Manager(app) 
    gunicorn_options = { 
     'bind': '127.0.0.1', 
     'port': 8000, 
     'workers': 4 
    } 
    manager.add_command("gunicorn", GunicornCommand(app, gunicorn_options)) 
    manager.run() 

バージョン

Flask==0.12.1 
Flask-Script==2.0.5 
gunicorn==19.7.1 
cassandra-driver==3.8.1 

参照

関連する問題