4

C10Kの問題は、従来の Web サーバーの最大容量が最大 10k の同時制限を持つことを示しています。

nginx などのサーバーは、スレッドの代わりにシングルスレッド モデルと非同期通信を使用して、着信要求を処理します。AFAIK Geventは、スレッドの代わりにグリーンレット(同じスレッド内で切り替え可能な実行コンテキスト) を使用します。

これにより、2 つの質問が生じます (ここでも、非同期モデルを使用していると仮定します。gevent と gunicorn を考えてください)。

  1. そのような状況では: リソースを浪費するリスクはありますか? greenlet ベースのサーバーについては、さらに質問を制限します。リソースの占有は実際にはミューテックス ロックであると仮定します (ミューテックス ロックは、現在のプロセスではありませんが、現在のスレッドをブロックします。しかし、現在はマルチスレッド アーキテクチャではありません。グリーンレットを使用する場合...私は間違っていますか?)。
  2. greenlet ベースのアーキテクチャ (またはスレッド化されたアーキテクチャ) を使用していない場合: Websocket はサーバーにどのように実装されていますか?

そして、追加の質問が Django に当てはまります。

  1. ビュー内になく、ビュー パラメータに直接アクセスできない場合、現在のリクエストを特定するにはどうすればよいですか? (カスタムミドルウェア内に入力された)を使用して現在のスレッドを識別するという悪い習慣がありthreading.localましたが、当時は非スレッドアーキテクチャを考慮していませんでした(私のコードは、「1つのリクエスト(意味)」と言える限り問題ありませんでした) 1 つのスレッド」)。

requestこれは、フォームが(鉱山/カスタム)フィールドのメソッドを呼び出したときに現在のものを特定するclean()(つまり、現在のリクエストに応じてデータに対して値を検証する)場合に役立ちます。ただし、10k の制限を超える同時要求があり、非同期 (非スレッド化) アプローチを使用している場合、このメソッドは失敗します。

4

1 に答える 1

3

(編集 - gevent.monkey.patch_all() - wsgy.py スクリプト ファイルで実行 - 自動的にスレッド ローカルにパッチを適用して greenlet ローカルにするため、Werkzeug を使用するこの代替手段は GEvent (または Gevent ワーカーを使用する GUnicorn) には必要ありません。 、GEventなしでグリーンレットを使用する場合、このソリューションが必要になる場合があります)

Flask Frameworkを思い出すと、答えが見つかりました。

Flask は、「グローバルに」多くのオブジェクトをサポートし、オブジェクトのように「見える」フレームsessionワークrequestですthreading.local。主な違いは、それらがスレッド ローカルではなくコンテキスト ローカルであることと、コンテキストが現在の実行スタックであることです。

スレッドには独自のコンテキストがあります (したがって、スレッド理論について読むときのコンテキスト スイッチの概念です)。プロセスには、スレッド (およびメイン スレッド) を含むコンテキストがあります。

これまでのところ、私たちが知っている理論では、プロセスにはスレッドが含まれ、スレッドには独自の実行コンテキストが含まれます。スレッドが独自のデータ コンテキストを作成できない限り、データは常に共有されます。ここで、スレッド ローカル (変数/データ)の概念が登場します。

しかし、この同時実行の概念に対処し、C10K の問題を考慮すると、対応するコンテキスト スイッチを使用して複数のブロック スレッドを使用する代わりに、1 つのスレッドでの非同期実行が優先されました (特に、デフォルトの python distr0 に GIL がある python に関して)。Greenlet は同じスレッド スイッチング コンテキストとして作成され、階層が変更されました。

Process 1--* thread 1--* greenlet (and now the requests are here)

そのため、Greenlets の概念は、 Geventのようなサーバーの Python で作成および実装されました。リクエストはスレッドにバインドされなくなったため、スレッド ローカル データを使用できなくなりました (つまり、同じスレッドローカル コンテキストを共有し、データを競合する可能性があります)。

現在、コンテキスト自体が greenlet であり、スレッド ローカルではなくコンテキスト ローカルの概念が必要です。

では、Flask はリクエストごとにデータを分離するコンテキスト ローカルをどのように使用するのでしょうか? (例: セッション、リクエスト)。コンテキストに依存しない分離に対する答えは次のとおりです。

Werkzeug のコンテキスト ローカル

Werkzeug と Flask の作成者は同じです。Werkzeug はフレームワークではなく、任意の WSGI フレームワーク( Djangoなど)で使用できる一連のユーティリティにすぎません。フレームワーク自体は Flask であり、実際には Werkzeug のユーティリティに依存しています。

Werkzeug のコンテキスト ローカルは、greenlet 固有のデータを保存し、スレッドローカル:

#a python module for my django project where I define
#a custom field class which statically needs to know the
#current request.

#I was using, instead, a threadlocal. The usage is THE SAME.
#the main difference is that threads are GCed, while contexts
#not necessarily, so you must ALWAYS release them explicitly
#using release_local, for the current context.

#this code below used to have `threading.local` instances
#instead of `werkzeug.local.Local` instances.

#as I said before, assigning data works like before, but
#the main difference is when releasing the data.

from werkzeug.local import Local, release_local

class AutocompleteField(object):

    DATA = Local()

    @staticmethod
    def set_request(request):
        AutocompleteField.DATA.request = request

    @staticmethod
    def unset_request(request):
        release_local(AutocompleteField.DATA)

    @staticmethod
    def get_request():
        try:
            return AutocompleteField.DATA.request
        except AttributeError as e:
            return None
于 2014-07-16T20:50:37.790 に答える