SpringCloud学習ノート-サービスフォールトトレランス保護

4388 ワード

サービスフォールトトレランス保護
前のマイクロサービスアーキテクチャの学習では、独自の登録センタークラスタ、サービスプロバイダクラスタ、クライアントリクエストを処理する負荷のバランスが取れていますが、マイクロサービスの世界にはまず、サードパーティのサービスを信じないという黄金の法則があります.すなわち、マイクロサービスではシステムが複数のモジュールに分割され、モジュールの増加に伴い、システムが故障する確率も指数倍に増加し、よく見られる異常、例えばネットワークタイムアウト、コードバグなどは、あるサービスの麻痺によって複数のシステムがタイムアウトする可能性があり、事前に有効な防犯措置がなければ、遅い応答やダウンタイムなどの問題が発生する可能性が高い.マイクロサービス遮断器モードが誕生しました
ブレーカモード
回路を学んだことのある人は、回路遮断器を聞いたことがあるはずですが、実は回路上で保護の役割を果たしている装置で、回路が短絡して過負荷になった場合、回路を急速に溶断し、過負荷による発熱や火災などのより深刻な後続の問題を防止することができます.このシーンはマイクロサービスに適しています.システム全体のあるサービスに異常が発生した場合、それに関連するサービスにも異常が発生する可能性があります.異常はウイルス伝播のように迅速にシステム全体に影響し、溶断メカニズムがあれば、要求に異常ノードが存在する場合、呼び出し元の明確な異常情報を直接返すことができ、リスクを低減することができる.
クイックスタート
私たちは依然として前に構築したマイクロサービスシステムに沿って、私たちの登録センターサービスeureka-serverを起動して、ポート番号1111、更に2つのサービスユニットhello-serviceを起動して、ポート番号はそれぞれ2221と2222で、更に1つのribbonクライアントを起動して、ポート番号3333、この時直接私たちの前に書いたインタフェースアドレスを訪問しますhttp://localhost:3333/ribbon-consumer、何回か繰り返しリフレッシュすると、ページには負荷等化後のポート番号2212と2222が順番に表示され、マイクロサービスシステム全体が正常に稼働していることを示します.この場合、ポート番号2211のサービスユニットを閉じるだけで、次回サーバに要求された要求が発行されると短い待ち時間がかかり、インタフェースは異常情報を放出します.
{
    "timestamp": "2020-02-12T15:18:55.004+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "I/O error on GET request for \" http://hello-service/hello\ ": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect",
    "path": "/ribbon-consumer"
}

説明この時、私たちはすでにサービスが切れていて、私は地元でpostを使ってデバッグして、今回のインタフェースは2.06 sを費やして、2秒の時間は長くないかもしれませんが、もしこのサービスが毎秒何千回も呼び出されたら?あるいは、現在ピーク時であり、2秒応答のインタフェースは災害的な結果をもたらすのに十分です.
次に、マイクロサービス遮断器:Spring Cloud Hystrixを導入します.
ribbon-consumerプロジェクトのbuild.gradleファイルに依存を導入し、アプリケーションクラスで注記@EnableCircuitBreakerを使用して溶断機能をオンにします.
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'

同時に、私たちのコードを改善します.小さなdemoですが、多くのルールは守らなければなりません.例えば、ビジネスコードはcontrollerに書かないでください.ここでは、以前のコードをserviceクラスのhelloメソッドに移し、@HystrixCommand注釈をメソッドに追加し、コールバックメソッド(fallback Method=「helloFallback」)を明記します.
@Service
public class HelloService {
    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "helloFallback")
    public String hello() {
        return restTemplate.getForEntity("http://hello-service/hello", String.class).getBody();
    }

    private String fallback() {
        return "system error!";
    }
}

コントロールクラスを変更する方法に対応して、HelloServiceを再注入して呼び出します.
@RestController
public class ConsumerController {
    @Autowired
    HelloService helloService;

    @RequestMapping(value = "/ribbon-consumer")
    public String helloConsumer() {
        return helloService.hello();
    }
}

このときribbon consumerプロジェクトを再実行し、ポート番号2221のサービスユニットがサービスを終了した状態を維持します.今回はpostman呼び出しの結果がプリセットの戻り値system errorになることを見てみましょう.もちろん、コールバック関数では、友好的なエラープロンプト情報をカスタマイズしたり、追加のビジネス処理を行ったりすることができます.さらに、サービスダウンによる使用不可に加えて、現在のシステムが非常に大きなトラフィック要求やその他の異常に耐えているため、インタフェースの応答時間が長すぎる可能性があります.hytrixは同様に遮断の効果を達成することができます.hytrixのデフォルトの応答時間は2000ミリ秒で最も長いです.つまり、インタフェースの応答時間が2千ミリ秒を超えると、hytrixは現在のサービスが使用できないと考えられます.これにより、前のシミュレーションサーバのダウンタイムのように予め設定されたコールバック関数を呼び出すことができます.ここでは、以下のhello-serviceのコードを変更する必要があります./helloインタフェースにランダムな睡眠時間を加えて、応答時間が長すぎる問題をランダムにトリガし、ribbon-consumer呼び出しコードにインタフェース応答時間の長いログ印刷を追加する必要があります.以下はコード修正です.
int time = new Random().nextInt(5000);
Thread.sleep(time);
@Service
public class HelloService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "helloFallback")
    public String hello() {
        long start = System.currentTimeMillis();
        String res = restTemplate.getForEntity("http://hello-service/hello", String.class).getBody();
        LOGGER.info("hellor cost : {}ms", System.currentTimeMillis() - start);
        return res;
    }

    private String helloFallback() {
        return "system error!";
    }
}

再起動後もpostman呼び出しを継続し、コントロールバーの出力ログとインタフェースの戻り情報を観察することで、2000 msより大きいリクエストはすべてコールバック関数の戻りエラー情報を呼び出し、他のリクエストは正常に戻り、日常的に使用する過程で、合理的にリクエストにhytrixを加えることで、サービスダウンなどの要素による異常な問題を簡単に効果的に防止することができる.ログの記録とコールバック後の補償操作も覚えておいてください.