uwsgi + nginxでpythonアプリケーション(フラスコ+ redis-py)を実行し、aws elasticache(redis 2.8.24)を使用しています。
アプリケーションの応答時間を改善しようとしているときに、高負荷 (1 秒あたり 500 リクエスト/loader.io を使用して 30 秒間) でリクエストが失われていることに気付きました (このテストでは、負荷のない単一のサーバーのみを使用しています)バランサー、1 つの uwsgi インスタンス、4 つのプロセス、テスト目的で)。
もう少し詳しく調べたところ、この負荷がかかると、ElastiCache への一部のリクエストが遅くなることがわかりました。例えば:
- 通常の負荷: cache_set 時間 0.000654935836792
- 高負荷: cache_set time 0.0122258663177 これはすべてのリクエストで発生するわけではなく、ランダムに発生します..
私の AWS ElastiCache は、cache.m4.xlarge の 2 つのノードに基づいています (デフォルトの AWS 構成設定)。過去 3 時間に接続された現在のクライアントを表示します。
現在 14 台のサーバー (そのうちの 8 台は XX RPS の高トラフィックでこのクラスターを使用) であるため、これは意味がないと思います。クライアント レートがはるかに高くなると予想されます。
uWSGI 構成 (バージョン 2.0.5.1)
processes = 4
enable-threads = true
threads = 20
vacuum = true
die-on-term = true
harakiri = 10
max-requests = 5000
thread-stacksize = 2048
thunder-lock = true
max-fd = 150000
# currently disabled for testing
#cheaper-algo = spare2
#cheaper = 2
#cheaper-initial = 2
#workers = 4
#cheaper-step = 1
Nginx は、unix ソケットを使用した uWSGI への単なる Web プロキシです。
これは、redis への接続を開く方法です。
rdb = [
redis.StrictRedis(host='server-endpoint', port=6379, db=0),
redis.StrictRedis(host='server-endpoint', port=6379, db=1)
]
これは、たとえば値を設定する方法です。
def cache_set(key, subkey, val, db, cache_timeout=DEFAULT_TIMEOUT):
t = time.time()
merged_key = key + ':' + subkey
res = rdb[db].set(merged_key, val, cache_timeout)
print 'cache_set time ' + str(time.time() - t)
return res
cache_set('prefix', 'key_name', 'my glorious value', 0, 20)
これは私が値を取得する方法です:
def cache_get(key, subkey, db, _eval=False):
t = time.time()
merged_key = key + ':' + subkey
val = rdb[db].get(merged_key)
if _eval:
if val:
val = eval(val)
else: # None
val = 0
print 'cache_get time ' + str(time.time() - t)
return val
cache_get('prefix', 'key_name', 0)
バージョン:
- uWSGI: 2.0.5.1
- フラスコ: 0.11.1
- redis-py: 2.10.5
- レディス: 2.8.24
したがって、結論は次のとおりです。
- 14 台のサーバーが接続され、それぞれに 4 つのプロセスがあり、それぞれが redis クラスター内の 8 つの異なるデータベースへの接続を開くと、AWS クライアントの数が少なくなる理由
- リクエストの応答時間が長くなる原因は何ですか?
- 高負荷時の ElastiCache や uWSGI のパフォーマンスに関するアドバイスをいただければ幸いです。