非同期、ノンブロッキング、イベントベースのアーキテクチャの違いは何ですか?


84
  1. 違いは何ですか:

    • 非同期
    • ノンブロッキング、および
    • イベントベースのアーキテクチャ?
  2. 何かを非同期非ブロッキング(およびイベントベース)の両方にすることはできますか?

  3. プログラミングで最も重要なことは、非同期、非ブロッキング、および/またはイベントベース(または3つすべて)です。

あなたが例を提供することができれば、それは素晴らしいことです。

私が同様のトピックに関するこの素晴らしいStackOverflowの記事を読んでいたので、この質問が尋ねられていますが、それは上記の私の質問に答えていません。

回答:


91

非同期 非同期とは、文字通り同期していないことを意味します。電子メールは非同期です。あなたはメールを送ります、あなたは今応答を受け取ることを期待していません。しかし、それはノンブロッキングではありません。基本的にそれが意味するのは、「コンポーネント」がすぐに応答を期待せずに相互にメッセージを送信するアーキテクチャです。HTTPリクエストは同期的です。リクエストを送信して応答を取得します。

ノンブロッキング この用語は主にIOで使用されます。これが意味するのは、システムコールを行うと、スレッドをスリープ状態にすることなく(高い確率で)、結果が何であれ、すぐに返されるということです。たとえば、ノンブロッキングの読み取り/書き込み呼び出しは、実行可能なものをすべて返し、呼び出し元が呼び出しを再度実行することを期待します。たとえば、try_lockは非ブロッキング呼び出しです。ロックを取得できる場合にのみロックされます。システムコールの通常のセマンティクスはブロックされています。readは、データが得られるまで待機し、呼び出しスレッドをスリープ状態にします。

イベントベース この用語はlibeventに由来します。ノンブロッキングの読み取り/書き込み呼び出し自体は、コールバック(再試行)する必要がある「いつ」を通知しないため、役に立ちません。select / epoll / IOCompletionPortなどは、これらの呼び出しが「興味深い」データを返すことが期待される「いつ」をOSから見つけるためのさまざまなメカニズムです。libeventおよびその他のそのようなライブラリは、さまざまなOSによって提供されるこれらのイベント監視機能のラッパーを提供し、オペレーティングシステム間で実行される一貫したAPIを提供します。ノンブロッキングIOは、イベントベースと密接に関連しています。

これらの用語は重複していると思います。たとえば、HTTPプロトコルは同期ですが、非ブロッキングIOを使用したHTTP実装は非同期にすることができます。ここでも、読み取り/書き込み/ try_lockのような非ブロッキングAPI呼び出しは同期的です(すぐに応答を返します)が、「データ処理」は非同期的です。


2
非同期はプッシュベースにすることができますが、一定のポーリングを必要とする非ブロッキングについての良い点。
Alexander Torstling 2015年

同期を即時応答の受信として定義しましたが、グーグル同期の場合、すべての辞書はそれを「即時応答」ではなく「同時に発生する」と定義します。
IntelliData 2016年

4
電子メールを送信したが応答を期待しない場合、どのようにブロックされますか?返事を待っている間、私は自分のビジネスを気にすることができます。
Koray Tugay 2017年

20

非同期ハードウェアでは、コードはあるエンティティに何かをするように要求し、アクションが実行されている間は他のことを自由に行うことができます。アクションが完了すると、エンティティは通常、何らかの方法でコードに信号を送ります。ノンブロッキングアーキテクチャは、コードが関心を持つ可能性のある自発的に発生するアクションを記録し、コードがそのようなアクションが発生したことを尋ねることを可能にしますが、コードは明示的にそれらについて尋ねた場合にのみそのようなアクションを認識します。イベントベースのアーキテクチャは、イベントが自発的に発生したときにコードに積極的に通知します。

コードが1,000バイトを受信するシリアルポートについて考えてみます。

ブロッキング読み取りアーキテクチャでは、コードは1,000バイトが到着するか、あきらめることを決定するまで待機します。

非同期読み取りアーキテクチャでは、コードはドライバーに1,000バイトが必要であることを通知し、1,000バイトが到着すると通知されます。

非ブロッキングアーキテクチャでは、コードはいつでも何バイトが到着したかを尋ねることができ、適切と思われるときにそのようなデータの一部またはすべてを読み取ることができますが、すべてのデータがいつ到着したかを知る唯一の方法は尋ねることです。コードが1000番目のバイトが到着したときに1/4秒以内に調べたい場合は、1/4秒ごとにチェックする必要があります。

イベントベースのアーキテクチャでは、シリアルポートドライバは、データが到着するたびにアプリケーションに通知します。ドライバーは、アプリケーションが必要とするバイト数を認識しないため、アプリケーションは、アプリケーションが必要とする量よりも少ないまたは多い量の通知を処理できる必要があります。


5

したがって、最初と2番目の質問に答えるには:

ノンブロッキングは事実上非同期と同じです-あなたは電話をかけ、後で結果を得るでしょう、しかしそれが起こっている間あなたは何か他のことをすることができます。ブロッキングは反対です。旅を続ける前に、電話が戻るのを待ちます。

今、非同期/非ブロッキングコードは絶対に素晴らしいように聞こえます、そしてそれはそうです。しかし、私には警告の言葉があります。非同期/非ブロッキングは、携帯電話などの制約のある環境で作業する場合に最適です...限られたCPU /メモリを検討してください。また、コードが何らかの方法でUIウィジェットに反応する必要があるフロントエンド開発にも適しています。

非同期は、すべてのオペレーティングシステムがどのように機能する必要があるかについての基本です-それらはバックグラウンドであなたのためにたわごとを行い、あなたが要求したことをしたときにあなたのコードを起こします、そしてその呼び出しが失敗したとき、あなたはそれがしなかったと言われます例外、またはある種のリターンコード/エラーオブジェクトのいずれかによって機能します。

コードが応答するのに時間がかかる何かを要求した時点で、OSは他のことをするのに忙しくなる可能性があることを知っています。あなたのコード-プロセス、スレッドまたは同等のもの、ブロック。コードは、ネットワーク接続が確立されるのを待っている間、HTTP要求からの応答を待っている間、またはファイルの読み取り/書き込みを待っている間、OSで他に何が起こっているかを完全に認識していません。など。あなたのコードは「単に」マウスクリックを待っている可能性があります。その間に実際に起こっていたのは、OSが「イベント」をシームレスに管理、スケジュール設定、および反応していることでした。メモリ、I / O(キーボード、マウス、ディスク、インターネット)の管理など、OSが監視しているものです。その他のタスク、障害回復など。

オペレーティングシステムはハードコアです。彼らはあなたのプログラマーから複雑な非同期/非ブロッキングのものをすべて隠すのが本当に得意です。そして、それがほとんどのプログラマーがソフトウェアを使って今日の場所にたどり着いた方法です。現在、CPUの制限に達しており、パフォーマンスを向上させるために並行して実行できると言われています。これは、非同期/非ブロッキングが非常に好ましいことのように思われることを意味します。そうです、ソフトウェアがそれを要求する場合、私は同意できます。

バックエンドWebサーバーを作成している場合は、注意して続行してください。水平方向にスケーリングすると、はるかに安価になることを忘れないでください。Netflix / Amazon / Google / Facebookは、このルールの明らかな例外ですが、純粋に、ハードウェアの使用量が少ない方が安価であるためです。

非同期/ノンブロッキングコードがバックエンドシステムにとって悪夢である理由を説明します。

1)それは生産性に対するサービス拒否になります...あなたはもっと多くのことを考えなければならず、途中で多くの間違いを犯します。

2)リアクティブコードのスタックトレースが解読できなくなります-何が、いつ、なぜ、どのように呼ばれたのかを知るのは困難です。デバッグで頑張ってください。

3)物事がどのように失敗するかについて、特に多くの物事があなたがそれらを送った方法に順不同で戻ってきたとき、あなたはもっと考えなければなりません。旧世界では、一度に1つのことをしました。

4)テストするのは難しいです。

5)維持するのが難しい。

6)痛いです。プログラミングは喜びと楽しみでなければなりません。痛みが好きなのはマゾヒストだけです。並行/リアクティブフレームワークを作成する人はサディストです。

そして、はい、私は同期と非同期の両方を書きました。99.99のバックエンドアプリケーションがこのパラダイムでうまくいくので、私は同期を好みます。フロントエンドアプリには間違いなくリアクティブコードが必要であり、それは常に方法でした。

  1. はい、コードは非同期、非ブロッキング、イベントベースにすることができます。

  2. プログラミングで最も重要なことは、コードが機能し、許容可能な時間内に応答することを確認することです。その重要な原則に固執すれば、間違いはありません。


**更新** Goで遊んだ後、チャネルとgoルーチンに頭を悩ませた後、言語の構成要素がSadistフレームワークの作成者から苦労しているため、実際にはコードをより並行的にするのが好きだと言わざるを得ません。非同期処理の世界には「安全な言葉」があります。それが「Go!」です。
user924272

4

私にとって、非ブロッキングとは、スレッド内のアクションの実行が他のスレッドの実行に依存しないことを意味し、特にクリティカルセクションを必要としません。

非同期とは、実行が呼び出し元のフローの外部で発生し、延期される可能性があることを意味します。通常、実行は別のスレッドで行われます。

同時データの読み取りは非ブロッキング(ロックする必要はありません)ですが、同期しています。逆に、同期的にデータを同時に書き込むことはブロックされます(排他ロックが必要です)。メインフローの観点から非ブロッキングにする方法は、書き込みを非同期にし、実行を延期することです。

イベントの概念は別のものです。これは、大まかに言えば、何かが発生したときに通知されることを意味します。書き込みが非同期で実行された場合、書き込みが実行されると、イベントを発生させてシステムの他の部分に通知することができます。他の部分はイベントに応答します。システムは、コンポーネント間で通信する唯一の方法としてイベントのみに基づいて構築できます(アクターモデルを考えてください)が、そうである必要はありません。

3つの用語は関連していますが、私にとっては異なる概念です。しかし、人々はそれらをいくぶん交換可能な方法で使用している可能性があります。


2

一般に、非ブロッキングアーキテクチャは、ワーカースレッドで長時間実行される可能性がありますが、呼び出しをブロックしないメソッド呼び出しに基づいています。スレッドをます。呼び出し元のスレッドが、ワーカースレッドが実行しているタスクに関する情報を取得する必要がある場合、またはタスクから情報を取得する必要がある場合、それを行うのは呼び出し側のスレッド次第です。

イベントベースのアーキテクチャは、発生したイベントに応答して実行されるコードの概念に基づいています。コード実行のタイミングは一般に決定論的ではありませんが、イベントによってブロッキングメソッドが呼び出される場合があります。システムがイベントベースであるからといって、それが行うすべてがブロックされていないことを意味するわけではありません。

一般に、非同期アーキテクチャは、イベントベースの非ブロッキングアーキテクチャです。

非同期呼び出しが行われると、イベントハンドラーが同期サービスを提供するAPIに登録され、呼び出し元が関心のあることが発生したことを呼び出し元に通知します。その後、呼び出しはすぐに戻り(非ブロッキング動作)、呼び出し元は自由に実行を続行できます。イベントが呼び出しプロセスに戻されると、そのプロセスの一部のスレッドで処理されます。

イベントが同じスレッドで処理されるかどうかを理解することは重要です。これは実行の非ブロッキングの性質に影響を与えるためですが、単一のスレッドで非同期実行管理を行うライブラリを個人的には知りません。

上記の段落は厳密には正しくないため、削除しました。私の意図は、OSファシリティへの呼び出しや実行の継続など、システム内の操作が非ブロッキングである場合でも、シングルスレッド実行の性質上、イベントが発生すると、イベントが競合することを意味します。スレッドの計算時間に関する他の処理タスク。


あなたの最後の段落は、「非同期アーキテクチャは...ノンブロッキングである」というあなたの声明と矛盾していません
nickb 2011年

私はあなたの質問の「定義」の部分に対処するのにあまり良い仕事をしなかったと思います。更新を投稿します。しかし、いや、シングルスレッドの実行の性質は、すべての操作は、本質的にブロックしていることである、実行されている間非同期がさらに便利になりました。
arootbeer 2011年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.