8

これが可能であるとは思えませんが、ここに問題と提案された解決策があります(提案された解決策の実現可能性がこの質問の目的です):


すべての要求で利用できる必要がある「グローバルデータ」があります。このデータを Riak に保存し、Redis をアクセス速度のキャッシング レイヤーとして使用しています (今のところ...)。データは、それぞれ約 8 KB の約 30 個の論理チャンクに分割されます。

各リクエストは、これらの 8KB チャンクのうち 4 つを読み取る必要があるため、Redis または Riak から 32KB のデータが読み込まれます。これは、読み取る必要があるリクエスト固有のデータに追加されます (これはかなりの量です)。

1 秒あたり 3000 リクエストでさえあると仮定すると (これはライブ サーバーではないため、実際の数値はありませんが、3000ps は合理的な想定であり、それ以上になる可能性があります)、これは、Redis または Riak からの 96KBps の転送を意味します。 -アプリケーションロジックから行われている重要でない他の呼び出し。また、Python はこれらの 8KB オブジェクトの JSON を毎秒 3000 回解析しています。


このすべて、特にデータを繰り返しデシリアライズしなければならない Python はまったくの無駄のように思えます。完全にエレガントな解決策は、デシリアライズされたデータを Python のインメモリ ネイティブ オブジェクトにキャッシュすることです。このすべての「静的」データが古くなったとき。毎秒 3000 回ではなく、数分 (または数時間) に 1 回。

しかし、これが可能かどうかはわかりません。メモリ内のデータをキャッシュするには、「常に実行されている」アプリケーションが現実的に必要です。そして、これはnginx + uwsgi + pythonの組み合わせ(ノードのようなものに対して)には当てはまらないことを知っています.pythonのメモリ内データは、ひどく間違っていない限り、私の知る限り、すべてのリクエストで永続化されません。

残念ながら、これは私が「継承」したシステムであるため、基本テクノロジーに関してあまり多くの変更を加えることはできません。また、Python プロセスの起動と永続化に関して、nginx + uwsgi + python の組み合わせがどのように機能するかについて十分な知識がありません。 Python のメモリ内データ - これは、上記の私の仮定とひどく誤解される可能性があることを意味します!


したがって、このソリューションが機能するかどうかについての直接的なアドバイスと、新しいプロセスの開始とメモリ割り当てに関してnginx + uwsgi + pythonがどのように機能するかを理解するのに役立つ資料への参照は、非常に役立ちます.

PS:

  1. nginx、uwsgi などのドキュメントをいくつか読んだことがありますが、ユースケースごとの影響をまだ完全には理解していません。今後、何らかの進展が見られることを願っています

  2. メモリ内のことがうまくいく場合は、Redis を削除します。これは、前述の静的データのみをその中にキャッシュしているためです。これにより、インプロセスの永続的なメモリ内 Python キャッシュがさらに魅力的になり、システム内の可動部分が 1 つ減り、リクエストごとに少なくとも 4 つのネットワーク ラウンドトリップが減ります。

4

4 に答える 4

3

あなたが提案していることは直接実行可能ではありません。新しいプロセスは制御外でスピンアップおよびスピンダウンできるため、ネイティブPythonデータをメモリに保持する方法はありません。

ただし、これを回避する方法はいくつかあります。

多くの場合、必要なのは1レベルのKey-Valueストレージだけです。また、値用の固定サイズのバッファー(str//オブジェクトとして直接使用できます。そこに必要なものやシリアル化する必要があるもの)だけで十分な場合もあります。その場合、uWSGIの組み込みキャッシュフレームワークが必要なすべてを処理します。bytesbytearraystruct

より正確な制御が必要な場合は、キャッシュがどのように実装されているかを確認し、SharedAreaカスタマイズを行うことができます。しかし、私はそれをお勧めしません。基本的に、ファイルで取得するのと同じ種類のAPIを提供します。ファイルを使用する場合の唯一の本当の利点は、サーバーがファイルの存続期間を管理することです。ファイルを許可しない言語も含め、uWSGIがサポートするすべての言語で機能します。また、後で必要になった場合に、カスタムキャッシュを分散(マルチコンピューター)キャッシュに簡単に移行できます。私はそれらのどれもあなたに関係があるとは思わない。

固定サイズのバッファーを使用せずにフラットなKey-Valueストレージを取得する別の方法は、Pythonのstdlibを使用することanydbmです。Key-Valueルックアップは、可能な限りpythonicです。dictメモリ内に格納されるのではなく、ディスク上のBDB(または同様の)データベースにバックアップされ、メモリに適切にキャッシュされることを除けば、と同じように見えます。ハッシュ表。

他のいくつかの単純なタイプ(sのように、非常に高速にアン/ピクルするもの)を処理する必要がある場合は、intを検討することをお勧めしますshelve

構造が十分に堅固な場合は、トップレベルにKey-Valueデータベースを使用できますが、を介して値にアクセスするctypes.Structureか、を使用して逆/シリアル化しstructます。しかし、通常、それができれば、トップレベルを削除することもできます。その時点で、全体が1つだけ大きくなりStructureますArray

その時点で、ストレージにプレーンファイルを使用できます。それは(の場合)、またはそれとそれmmap(の場合)のいずれかです。ctypesopenreadstruct

または、multiprocessing共有ctypesオブジェクトStructureを使用して、共有メモリ領域から直接アクセスします。

一方、実際にすべてのキャッシュデータを常に必要としているわけではなく、たまに少しずつ必要な場合は、まさにそれがデータベースの目的です。繰り返しにanydbmなりますが、などで十分かもしれませんが、複雑な構造の場合は、ERダイアグラムを作成し、それを一連のテーブルに変換して、MySQLのようなものを使用してください。

于 2013-03-15T23:57:14.597 に答える
0

私は実際に自分で試したことはありませんが、uWSGI のSharedAreaを使用して目的を達成することはできますか?

于 2013-03-15T23:40:58.890 に答える