オープニング思考
システムの一部が別の言語でより良くなるという結論にどのように到達しましたか?パフォーマンスに問題がありますか?これらの問題はどの程度深刻ですか?より高速にできる場合、高速であることが重要ですか?
シングルスレッド非同期
シングルスレッドの非同期性とマルチスレッドの同時性の違い、長所、短所をすでに扱っているいくつかの質問と他のウェブリソースがあります。I / Oが主要なボトルネックであり、多数のリクエストが同時に処理される場合のNode.jsのシングルスレッド非同期モデルの動作について読むのは興味深いです。
Twisted、Tornado、およびその他の非同期モデルは、シングルスレッドをうまく利用しています。多くのWebプログラミングには大量のI / O(ネットワーク、データベースなど)があるため、リモートコールの待機に費やされる時間が大幅に増えます。それは、他のデータベース呼び出しの開始、ページのレンダリング、データの生成など、他のことを行うために費やすことができる時間です。そのシングルスレッドの使用率は非常に高くなっています。
シングルスレッド非同期の最大の利点の1つは、使用するメモリがはるかに少ないことです。マルチスレッド実行では、各スレッドに一定量の予約メモリが必要です。スレッドの数が増えると、スレッドが存在するために必要なメモリ量も増えます。メモリは有限であるため、一度に作成できるスレッドの数には限界があります。
例
Webサーバーの場合、各リクエストに独自のスレッドが与えられているふりをします。各スレッドに1MBのメモリが必要であり、Webサーバーには2GBのRAMがあるとします。このWebサーバーは、これ以上処理するのに十分なメモリがなくなる前の任意の時点で(およそ)2000件の要求を処理できます。
負荷がこれよりも大幅に高い場合、リクエストは非常に長い時間がかかる(古いリクエストが完了するのを待つ場合) 。
マルチスレッド同時実行
マルチスレッドの同時実行性は、代わりに複数のタスクを同時に実行することに依存しています。つまり、データベース呼び出しが戻るのを待ってスレッドがブロックされている場合、他の要求を同時に処理できます。スレッドの使用率は低くなりますが、実行するスレッドの数ははるかに多くなります。
また、マルチスレッドコードを推論するのははるかに困難です。ロック、同期、およびその他の楽しい同時実行性の問題があります。シングルスレッドの非同期は同じ問題の影響を受けません。
マルチスレッドコードは、CPUを集中的に使用する場合のパフォーマンスがはるかに高いただし、するタスクでは、。通常はブロックするネットワークコールなど、スレッドが「譲る」機会がない場合、シングルスレッドモデルは同時実行性をまったく持ちません。
両方が共存する可能性があります
もちろん、2つの間に重複があります。それらは相互に排他的ではありません。たとえば、マルチスレッドコードは、各スレッドをより有効に活用するために、ノンブロッキング方式で記述できます。
ボトムライン
考慮すべき他の多くの問題がありますが、私はこのような2つについて考えるのが好きです:
- プログラムがI / Oバウンドの場合である場合、シングルスレッド非同期はおそらく非常にうまく機能するでしょう。
- プログラムがCPUバウンドの場合、おそらくマルチスレッドシステムが最適です。
特定のケースでは、完了している非同期作業の種類と、それらのタスクが発生する頻度を判断する必要があります。
- リクエストごとに発生しますか?その場合、リクエストの数が増えるにつれて、メモリが問題になる可能性があります。
- これらのタスクは注文されていますか?その場合、複数のスレッドを使用する場合は同期を検討する必要があります。
- これらのタスクはCPUを集中的に使用しますか?もしそうなら、シングルスレッドは負荷に追いつくことができますか?
簡単な答えはありません。ユースケースとは何かを検討し、それに応じて設計する必要があります。非同期シングルスレッドモデルの方が良い場合があります。それ以外の場合、多数のスレッドを使用して大規模な並列処理を実現する必要があります。
その他の考慮事項
選択した同時実行モデルだけでなく、考慮する必要がある他の問題もあります。ErlangまたはClojureを知っていますか?これらの言語のいずれかで安全なマルチスレッドコードを記述して、アプリケーションのパフォーマンスを向上させることができると思いますか?これらの言語の1つに慣れるのに長い時間がかかりますか?また、学習した言語は将来あなたに利益をもたらすでしょうか?
これら2つのシステム間の通信に関連する問題はどうですか?2つの別々のシステムを並行して維持するのは非常に複雑ですか?ErlangシステムはどのようにしてDjangoからタスクを受け取りますか?Erlangはこれらの結果をDjangoにどのように伝えますか?パフォーマンスは、複雑さを増すだけの価値があるほど問題になりますか?
最終的な考え
私はいつもDjangoが十分に速いことを発見しており、非常にトラフィックの多いサイトで使用されています。同時要求数と応答時間を増やすために、いくつかのパフォーマンス最適化を行うことができます。確かに、私はこれまでCeleryで何もしていませんので、通常のパフォーマンスの最適化では、おそらくこれらの非同期タスクで発生する可能性のある問題は解決しません。
もちろん、問題に対してより多くのハードウェアを投入するという提案が常にあります。新しいサーバーをプロビジョニングするコストは、まったく新しいサブシステムの開発および保守コストよりも安いですか?
私はこの時点であまりにも多くの質問をしましたが、それは私の意図でした。答えは、分析とさらなる詳細なしでは簡単ではありません。しかし、問題を分析できるようになると、尋ねるべき質問を知ることになります。
私の直感では、別の言語で書き直す必要はないという。複雑さとコストはおそらく多すぎるでしょう。
編集
フォローアップへの対応
あなたのフォローアップは、いくつかの非常に興味深いユースケースを提示します。
1. HTTPリクエストの外部で動作するDjango
最初の例では、NFCタグを読み取り、データベースにクエリを実行しました。データベースまたはLDAPサーバーへのクエリはネットワークI / O(および潜在的にデータベースのパフォーマンス)によって制限されるため、この部分を別の言語で書くことはそれほど便利だとは思いません。一方、各管理コマンドは独自のプロセスとして実行されるため、同時要求の数はサーバー自体によってバインドされます。すでに実行中のプロセスにメッセージを送信していないため、セットアップとティアダウン時間がパフォーマンスに影響します。ただし、それぞれが独立したプロセスになるため、複数の要求を同時に送信できます。
この場合、調査できる2つの方法があります。
- 接続プーリングを使用して、データベースが複数のクエリを一度に処理できることを確認してください。(たとえば、Oracleでは、それに応じてDjangoを構成する必要があります
'OPTIONS': {'threaded':True}
。)データベースレベルまたはDjangoレベルで、独自のデータベースに合わせて調整できる同様の構成オプションがある場合があります。データベースクエリを作成する言語に関係なく、このデータが返されるのを待ってからLEDを点灯させる必要があります。ただし、クエリコードのパフォーマンスは違いをもたらす可能性があり、Django ORMは非常に高速ではありません(ただし、通常は十分高速です)。
- セットアップ/分解時間を最小限にします。プロセスを常に実行し、それにメッセージを送信します。(私が間違っている場合は修正してください。しかし、これはあなたの元の質問が実際に焦点を当てているものです。)管理コマンドを頻繁に使用するという考えは好きではありません。NFCリーダーからのメッセージをメッセージキューにプッシュし、Celeryが読み取ってDjangoに転送する小さなコードを継続的に実行することは可能ですか?小さなプログラムのセットアップと分解は、たとえそれがPythonで書かれていても(Djangoではありません!)、Djangoプログラム(そのすべてのサブシステムを含む)を開始および停止するよりも優れているはずです。
DjangoにどのWebサーバーを使用しているかわかりません。mod_wsgi
for Apacheでは、リクエストを処理するプロセスおよびプロセス内のスレッドの数を構成できます。Webサーバーの関連する構成を調整して、サービス可能な要求の数を最適化してください。
2. Djangoシグナルによる「メッセージの受け渡し」
2番目のユースケースも非常に興味深いものです。その答えがあるかどうかはわかりません。モデルインスタンスを削除していて、後で操作したい場合は、それらJSON.dumps
をシリアル化してから逆シリアル化することができJSON.loads
ます。関連フィールドはデータベースから遅延ロードされ、そのリンクはもはや存在しないため、後でオブジェクトグラフを完全に再作成(関連モデルのクエリ)することは不可能です。
もう1つのオプションは、何らかの方法でオブジェクトを削除対象としてマークし、要求/応答サイクルの最後(すべての信号が処理された後)にのみ削除することです。に依存するのではなく、これを実装するにはカスタム信号が必要になる場合がありpost_delete
ます。