同様に、避けるべき設計パターンはありますか?
8 に答える
信頼できるソフトウェアを作成するための 1 つのアプローチは、クラッシュのみのソフトウェアです。
クラッシュ専用ソフトウェアは、安全にクラッシュし、迅速に回復するソフトウェアです。停止する唯一の方法はクラッシュすることであり、開始する唯一の方法は回復することです。クラッシュのみのシステムは、再試行可能な要求と通信するクラッシュのみのコンポーネントで構成されています。障害は、障害のあるコンポーネントをクラッシュして再起動し、タイムアウトになった要求を再試行することによって処理されます。結果として得られるシステムは、多くの場合、より堅牢で信頼性が高くなります。これは、クラッシュ リカバリが後付けではなく、開発プロセスの第一級の市民であり、明示的なシャットダウンのための追加のコード (および関連するインターフェイスとバグ) が不要になるためです。すべてのソフトウェアは安全にクラッシュし、迅速に回復できる必要がありますが、クラッシュのみのソフトウェアはこれらの品質を備えていなければなりません。
違う:
...そして、ストレージサーバーがあります
良い:
...そして、(複数の) ストレージ サーバーのファームがあり、その前に (複数の) ロード バランサーがあります。
すべての前にロードバランサーを配置します。現時点では 4 つのバックエンドを持つことができますが、将来的には 400 になる可能性があるため、バックエンドを使用するすべてのアプリではなく、LB でのみ管理するのが賢明です。
複数レベルのキャッシュを使用します。
高速化に関する一般的なソリューションを探します (memcached など)。
システムを更新する場合は、部分ごとに、複数の小さなステップに分けて更新してください。1 つの大きなステップ (古いものをオフにし、新しいものをオンにして、それが機能することを祈る) でそれを行うと、ほとんどの場合失敗します。
storage-lb.servicename
すべてのストレージ ロードバランサーのアドレスに解決されるものには DNS 名を使用します。追加したい場合は、dns を変更するだけで、すべてのサービスが自動的に使用を開始します。複雑にしないでおく。依存するシステムが多ければ多いほど、サービスが影響を受けます。
私が理解しているように、あなたはHAアーキテクチャの一部であるJavaアプリケーションで使用する特定のパターンを探しています。もちろん、使用できるパターンやベストプラクティスは多数ありますが、これらは実際には「HAパターン」ではありません。むしろ、それらは多くのコンテキストで利用できる優れたアイデアです。
私が言おうとしているのは、これだと思います。高可用性アーキテクチャは、多数の小さなパーツで構成されています。これらの小さなパーツの1つを選んで調べると、この小さなコンポーネントに魔法のHA属性がないことがわかるでしょう。他のすべてのコンポーネントを調べると、同じことがわかります。それは、それらがインテリジェントな方法で組み合わされて、HAアプリケーションになるときです。
HAアプリケーションは、最初から最悪の事態を計画するアプリケーションです。「このコンポーネントは非常に安定しているため、追加の冗長性は必要ありません」という観点から考えると、おそらくHAアーキテクチャではありません。結局のところ、予測した問題のシナリオを処理するのは簡単です。それはあなたを驚かせるものであり、システムをダウンさせます。
これらすべてにもかかわらず、HAコンテキストで特に役立つパターンがあります。それらの多くは、MartinFowlerによる古典的な本「PatternsofEnterpriseApplicationArchitecture」に文書化されています。
「高可用性」を「ゼロ ダウンタイム」として解釈しています。これは、他の SE の質問に従って実装できます。
- A/B スイッチ: (ローリング アップグレード + フォールバック メカニズム)
- 並列展開 – Apache Tomcat: (Web アプリケーションのみ)
- 遅延ポート バインド
- 高度なポート バインド
これらの概念のいくつかを使用して、上記のアプローチを補完する、ソフトウェアの観点から高可用性システムの設計パターンを考え出します。
使用するパターン:
プロキシ オブジェクトを用意すると、プロキシがリクエストのリダイレクト先を決定します。バージョン 1 とバージョン 2 のソフトウェアがあるとします。クライアントが古いプロトコルで接続している場合は、クライアントをバージョン 1 ソフトウェアにリダイレクトします。新しいクライアントはバージョン 2 に直接接続できます。Proxy は、新しいバージョンのソフトウェアをレンダリングするための Factory メソッドまたは AbstractFactory のいずれかを持つことができます。
アルゴリズムのファミリから 1 つのアルゴリズムを選択することにより、実行時にアルゴリズムを変更できます。航空会社を例にとると、トラフィックがピークでない月とピークの月に、DiscountFare アルゴリズムと NormalFare アルゴリズムを切り替えることができます。
実行時にオブジェクトの動作を変更できます。新しいクラスを追加し、追加の責任を飾ります。
バージョン 1 とバージョン 2 の間でインターフェイスまたはコントラクトを変更する場合に役立ちます。アダプターは、古いクライアントと新しいクライアントの両方の要求に適切に応答します。
一般的なガイドライン:
- オブジェクト間の疎結合
- アプリケーションでSOLIDの原則に従う
理解を深めるために、上記のパターンについてソース作成 Web サイトの記事を参照してください。
使用しないもの:
設計パターンとは別に、アプリケーションのダウンタイムをゼロにするには、いくつかの予防策を講じる必要があります。
- システムに単一障害点を導入しないでください。
- 分散キャッシュ (Terracotta など) /ロックを控えめに使用します。
- サービス間のハード カップリングを削除します。メッセージング バス/フレームワーク (JMS、ActiveMQ など) を使用して、サービス間の密結合を取り除きます。
高可用性は、コーディング規則よりも、ハードウェアの可用性と冗長性に関係しています。ほとんどすべての HA ケースで使用するパターンがいくつかあります。データベース オブジェクトにシングルトン パターンを選択し、ファクトリ パターンを使用してシングルトンを作成します。ファクトリは、データベースの可用性の問題を処理するロジックを持つことができます (ほとんどの可用性の問題はここで発生します)。たとえば、マスターがダウンしている場合は、マスターが復旧するまで、読み取りと書き込みの両方のために 2 番目のマスターに接続します。これらが最も活用されているパターンかどうかはわかりませんが、私のコードでは最も活用されています。
もちろん、このロジックは __construct メソッドで処理できますが、ファクトリ パターンを使用すると、データベース接続の問題を処理する方法のコードと意思決定ロジックをより適切に制御できます。ファクトリを使用すると、シングルトン パターンをより適切に処理できます。
デコレータ パターンとオブザーバ パターンは絶対に避けます。どちらもコードが複雑になり、保守が困難になります。これらはニーズに最適な選択である場合もありますが、ほとんどの場合はそうではありません。