同時にカウントするのは困難です。カウントが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アプリケーションから独立しており、永続性のオプションがあり、アトミック・インクリメントを実行できます。また、アプリケーションの他の部分(キャッシングなど)にも使用できます。