2017-03-08 30 views
5

Flaskアプリケーションでページにアクセスするときにカウンタを増やしたいとします。 2人のユーザーがページにアクセスした場合、カウントは2ずつ増加するはずです。以下を試しましたが、カウントは常に1です。アクセスごとに値を増やすにはどうすればよいですか?Flaskビューへのアクセスごとにインクリメントカウンタを設定する

@app.route('/count') 
def make_count(): 
    count = 0 
    value = count + 1 
    return jsonify(count=value) 

答えて

7

同時にカウントするのは困難です。カウントが0であると仮定します。十分な間隔で2人のユーザーが両方のエンドポイントにヒットした場合、それぞれ0の値を取得し、1に増やして戻します。 2人のユーザーがエンドポイントにヒットしますが、結果の数は2ではなく1になります。これを回避するには、(1つのプロセスで一度に実行できる操作のように)アトミックにインクリメントするデータストアを使用する必要があります。

単純なPython globalを使用することはできません。これは、WSGIサーバーが複数のプロセスを起動するため、それぞれ独自のグローバルコピーを持つためです。反復された要求は、異なるプロセスによって処理される可能性があり、その結果、異なる非同期値が発生します。

最も簡単な解決策は、Python multiprocessing.Valueです。これにより、プロセスが値の作成後に生成される限り、プロセス間で共有された値へのアクセスが同期されます。

from flask import Flask, jsonify 
from multiprocessing import Value 

counter = Value('i', 0) 
app = Flask(__name__) 

@app.route('/') 
def index(): 
    with counter.get_lock(): 
     counter.value += 1 

    return jsonify(count=counter.value) 

app.run(processes=8) 
# access http://localhost:5000/ multiple times quickly, the count will be correct 

は、まだいくつかの注意点があります。

  • データは限りマネージャーが生きているとして存続します。サーバを再起動すると、カウンタもリセットされます。
  • アプリケーションプロセスが複数のマシンに分散されている場合、共有メモリはグローバルと同じ問題を抱えます。ローカルマシンでのみ同期され、ネットワークでは同期されません。

実際のシナリオでは、Redisははるかに堅牢なソリューションです。サーバーはWebアプリケーションから独立しており、永続性のオプションがあり、アトミック・インクリメントを実行できます。また、アプリケーションの他の部分(キャッシングなど)にも使用できます。

関連する問題