ナビゲーションをスキップ

スレッドモデル

このページは Github Wikiページ から自動生成されていることをご存知ですか? こちら から改善できます!

簡単に言うと、チャネルについて

  1. トランスポートと種類に関係なく、すべてのアップストリーム(受信)イベントは、チャネルのI/Oを実行するスレッド(I/Oスレッド)から発生させる必要があります。
  2. すべてのダウンストリーム(送信)イベントは、I/Oスレッドと非I/Oスレッドを含む任意のスレッドからトリガーできます。ただし、ダウンストリームイベントの副作用としてトリガーされるアップストリームイベントは、I/Oスレッドから発生させる必要があります。(例:Channel.close()channelDisconnectedchannelUnboundchannelClosed をトリガーする場合、これらはI/Oスレッドによって発生させる必要があります。)

現在の問題(UGLY - アップストリームハンドラで競合状態を引き起こす、BAD - 競合状態を引き起こさないが、予期されるスレッドモデルに違反する)

  • UGLY: ダウンストリームイベントの副作用としてトリガーされるアップストリームイベントは、呼び出し元スレッドによってトリガーされます。

  • UGLY: ローカルトランスポートは、常に呼び出し元スレッドを使用してイベントをトリガーします。

  • BAD: channelOpen は、ChannelFactory.newChannel() を呼び出したスレッドによってトリガーされます。これはI/Oスレッドではありません。これは少し問題ですが、そうでなければ、ここでチャネルを閉じることで、同時アクティブチャネル数を制限することはできません。IOスレッドでこれを行うと、それほど効率的ではありません。

  • BAD: クライアント側チャネルは、2つのI/Oスレッドによって実行されます。1つは接続試行を行い、もう1つは実際のI/Oを行います。

アクションアイテム

  • クライアント側ボス、サーバー側ボス、NioWorkerを、すべてのI/O操作を実行できるユニバーサルI/Oスレッドにマージします。これを行うことで
    • 接続試行を試みたスレッドが読み取りと書き込みを続行できるため、クライアント側チャネルの問題を解決します。
    • Nettyが開いているサーバーポートの数と同じ数のスレッドを作成するという問題を解決します。
    • NioWorkerのプールをより簡単に共有でき、チャネルとワーカーのマッピングに柔軟性が増します。
    • また、すべてのトランスポート(ソケット、データグラム、SCTPなど)が拡張できるように、抽象I/Oスレッドクラスを作成できるかどうかを調査する必要があります。現在、ソケット、データグラム、SCTPの間で重複が多すぎます。
  • 呼び出し元スレッドがI/Oスレッドでない場合、Nettyは後でI/Oスレッドでアップストリームイベントをトリガーします。この変更に加えて、ChannelPipelineChannelHandlerContextsendUpstreamLater() メソッドを追加することにより、ユーザーが後でI/Oスレッドで独自のアップストリームイベントをトリガーできるようにします。
    • ただし、現在のスレッドがI/Oスレッドでない場合にのみ sendUpstreamLater() を使用することはできません。OMATPE または MATPE が干渉するため、ユーザーに決定させる必要があります。(つまり、sendUpstream() または sendUpstreamLater() を呼び出すこと)
  • ChannelFactory.newChannel() は、イベントをすぐにトリガーしてはなりません。 newChannel() は、呼び出し元に新しいチャネルを返す前に、I/OスレッドがチャネルがI/Oスレッドに登録されたことを通知するまで待機する必要があります。
  • ローカルトランスポートを書き直します。

質問

  • v3ですべての変更を行い、下位互換性を維持することはできますか? v4でこれを行う方が簡単ではありませんか? ChannelFuture を多用するハンドラですべてのI/Oを実行する完全に非同期のユーザーアプリケーションは、現在の欠陥のあるスレッドモデルの影響を受けないはずです。つまり、ユーザーはこの問題を回避できるため、2つのブランチで同じ変更を行うのではなく、v4に移行する方が良いかもしれません。

回答

  • v3に「バックポート」するのが大変な作業であれば、先に進んでv3を「無視」するだけだと思います。おそらく、v3で「より簡単な」回避策を見つけることができ、少なくともChannel.close()レースを取り除くのに役立ちます。これはユーザーに最も影響を与える可能性が高いものです。(normanmaurer)
最終取得日:2024年7月19日