この記事では、ソフトウェア プロジェクトでリアクティブ アーキテクチャから移行するという決定について説明します。リアクティブ システムの中核原則、ノンブロッキング I/O の利点、リアクティブ アプローチで直面した課題について詳しく説明します。
Reactive には、応答性の高い分散システムとアプリケーションの構築を目的とした一連の原則とガイドラインが含まれており、次の特徴があります。
リアクティブ システムの主な利点の 1 つは、ノンブロッキング I/O の使用です。このアプローチにより、I/O 操作中のスレッドのブロックが回避され、単一のスレッドで複数のリクエストを同時に処理できるようになります。これにより、従来のブロッキング I/O と比較してシステム効率が大幅に向上します。
従来のマルチスレッドでは、ブロック操作はシステムの最適化において重大な課題を引き起こします (図 1)。過剰なメモリを消費する貪欲なアプリケーションは非効率的であり、他のアプリケーションに悪影響を及ぼし、多くの場合、メモリ、CPU、またはより大きな仮想マシンなどの追加リソースの要求が必要になります。
図 1 – 従来のマルチスレッド
I/O 操作は現代のシステムに不可欠であり、貪欲な動作を防ぐには I/O 操作を効率的に管理することが最も重要です。リアクティブ システムはノンブロッキング I/O を採用し、少数の OS スレッドで多数の同時 I/O 操作を処理できるようにします。
ノンブロッキング I/O には大きな利点がありますが、従来のフレームワークとは異なる新しい実行モデルが導入されます。リアクティブ プログラミングは、ブロック操作中にアイドル状態になるプラットフォーム スレッドの非効率性を軽減するため、この問題に対処するために登場しました (図 2)。
図 2 – リアクティブ イベント ループ
Quarkus は、Eclipse Vert.x と Netty を活用したリアクティブ エンジンを活用し、ノンブロッキング I/O インタラクションを促進します。 Mutiny は、Quarkus でリアクティブなコードを記述するための推奨アプローチであり、受信したイベントによってリアクションがトリガーされるイベント駆動型のパラダイムを採用しています。
Mutiny は 2 つのイベント駆動型と遅延型を提供します。
リアクティブ システムには利点がありますが、開発中にいくつかの課題に直面しました。
「確かに、読み取り時間と書き込み時間の比率は 10 対 1 をはるかに超えています。私たちは新しいコードを書く努力の一環として常に古いコードを読んでいます。...[したがって] 読みやすくすることで、書きやすいです。」
― Robert C. Martin、クリーン コード: アジャイル ソフトウェア クラフトマンシップのハンドブック
複雑さを説明するために、Mutiny を使用したリアクティブ コードの例を次に示します。
Multi.createFrom().ticks().every(Duration.ofSeconds(15)) .onItem().invoke(() - > Multi.createFrom().iterable(configs()) .onItem().transform(configuration - > { try { return Tuple2.of(openAPIConfiguration, RestClientBuilder.newBuilder() .baseUrl(new URL(configuration.url())) .build(MyReactiveRestClient.class) .getAPIResponse()); } catch (MalformedURLException e) { log.error("Unable to create url"); } return null; }).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > { AtomicInteger callbackCount = new AtomicInteger(); return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples) .subscribe().with(tuple - > tuple.getItem2().subscribe().with(response - > { emitter.emit(callbackCount.incrementAndGet()); if (callbackCount.get() == tuples.size()) { emitter.complete(); } }) )); }).subscribe().with(s - > {}, Throwable::printStackTrace, () - > doSomethingUponComplete())) .subscribe().with(aLong - > log.info("Tic Tac with iteration: " + aLong));
Java エコシステムの最近の開発である Project Loom は、操作のブロックに関連する問題を軽減すると約束しています。 Project Loom は、ハードウェアを変更せずに何千もの仮想スレッドを作成できるようにすることで、多くの場合、事後対応型のアプローチの必要性を排除できる可能性があります。
「Project Loom はリアクティブ プログラミングを廃止しようとしている」
―ブライアン・ゲッツ
結論として、プロジェクトの長期的な保守可能性に対する実用的なアプローチとして、リアクティブ アーキテクチャ スタイルから脱却するという決定を下しました。リアクティブ システムには潜在的な利点がありますが、私たちの特定の状況では、リアクティブ システムがチームにもたらした課題の方が利点を上回りました。
重要なのは、この変更によってパフォーマンスが損なわれることはありませんでした。これは、適切に設計された非リアクティブ (命令的) アーキテクチャが、このケースのリアクティブ アーキテクチャに伴う複雑さを伴うことなく、必要なパフォーマンスを提供できることを示しているため、肯定的な結果です。
私たちは将来に向けて、機能的なだけでなく、あらゆる経験レベルの開発者にとって理解しやすく保守しやすいコードベースを構築することに引き続き重点を置いています。これにより、開発時間が短縮されるだけでなく、チーム内でのコラボレーションと知識の共有が促進されます。
以下のグラフでは、X 軸は進化に伴うコードベースの複雑さの増加を表し、Y 軸はこれらの開発上の変更に必要な時間を表しています。
以上がコードからリアクティブ システム アーキテクチャを削除したのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。