5

mod_wsgi の下で最初の django アプリケーションを次のようにロールアウトしています。

`WSGIDaemonProcess our-appname processes=6 threads=15'`

また、Python コードとそれが使用する Redis および Postgres ライブラリをスレッドセーフにする必要があるかどうかについても議論しています。

mod_wsgi のドキュメントを読んでわかることから、Apache ワーカーは複数のApacheスレッドでリクエストを処理していますが、Pythonコードはすべての意図と目的のためにシングルスレッドになっています。mod_wsgi ドキュメントに、「注意してください!!グローバル データとスレッド セーフについて心配する必要があります!」という警告が表示されません。しかし、明示的な「スレッドが存在しないことを心配しないでください」もありません。

私たちの Python コードでは、明示的にスレッドを使って何もしていません。

しかし、ここにいる一部の人々は、私たちがそれで実行しthreads=15ているため、現在マルチスレッドの世界にいるという意見を持っています.

ここで実際に何が起こっているのかを誰かが明確にすることはできますか? 私たちの Python コードは、以前にはなかった同じデータを介した複数の実行スレッドの影響を受けるようになりましたか?

4

3 に答える 3

6

はい、明らかにマルチスレッドアプリを実行しており、グローバルやクラス属性などに注意しないと問題が発生します

何かをグローバルに保持する必要がある場合は、スレッド ローカル ストレージに保持します。

これはmodwsgi doc、Building_A_Portable_Applicationからの引用です。

3. アプリケーションは再入可能である必要があります。つまり、簡単に言えば、同時に複数のスレッドから同時に呼び出すことができる必要があります。リクエストの存続期間中存在する必要があるデータは、スタックベースのデータ、スレッドローカルデータとして保存するか、WSGI アプリケーション環境にキャッシュする必要があります。実際のアプリケーション モジュール内のグローバル変数は、この目的には使用できません。

したがって、十分に警告されていると思います。

于 2012-10-25T19:27:17.357 に答える
1

Python インタープリターは、特に参照カウントのためにスレッドセーフではないため、スレッドは同じプロセス空間で同時に Python オブジェクトにアクセスできません。インタープリターは GIL (グローバル インタープリター ロック) によって保護されているため、誤ってまたは意図的にこれを回避するように mod_wsgi を構成する方法はありません。したがって、同時スレッドが同じメモリ オブジェクトにアクセスするリスク (メモリ ロックなど) に伴う、特にトリッキーなスレッド セーフの問題について心配する必要はありません。

gevent バッカーを備えた gunicorn などの一部の Web サーバーは、メモリ内に複数のスレッドを同時に保持するため、個々のプロセスを I/O (データベース アクセス、ネットワーク アクセスなど) でブロックする必要はありません。これは、mod_wsgi にも当てはまります。ただし、これはアプリケーション コードで心配する必要がないように実装されています。アプリケーションがマルチプロセッシングで安全に使用できる場合は、この種の限定された非同時スレッドでも安全に使用できるはずです。モデル。

もちろん、グローバル変数を使用したり、実行中にアプリケーションの一部を動的に編集したりすることはできませんが、Django でそのようなことを行うと、スレッド化について心配する前に問題が発生します。Django やその他の Web フレームワークは、そのモデル内のスレッド/プロセスの安全性について心配することなく、データがリクエストとして渡され、レスポンスとして渡されるように設計されています。

Web アプリケーションと同様に、データ ストア (特にデータベース エントリ) への同時アクセスについて心配する必要があります。データベースへのアクセスに関しては、防御的にコーディングします。

于 2012-10-25T19:59:56.087 に答える
1

アンドリューの答えは少し誤解を招くと思います。CPython (Jython や PyPy などの他の Python 実装があることに注意してください) が GIL を持っているという事実は、コードがスレッドセーフであることを心配する必要がないという意味ではありません! GIL のため、1 つのプロセスで 2 つのスレッドを同時にアクティブにすることはできません。ただし、並列処理は、スレッドを定期的に切り替えることによってシミュレートされます。このようなコンテキストの切り替えは、プログラムの実行中にいつでも発生する可能性があります。foo例として、「グローバル」変数を含むモジュールがある場合x、次のメソッドは、同じメソッドを実行するスレッドの数に応じて、2、3、4、... のいずれかを出力する可能性があります。

def bar():
    foo.x = 1
    # a context switch might happen here!
    foo.x = foo.x + 1
    # or here!
    print(foo.x)

実際には、max を使用するように mod_wsgi を構成できます。1 スレッド。そして、スレッドセーフについて心配する必要はありません。しかし、プログラムの正確性は Web サーバーの構成に依存するため、これは非常に望ましくない状況です。

于 2014-03-01T19:20:17.690 に答える