2016-12-20 20 views
0

ここでは、Python内のさまざまな変数の寿命について、既に質問と回答がありますが、アプリケーションスコープの点でdjango環境にどのように変換するのかを探しています。エンドポイントスコープ。djangoのクラス変数とインスタンス変数の有効期間と有効範囲

# This class should be global to the entire application and only 
# load when the server is started. 

class GlobalCacheobject): 
    _cache = {} 

    @classmethod 
    def fetch(cls): 
     return cls._cache 

    @classmethod 
    def flush(cls): 
     cls._cache = {} 

    @classmethod 
    def load_cache(cls, files_to_load_data_from): 
     for file in files_to_load_from: 
      cls._cache[file] = <load file and process its data into an entry> 

my_cache /モデル/ InstanceCache:ここで私が作っていると私はそれが私が

my_cache /モデル/ GlobalCache.pyにそれを期待していますように動作することを保証するために何をしたいのシンプルなバージョンがあります.py:

from .GlobalCache import GlobalCache 

# This class will contain a reference to the global cache and use it to look 
# up entries. 

class InstanceCache(object): 
    def __init__(self, name=None): 
     self._name = name 
     self._cache = GlobalCache.fetch() 

    def fetch_file_data(self, file_name): 
     cache_entry = self._cache.get(file_name, None) 
     if cache_entry is None: 
      raise EntryNotFoundException() 
     return ReadOnlyInterfaceObject(cache_entry) 

意図はGlobalCacheは、サーバを実行している限り持続しますcls._cache値を持っていることです。 GlobalCache.flush()を呼び出すと、トラッキングしていたデータへのグローバル参照が削除され、GlobalCache.load(files_to_load_from)を呼び出すと、そのデータの新しいインスタンスが作成されます。

InstanceCacheオブジェクトは、現在のバージョンのデータへの参照を保持し、元のファイル名で識別される異なるデータセットの読み取り専用オブジェクトを返します。

私のテストでは、実際にInstanceCacheオブジェクト自体は持っていませんが、これはうまくいくようです。グローバルキャッシュを読み込み、読み込み専用のオブジェクトを取得してからグローバルをフラッシュし、新しいデータでロードすることができます。元の読み取り専用オブジェクトは元々ロードされていた値を返しますが、新しい要求は新しいデータ値を使用します。

私が確認したいのは、サーバーが動作していて、かつ、flush()とload_cache()への直接呼び出しでのみデータを変更する限り、GlobalCacheが存在することです。そして、私がエンドポイントにヒットしてInstanceCacheを作成すると、元のデータが存在するかぎり、元のデータへの参照が保持されます。エンドポイントでの実行が完了すると、グローバルキャッシュへの参照を削除して範囲外になることが予想されますが、最後のキャッシュであれば、それはなくなり、新しい/現在のデータだけが保持されます。それが問題なら、私はPython 2.7.6とdjango 1.5.12を実行しています。アップグレードが必要なソリューションも同様に役立つかもしれませんが、それは私のための即時の選択肢ではありません。

答えて

2

ここの答えは多分ですが、それはまた、あなたがdjangoを実行するために使用しているアプリケーションサーバー(マルチプロセスを実行している場合)に大きく依存します。

したがって、一般的に言えば、GlobalCacheは、キャッシュされたコンテンツを、初期化後のプロセスの存続期間にわたって保持します。

しかし、InstanceCacheは、それ以上参照がなくなってからしばらくしてガベージコレクションされることが保証されています。ガベージコレクションは深い分野であり、多くの場合、アルゴリズムを扱うチームが存在するため、正確なシナリオに入ることはおそらくSOの答えの範囲外です。 Pythonの普及した実装はpypyであり、pypy hereで使用されているガベージコレクションについて詳しく読むことができます。

しかし、ほとんどのアプリサーバーは複数のプロセスであることに注意してください。 uwsgiとgunicornは両方とも、要求を処理するために子プロセスをスピンアップします。したがって、GlobalCacheがプロセスのシングルトンであっても、それぞれが独自のGlobalCacheを持ついくつかのプロセスが存在する可能性があります。そして、このGlobalCacheは、プロセスが終了すると最終的にガベージコレクション/クリーンアップされます。 uwsgiとgunicornは、通常、子プロセスがいくつかのHTTP要求を処理した後、子プロセスを強制終了します。

+0

情報の良いビット..子プロセスが、GlobalCacheの独自のバージョンを持っていて、それが作成されて破壊されるのではないでしょうか?そして、ガベージコレクションのパスが作られたときには、それがその生涯の側面を離れてしまうという面白さを残しても大丈夫です。私は何かを残してメモリリークが発生するのを心配していました。 – James

+0

はい、 'GlobalCache'はプロセスシングルトンになり、プロセスごとに1回発生します。アプリケーションサーバーの素晴らしいところは、メモリリークがあっても、N回のリクエスト後にプロセスが終了することです。理想的ではありませんが、少なくとも役立ちます。 – 2ps

関連する問題