高性能コンピューティング[単一サーバーの高性能]

もちろん、アーキテクトの視点では、高性能アーキテクチャの設計に特別な注意を払う必要があり、高性能アーキテクチャの設計は主に次の2つの側面に焦点を当てています。

  • 単一サーバーのパフォーマンスを向上させ、単一サーバーのパフォーマンスを最大化するようにしてください
  • 1台のサーバーでパフォーマンスをサポートできない場合は、サーバークラスターソリューションを設計する

上記の2つの点に加えて、最終的なシステムが高いパフォーマンスを達成できるかどうかは、特定の実装とコーディングにも関係しています。しかし、アーキテクチャ設計は高性能の基礎であり、アーキテクチャ設計が高性能を達成しない場合、特定の実装とコーディングの改善の余地は限られます。はっきりと言えば、アーキテクチャの設計はシステムパフォーマンスの上限を決定し、実装の詳細はシステムパフォーマンスの下限を決定します

単一サーバーの高性能

単一サーバーの高パフォーマンスの鍵の1つは、サーバーで採用されているネットワークプログラミングモデルです。ネットワークプログラミングモデルの設計には、2つの重要なポイントがあります。

  • サーバーがリンクを管理する方法
  • サーバーがリクエストを処理する方法

そして、これらの2つのポイントは、最終的にはオペレーティングシステムのI / Oモデルとプロセスモデルに関連しています。

  • I / Oモデル:ブロッキング、非ブロッキング、同期、非同期
  • プロセスモデル:シングルプロセス、マルチプロセス、マルチスレッド、シングルスレッド

PPC

PPCは、接続ごとのプロセスの略であり、その意味は、接続の要求を処理する新しい接続があるたびに新しいプロセスを作成することです。これは、従来のUNIXネットワークサーバーで採用されているモデルです。基本的なプロセスは次のとおりです。
ここに画像の説明を挿入

  • 親プロセスがリンクを受け入れ、子プロセスをフォークします
  • 子プロセスはリンク関連の要求を処理し、次に子プロセスは接続を閉じます
  • 親プロセスが子プロセスをforkした後、それはcloseを呼び出します。実際には、接続を閉じませんが、接続されたファイル記述子の参照カウントをデクリメントします。接続が実際に閉じられた場合、子プロセスもcloseを呼び出した後、対応するファイル記述をリンクしますシンボル参照カウントが0になった後、オペレーティングシステムは実際に接続を閉じます。

PPCモードは実装が簡単で、サーバー接続の数がそれほど多くない状況に適しています。たとえば、データベースサーバー。通常のビジネスサーバーの場合、インターネットが台頭する前は、サーバーのトラフィックと同時実行性はそれほど大きくなかったため、このモデルは実際には非常にうまく機能していました。インターネットの台頭後、サーバーの同時実行数とアクセス数は数十から数万に劇的に増加しました。このモデルの欠点は、主に次の点で強調されています。

  • フォークはコストがかかります。オペレーティングシステムの観点から見ると、プロセスを作成するコストは非常に高く、多くのカーネルリソースを割り当てる必要があり、メモリイメージを親プロセスから子プロセスにコピーする必要があります。現在のオペレーティングシステムがメモリイメージのコピー時にコピーオンライト(Copy on Write)テクノロジを使用している場合でも、プロセスを作成する全体的なコストは依然として非常に高くなります。
  • 親プロセスと子プロセスの間の複雑な通信:親プロセスが子プロセスを「フォーク」すると、ファイルディスクリプターはメモリイメージのコピーによって親プロセスから子プロセスに渡されますが、「フォーク」が完了すると、親プロセスと子プロセス間の通信がより面倒になり、IPC(プロセス間)通信)およびその他のプロセス通信スキーム。たとえば、子プロセスは、グローバルプロセスの親プロセスをサポートするために閉じる前に処理した要求の数を親プロセスに通知する必要があります。次に、子プロセスと親プロセスはIPCスキームを使用して情報を送信する必要があります。
  • プロセス数の増加は、オペレーティングシステムに大きな圧力をかけます。各接続の生存時間が長く、新しい接続が継続的に発生する場合、プロセス数が増加し、オペレーティングシステムプロセスのスケジューリングと切り替えの頻度も増加します。高くなるほど、システムへの圧力が高くなります。したがって、一般に、PPCソリューションが処理できる同時接続の最大数は数百のみです。

プリフォーク

PPCモードのさまざまな欠点を考慮して、さまざまなソリューションが作成されました。PPCモードでは、接続が着信したときに接続要求を処理するために新しいプロセスが「フォーク」されます。「フォーク」プロセスはコストが高いため、ユーザーはアクセスに時間がかかると感じる場合があります。プリフォークモードの出現は、この問題を解決することです。プリフォークは、プロセスを事前に作成することです(プリフォーク)。システムは、プロセスが開始すると事前にプロセスを作成し、ユーザーリクエストの受け入れを開始します。新しい接続が確立されると、 「フォーク」プロセスの操作を排除し、ユーザーがより速くより良いエクスペリエンスにアクセスできるようにする、プリフォークの基本的なダイアグラム:
ここに画像の説明を挿入

  • プリフォークを実現するための鍵は、複数の子プロセスが同じソケットを受け入れることです。新しい接続が開始されると、オペレーティングシステムは1つのプロセスのみが正常に受け入れられることを保証しますが、ここにも問題があります。「ショックグループ」の現象は、子プロセスは正常に受け入れることができますが、受け入れ時にブロックされたすべての子プロセスが呼び起こされ、不要なプロセスのスケジューリングとコンテキストの切り替えが発生します。オペレーティングシステムはこの問題を解決できます。カーネルはLinux 2.6バージョン以降で解決されています。サプライズグループの問題を受け入れる
  • PPCのようなpreforkモードは、複雑な親子プロセスの通信とサポートされる同時接続の数が限られているという問題がまだあるため、現在、実用的なアプリケーションは多くありません。
  • ApacheサーバーはMPMプリフォークモードを提供します。これは、古いソフトウェアとの信頼性または互換性を必要とするサイトに推奨されます。デフォルトでは、最大256の同時接続をサポートします。

TPC

TPCはThread per Connectionの略であり、この接続の要求を処理する新しい接続があるたびに新しいスレッドを作成することを意味します。プロセスと比較して、スレッドは軽く、スレッドを作成するコストはプロセスのコストよりもはるかに少ないですが、同時に複数のスレッドがプロセスのメモリ空間を共有し、スレッド通信はプロセス通信よりも単純です。したがって、TPCは実際にPPCフォークの高コストと親プロセスと子プロセス間の複雑な通信を解決または弱めます。

TPCの基本的なプロセスは次のとおりです。

  • 親プロセスは接続を受け入れます(図では受け入れます)
  • 親プロセスは子スレッド(図のpthread)を作成します
  • 子スレッドは、接続の読み取り要求と書き込み要求を処理します(図では、子スレッドの読み取り、ビジネス処理、書き込み)。
  • 子スレッドは接続を閉じます(図の子スレッドで閉じます)

ここに画像の説明を挿入
PPCと比較して、メインプロセスがリンクを閉じる必要がないことを見つけることは難しくありません。理由は、子スレッドがメインプロセスのプロセススペースを共有し、接続のファイル記述子がコピーされないため、閉じる必要があるのは1回だけです。

TPCは、高いフォークコストと複雑なプロセス通信の問題を解決しますが、新しい問題も引き起こします。

  • まず、スレッドの作成はプロセスの作成よりも安価ですが、コストがかからないわけではありません。高い同時実行性(1秒あたり数万の接続など)の場合でも、依然としてパフォーマンスの問題があります。
  • 第二に、プロセス間通信の必要はありませんが、スレッド間の相互排除と共有によって複雑さが生じ、誤ってデッドロックの問題が発生する可能性があります
  • 最後に、複数のスレッドが相互に影響します。スレッドに異常があると、プロセス全体が終了する可能性があります(範囲外のメモリなど)。
  • TPCには、新たな問題が発生するだけでなく、CPUスレッドのスケジューリングと切り替えコストの問題も残っています。したがって、TPCソリューションは基本的にPPCソリューションに似ています。数百の同時接続のシナリオでは、PPCソリューションがより採用されます。PPCソリューションにはデッドロックのリスクがなく、複数のプロセス間に相互作用がないためです。高い安定性

プリスレッド

  • TPCモードでは、接続が着信すると、接続要求を処理するために新しいスレッドが作成されます。スレッドの作成はプロセスの作成よりも軽量ですが、それでもある程度の代償があります。プリスレッドモードはこの問題を解決するためのものです
  • preforkと同様に、prethreadモードでは、事前にスレッドが作成され、ユーザーリクエストの受け入れが開始されます。新しい接続が確立されると、スレッドの作成操作を省略できるため、ユーザーはより速く感じ、より良いエクスペリエンスを得ることができます。
  • 複数のスレッド間でのデータ共有と通信の方が便利なので、実際には、プリスレッドの実装はプリフォークよりも柔軟性があります。一般的な実装は次のとおりです。
    • メインプロセスが受け入れ、処理のために接続をスレッドに渡します
    • 子スレッドはすべて受け入れようとしました。結局、
      ここに画像の説明を挿入
      受け入れられたQianchengは1つだけ成功しました。スキームの基本的なダイアグラムは次のとおりです。ApacheサーバーのMPMワーカーモードは基本的にプレスレッドスキームですが、わずかな改善により、Apacheサーバーは複数のプロセスを作成しますプロセスに複数のスレッドを作成します。これは主に安定性のためです。子プロセスのスレッドが異常であり、子プロセス全体が終了した場合でも、サービスを提供し続け、サーバー全体がハングアップしない他の子プロセスがあります。 。
      理論上、プリスレッドはプリフォークよりも多くの同時接続をサポートできますApacheサーバーMPMワーカーモードは、デフォルトで16×25 = 400の同時処理スレッドをサポートします。

リアクター

PPCソリューションの主な問題は、接続ごとにプロセスを作成する必要があり、接続が終了するとプロセスが破棄されることです。これは実際には大きな無駄です。この問題を解決するには、リソースを再利用する、つまり分離しないのが自然な考え方です。接続ごとにプロセスを作成しますが、プロセスプールを作成し、プロセスに接続を割り当てます。プロセスは、複数の接続のビジネスを処理できます。

  • リソースプールの処理方法の導入後、新しい質問が浮上します。プロセスは複数の接続のビジネスをどのように効率的に処理できるでしょうか。プロセスが接続されると、プロセスは「読み取り->ビジネス処理->書き込み」の処理フローを採​​用できます。現在の接続に読み取るデータがない場合、プロセスは読み取り操作でブロックされます。このブロック方法は1つずつ接続されますプロセスのシナリオには問題はありませんが、プロセスが複数の接続を処理する場合、プロセスは特定の接続の読み取り操作でブロックされます。現時点では、他の接続が読み取り可能なデータを持っている場合でも、プロセスはそれを処理できません。明らかに、これは実行できません。ハイパフォーマンス
  • この問題を解決する最も簡単な方法は、読み取り操作を非ブロッキングに変更し、プロセスが複数の接続を継続的にポーリングすることです。この方法はブロッキングの問題を解決できますが、解決策は洗練されていません。まず、ポーリングはCPUを消費します。次に、プロセスが数万の接続を処理する場合、ポーリングの効率は非常に低くなります。

上記の問題をよりよく解決するには、接続にデータがある場合にのみ処理するのが自然な考え方です。これがI / O多重化テクノロジーの源であるI / O多重化通信業界ではより一般的です。たとえば、時分割多重化(GSM)、コード分割多重化(CDMA)、周波数分割多重化(GSM)などは、「1つのチャネルで複数の信号またはデータストリームを送信するプロセスと技術」を意味しますが、この意味をコンピュータフィールドに適用すると混乱が生じます。表面的な意味から、通信フィールドの「チャネル」はコンピュータフィールドの「接続」に似ており、通信フィールドの「データフロー」はコンピュータフィールドの「データフロー」に似ているためです。 「それは似ている。通信分野の多重化の定義をコンピュータ分野に直接コピーすると、多重化は「1つの接続で複数のデータを送信することであり、実際のI / O多重化とはかけ離れています。コンピュータネットワークの分野でのI / O多重化。「多重化」は複数の接続を指し、「多重化」は同じブロッキングオブジェクトを多重化する複数の接続を指します。このブロッキングオブジェクトは特定の実装に関連しています。例としてLinuxを取り上げます。selectを使用する場合、共通のブロッキングイメージは、selectが使用するfd_setです。epollを使用する場合は、epoll_createが作成したファイル記述子です。

要約すると、I / O多重化テクノロジには、次の2つの主要な実装ポイントがあります。

  • 複数の接続がブロッキングオブジェクトを共有する場合、プロセスはすべての接続をポーリングするのではなく、1つのブロッキングオブジェクトでのみ待機する必要があります。
  • 接続に処理可能な新しいデータがある場合、オペレーティングシステムはプロセスに通知し、プロセスはブロックされた状態から戻ってビジネス処理を開始します

スレッドプールと組み合わせたI / O多重化は、PPCおよびTPCモデルの問題を完全に解決し、「素晴らしい神々」がそれに非常に良い名前を付けました。リアクター、中国語は「リアクター」を意味し、実際には「 「応答」とは「イベントの反応」を意味します。これは、素人の言葉で「イベントが発生したときに、対応する応答がある」と理解できます。ReactorモードはDispatcherモードとも呼ばれます(多くのオープンソースシステムは、Reactorモードを実際に実装するこの名前のクラスを参照します)。これは、モード自体の意味に近い、つまり、受信されたI / O多重化統合監視イベントです。プロセスへのディスパッチ
。Reactorモデルのコアコンポーネントには、Reactorおよび処理リソースプール(プロセスプールまたはスレッドプール)が含まれます。Reactorはイベントの監視と配信を担当し、処理リソースプールはイベントの処理を担当します。一見すると、Reactorの実装比較的単純ですが、実際には、さまざまなビジネスシナリオと組み合わせて、Reactorモードの特定の実装は柔軟で変更可能であり、主に次の2つの点に反映されます。

  • Reactorの数は変更できます。1つまたは複数のReactorです。
  • リソースプールの数は変更できます。プロセスを例にとると、単一のプロセスまたは複数のプロセスにすることができます(スレッドは類似しています)

上記の2つの要素を組み合わせると、理論的には4つの選択肢がありますが、「マルチリアクターシングルプロセス」の実装スキームは「シングルリアクターシングルプロセス」スキームよりも複雑で、パフォーマンス上の利点がないため、「マルチリアクターシングルプロセス」です。 「このスキームは理論上のスキームにすぎず、実際には適用されません。最終的なReactorモードには、次の3つの典型的な実装スキームがあります。

  • シングルリアクターシングルプロセス/シングルスレッド
  • シングルリアクターマルチスレッド
  • マルチリアクターマルチプロセス/スレッド。

上記のスキームは、プロセスまたはスレッドを具体的に選択し、さらにプログラミング言語とプラットフォームに関連しています。たとえば、Java言語は一般にスレッド(たとえば、Netty)を使用し、C言語はプロセスとスレッドを使用します(たとえば、Nginxはプロセスを使用し、Memcacheはスレッドを使用します)。

シングルリアクターシングルプロセス/スレッド

シングルリアクターシングルプロセス/スレッドスキームの概略図は次のとおりです(プロセスを例にとります)。
ここに画像の説明を挿入
選択、受け入れ、読み取り、送信は標準のネットワークプログラミングAPIであり、ディスパッチと「ビジネス処理」はXu Yahaoが完了した操作です
計画の詳細は次のとおりです。

  • Reactorオブジェクトは、selectを介して接続イベントを監視し、イベントの受信後にディスパッチを介してそれらを配信します
  • 接続確立イベントの場合は、Acceptorによって処理されます。Acceptorは、acceptを介して接続を受け入れ、接続後に後続のさまざまなイベントを処理するハンドラを作成します。
  • 接続確立イベントではない場合、Reactorは接続に対応するハンドラー(ステップ2で作成されたハンドラー)を呼び出して応答します。
  • ハンドラーは、読み取り->ビジネス処理->送信の完全なビジネスプロセスを完了します。

単一リアクター単一プロセスモデルの利点は、非常に単純で、プロセス間通信がなく、プロセスの競合がなく、すべて同じプロセスで完了することです。しかし、その欠点も非常に明白です。具体的な症状は次のとおりです。

  • プロセスは1つしかなく、マルチコアCPUのパフォーマンスを使用することはできません。マルチコアCPUを利用するために複数のシステムを配置することはできますが、これにより操作とメンテナンスが複雑になります。本来、1つのシステムのみをメンテナンスする必要があります。この方法では、1台のマシンでメンテナンスが必要です。複数のシステム
  • ハンドラーが特定の接続でビジネスを処理しているとき、プロセス全体が他の接続のイベントを処理できないため、パフォーマンスのボトルネックに簡単につながる可能性があります

したがって、シングルリアクターシングルプロセスソリューションには、実際にはアプリケーションシナリオがほとんどなく、ビジネス処理が非常に高速なシナリオにのみ適しています。現在、より有名なオープンソースソフトウェアはシングルリアクターシングルプロセスRedisを使用しています。

プロセスでスレッドを作成する必要がないため、C言語の書き込みシステムは通常、単一のReactor単一プロセスを使用します。Java言語の書き込みは、通常、単一のReactor単一スレッドを使用しますが、Java仮想マシンはプロセスであるため、仮想マシン、ビジネスには多くのスレッドがありますスレッドはスレッドの1つにすぎません

シングルリアクターマルチスレッド

単一の反応器、単一のプロセス/スレッド溶液の欠点を回避するためには、マルチプロセス/マルチスレッドを導入する第二溶液にそのリードは明らかである:単一の反応器は、多
次のように-currency単一反応器、マルチスレッド・ソリューション図である。
ここに画像の説明を挿入
次のように溶液の詳細な説明は次のとおりです。

  • メインスレッドでは、Reactorオブジェクトがselectを介して接続イベントを監視し、イベントを受信した後、ディスパッチを介してそれらを配信します。
  • 接続確立イベントの場合は、Acceptorによって処理されます。Acceptorは、acceptを介して接続を受け入れ、接続後に後続のさまざまなイベントを処理するハンドラを作成します。
  • 接続確立イベントではない場合、Reactorは接続に対応するハンドラー(ステップ2で作成されたハンドラー)を呼び出して応答します。
  • ハンドラーはイベントへの応答のみを担当し、ビジネス処理を実行しません。ハンドラーが読み取りによってデータを読み取った後、ビジネス処理のためにプロセッサーに送信されます
  • プロセッサは、独立したサブマネープロセスで実際のビジネス処理を完了し、応答結果をメインプロセスのハンドラーに送信して処理します。ハンドラーは、応答を受信した後、送信を通じてクライアントに応答結果を返します。

シングルリアクターマルチスレッドソリューションは、マルチコアおよびマルチCPUの処理能力を最大限に活用できますが、次の問題もあります。

  • マルチスレッドデータの共有とアクセスはより複雑です。たとえば、子スレッドがビジネス処理を完了した後、結果をメインスレッドのReactorに渡して送信する必要があります。これには、共有データの相互排除と保護メカニズムが含まれます。JavaのNIOを例にとると、セレクタはスレッドセーフですが、Selector.selectKeys()によって返されるキーのセットはスレッドセーフではありません。選択されたキーの処理は、保護するためにシングルスレッドで行うか、同期する必要があります。
  • Reactorは、すべてのイベントの監視と応答を担当し、メインスレッドでのみ実行されます。これは、瞬間的に高い同時実行性が発生すると、パフォーマンスのボトルネックになります。

ここでは「シングルリアクターマルチスレッド」スキームについて説明していますが、「シングルリアクターマルチプロセス」スキームについては触れていません。主な理由は、複数のプロセスが使用されている場合、子プロセスがビジネスプロセスを完了した後、結果が親プロセスに返され、親プロセスに送信するよう通知されます。親プロセスはReactorを介して各接続のイベントのみを監視し、それを配信するため、どのクライアントが非常に厄介ですか。親プロセスと通信する場合、子プロセスは接続ではありません。親プロセスと子プロセス間の通信を接続とし​​てシミュレートし、Reactorを監視に追加する場合は、さらに複雑になります。マルチスレッドを使用する場合、マルチスレッドはデータを共有するため、スレッド間で通信することは非常に便利です。スレッド間でデータを共有するときの同期の問題についてはさらに考慮が必要ですが、複雑さは上記のプロセス間通信の複雑さよりも低くなります。たくさんの

マルチリアクターマルチプロセス/スレッド

単一のリアクターとマルチスレッドの問題を解決するための最も直感的な方法は、単一のリアクターを複数のリアクターに変更することです。これは、3番目のソリューションである複数のリアクターと複数のプロセス/スレッドにつながります。
マルチリアクターマルチプロセス/スレッドスキームの概略図は次のとおりです(例としてプロセスを取り上げます)
ここに画像の説明を挿入
スキームの詳細な説明は次のとおりです。

  • 親プロセスのmainReactorオブジェクトは、selectを介して接続確立イベントを監視し、イベントの受信後にAcceptorを介してイベントを受信し、新しい接続を子プロセスに割り当てます
  • 子プロセスのsubReactorは、mainReactorによって割り当てられた接続を監視のために接続キューに追加し、接続のさまざまなイベントを処理するハンドラーを作成します
  • 新しいイベントが発生すると、subReactorは対応するハンドラー(つまり、ステップ2で作成されたハンドラー)を呼び出して応答します。
  • ハンドラは、読み取り->ビジネス処理->送信の完全なビジネスプロセスを完了します。

マルチリアクターマルチプロセス/スレッドソリューションは、シングルリアクターマルチスレッドよりも複雑に見えますが、実際の実装は単純です主な理由は次のとおりです。

  • 親プロセスと子プロセスの責任は非常に明確であり、親プロセスは新しい接続の受信のみを担当し、子プロセスは後続のビジネス処理を完了します
  • 親プロセスと子プロセスの間の相互作用は非常に単純で、親プロセスは新しい接続を子プロセスに渡すだけでよく、子プロセスはデータを返す必要はありません
  • 子プロセスは互いに独立しており、同期および共有する必要はありません(ここでは、ネットワークモデル関連の選択、読み取り、送信などにのみ限定され、同期および共有する必要はありません。「ビジネス処理」を同期および共有する必要がある場合があります)。

現在、複数のリアクターと複数のプロセスを使用する有名なオープンソースシステムはNginxで、複数のリアクターと複数のスレッドを使用してMemcacheとNettyを実装しています。

Nginxはマルチリアクターマルチプロセスモデルを使用しますが、ソリューションは標準のマルチリアクターマルチプロセスとは異なります。具体的な違いは、リスニングポートのみがメインプロセスで作成され、mainReactorは接続を「受け入れる」ために作成されないことを示しています。代わりに、子プロセスのReactorが接続を「受け入れ」ます。「受け入れ」へのロックによって制御される子プロセスは一度に1つだけです。プロセスが新しい接続を「受け入れる」と、処理のために独自のReactorに配置され、他の子プロセスには割り当てられません。

プロクター

Reactorは非ブロッキング同期ネットワークモデルです。これは、実際の読み取りおよび送信操作にはユーザープロセスの同期が必要なためです。ここで「同期」とは、読み取りや送信などのI / O操作を実行するときにユーザープロセスが同期していることを意味します。I/ O操作を非同期に変更すると、パフォーマンスがさらに向上します。これは非同期ネットワークモデルです。

Proactorの「プロアクティブデバイス」としての中国語の翻訳は理解が難しくなります。同様の単語はプロアクティブ、つまり「アクティブ」を意味するため、「アクティブデバイス」に翻訳することで理解を深めることができます。Reactorは「イベントが発生したときに通知し、処理します」と理解でき、Proactorは「イベントが発生したときに処理し、イベントが処理されたときに通知します」と理解できます。ここでの「I」はオペレーティングシステムのカーネルであり、「イベント」は新しい接続、読み取るデータ、書き込むデータなどのI / Oイベントです。

原子炉モデル図:
ここに画像の説明を挿入

計画の詳細は次のとおりです。

  • Proactorイニシエーターは、ProactorとHandlerを作成し、非同期操作プロセッサーを通じてカーネルにProactorとHandlerの両方を登録します。
  • 非同期操作プロセッサは、登録要求の処理とI / O操作の完了を担当します
  • 非同期操作プロセッサは、I / O操作の完了後にProactorに通知します
  • Proactorは、さまざまなイベントタイプに応じてビジネス処理のためにさまざまなハンドラーをコールバックします
  • ハンドラーはビジネス処理を完了します。ハンドラーはカーネルプロセスに新しいハンドラーを登録することもできます

理論的には、ProactorはReactorよりも効率的です非同期I / OはDMA機能を最大限に活用し、I / O操作と計算をオーバーラップさせることができます。ただし、真の非同期I / Oを実現するには、オペレーティングシステムが多くの作業を行う必要があります。現在、真の非同期I / OはWindowsでIOCPを介して実装されていますが、LinuxでのAIOは完全ではないため、Linuxで高同時ネットワークが実装されますリアクターモードはプログラミングのメインモードです。したがって、ブーストasioがプロクターモデルを実装すると主張している場合でも、実際にはWindowsではIOCPを使用しますが、LinuxではReactorモード(epollを使用)でシミュレートされた非同期モデルです

おすすめ

転載: blog.csdn.net/dawei_yang000000/article/details/108556754