マイクロサービス Day1 - マイクロサービスを始める

画像-20230717095604286

画像-20230717095712864


1. マイクロサービスを理解する

1. 単一構造

ビジネスのすべての機能は 1 つのプロジェクトで開発され、展開用に 1 つのパッケージにパッケージ化されます。

アドバンテージ

  • シンプルな構造
  • 導入コストが低い

欠点がある

  • 高結合

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-fPfsQXAn-1689593800699)(https://picture.wangkay.tech/blog/image-20230717100100447.png)]

2. 分散アーキテクチャ

システムは業務機能ごとに分割され、各業務モジュールはサービスと呼ばれる独立したプロジェクトとして開発されます。

アドバンテージ

  • カップリングを減らす
  • サービスのアップグレードと拡張に貢献

画像-20230717100340895

3. マイクロサービス

マイクロサービスは、適切に設計されたアーキテクチャを備えた分散アーキテクチャ ソリューションです。マイクロサービス アーキテクチャの特徴は次のとおりです。

  • 単一の責任: マイクロサービスの分割粒度は小さく、各サービスは固有のビジネス機能に対応するため、単一の責任を達成し、繰り返しのビジネス開発を回避できます。
  • サービス指向: マイクロサービスはビジネス インターフェイスを外部に公開します
  • 自律性: 独立したチーム、独立したテクノロジー、独立したデータ、独立した展開
  • 強力な分離: サービス コールは分離され、耐障害性があり、連鎖的な問題を回避するために機能が低下します。

4. マイクロサービス構造

マイクロサービス ソリューションを実装するには技術的なフレームワークが必要であり、世界中のインターネット企業が独自のマイクロサービス実装技術を積極的に試しています。中国で最もよく知られているのは SpringCloud と Alibaba の Dubbo です。

5. 企業のニーズ

画像-20230717101205179

二、スプリングクラウド

  • SpringCloudは現在、中国で最も広く使用されているマイクロサービス フレームワークです。
  • SpringCloud は、さまざまなマイクロサービス機能コンポーネントを統合し、SpringBoot に基づいてこれらのコンポーネントの自動アセンブリを実現するため、すぐに使用できる優れたエクスペリエンスを提供します。
    画像-20230717101412724

1. サービス分割

サービス分割に関する考慮事項

  • 単一の責任: 異なるマイクロサービス、同じビジネスを繰り返し開発しない
  • データの独立性: 他のマイクロサービスのデータベースにアクセスしない
  • サービス指向: 他のマイクロサービスが呼び出すためのインターフェイスとしてビジネスを公開します。

2. リモート呼び出し (注文 ID に従って注文関数をクエリ)

要件: 注文 ID に従って注文をクエリする際に、注文が属するユーザー情報を返します。

[外部リンク画像の転送に失敗しました。ソース サイトには盗難防止リンク メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-OxFyPehL-1689593800699)(https://picture.wangkay.tech/blog/image-20230717102926142.png)]

(1) RestTemplateの登録

order-serviceのOrderApplicationにRestTemplateを登録する

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderApplication.class, args);
    } 

    @Bean
    public RestTemplate restTemplate(){
    
    
        return new RestTemplate();
    }
}

(2) サービスはリモートから RestTemplate を呼び出します

order-service の OrderService の queryOrderById メソッドを変更します。

@Service
public class OrderService {
    
    
    
    @Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
    
    
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // TODO 2.查询用户 
        String url = "http://localhost:8081/user/" +  order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user信息
        order.setUser(user);
        // 4.返回
        return order;
    }
}

(3) マイクロサービスの基本的な呼び出し方法

  • RestTemplateによって開始されたhttpリクエストに基づいたリモート呼び出しを実現します
  • http リクエストによって行われるリモート呼び出しは、相手の IP、ポート、インターフェイス パス、およびリクエスト パラメーターがわかっている限り、言語に依存しない呼び出しです。

(4) サービスコール関係

  1. サービス プロバイダー: インターフェイスを他のマイクロサービス呼び出しに公開します。
  2. サービスコンシューマ: 他のマイクロサービスによって提供されるインターフェイスを呼び出す
  3. プロバイダーとコンシューマーの役割は実際には相対的なものです
  4. サービスはサービスプロバイダーとサービスコンシューマーの両方になることができます

3. エウレカ登録センター

1. エウレカの紹介

Eureka は、Netflix のオープンソース サービス登録および検出コンポーネントであり、分散システムでマイクロサービス アーキテクチャを構築するためのコア ツールの 1 つです。Eureka レジストリの主な目標は、高可用性、動的な検出、サービス間の負荷分散を実現することです。

マイクロサービス アーキテクチャでは、システムが複数の小さなサービスに分割され、それぞれが独立したプロセスで実行され、相互に連携してシステム全体の機能を提供します。これらのサービスは、分散環境で通信および検出できる必要があり、これを行うのが Eureka レジストリです。

Eureka レジストリには 2 つの主要コンポーネントがあります。

  1. Eureka Server: これはレジストリの中核であり、クラスター内の 1 つ以上のサーバー上で実行されます。各サービス(マイクロサービス アプリケーション)は、サービス名、ネットワーク アドレス、健全性ステータスなどの独自の情報を Eureka Server に登録します。Eureka Server は、登録されているすべてのサービス情報を記録するサービス レジストリを維持します。

  2. Eureka Client: これはマイクロサービス アプリケーションであり、サービス コンシューマとして自身を Eureka Server に登録し、定期的にハートビートを送信してその健全性状態を示します。同時に、エウレカクライアントはエウレカサーバーからサービスレジストリも取得し、他のサービスを呼び出す必要がある場合にはレジストリから該当サービスの情報を取得してサービス間の通信を実現します。

Eureka レジストリには次の主な機能があります。

  1. 高可用性: Eureka Server は、登録センターの高可用性を確保するためにクラスターでの実行をサポートしており、ノードに障害が発生した場合でも、他のノードがサービスの登録および検出機能を提供できます。

  2. 動的検出: サービスの登録と検出は動的です。新しいサービスがオンラインまたはオフラインになると、Eureka Server は適時にレジストリを感知して更新できるため、他のサービスは最新のサービス情報を動的に取得できます。

  3. 負荷分散: Eureka Client は、サービス レジストリ内の情報に従って負荷分散を実装し、複数の利用可能なサービス プロバイダー間でリクエストを分散し、システムのスケーラビリティとパフォーマンスを向上させることができます。

Eureka レジストリは Netflix のマイクロサービス アーキテクチャで重要な役割を果たしており、そのオープンソースの性質により、他の多くの企業や開発者もプロジェクトでのサービスの登録と検出のためのソリューションとして Eureka を採用しています。Eureka は過去に広く使用されてきましたが、現在の技術開発では、Consul、etcd など、同様の機能を備えた他のレジストリ ソリューションも登場していることは注目に値します。

2.エウレカ役

  • 消費者はサービスプロバイダーに関する具体的な情報をどのように入手すればよいでしょうか?
    • サービス提供者はサービス開始時に自身の情報をeurekaに登録します
    • エウレカはこの情報を保存します
    • 消費者はサービス名に従って eureka からプロバイダー情報を取得します
  • サービスプロバイダーが複数ある場合、消費者はどのように選択すればよいでしょうか?
    • サービスコンシューマは負荷分散アルゴリズムを使用してサービスリストからサービスを選択します
  • 消費者はサービス提供者の健康状態をどのように認識しているのでしょうか?
    • サービス プロバイダーは、ヘルス ステータスを報告するために 30 秒ごとに EurekaServer にハートビート リクエストを送信します。
    • eurekaはレコードサービスリスト情報を更新し、異常なハートビートを削除します
    • 消費者は最新情報を入手できる

Eureka アーキテクチャには、2 種類のマイクロサービス ロールがあります。

  • EurekaServer: サーバー、登録センター
    • サービス情報を記録する
    • ハートビートモニタリング
  • EurekaClient: クライアント
    • プロバイダー: サービスプロバイダー (例: ユーザーサービス)
      • エウレカサーバーに自分の情報を登録する
      • 30 秒ごとにハートビートを EurekaServer に送信します
    • Consumer: サービス消費者 (例: order-service)
      • サービス名に従ってEurekaServerからサービスリストを取得します。
      • サービスリストに基づいて負荷分散を行い、マイクロサービスを選択した後にリモート呼び出しを開始します。

[外部リンク画像の転送に失敗しました。ソース サイトには盗難防止リンク メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-88TXJy2e-1689593800699)(https://picture.wangkay.tech/blog/image-20230717142428805.png)]

3. エウレカサーバーの構築

EurekaServer サービスを構築する手順は次のとおりです。

  1. プロジェクトを作成し、spring-cloud-starter-netflix-eureka-server の依存関係を導入する

    画像-20230717151327511

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. スタートアップクラスを記述し、 @EnableEurekaServer アノテーションを追加します

    eureka-server サービスの起動クラスを作成するには、必ず @EnableEurekaServer アノテーションを追加して、eureka の登録センター機能を有効にしてください。

    package cn.itcast.eureka;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
          
          
        public static void main(String[] args) {
          
          
            SpringApplication.run(EurekaApplication.class, args);
        }
    }
    
  3. application.yml ファイルを追加し、次の構成を記述します。

    server:  port: 10086spring:
      application:
        name: eurekaserver
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka/
    
  4. サービスを開始する

マイクロサービスを開始し、ブラウザでアクセスします: http://127.0.0.1:10086

次の結果が成功することを確認してください。

画像-20230717152406414

4. サービス登録

次に、eureka-serverにuser-serviceを登録します。

1) 依存関係を導入する

user-service の pom ファイルに、次の eureka-client 依存関係を導入します。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2) 設定ファイル

user-service で、application.yml ファイルを変更し、サービス名と eureka アドレスを追加します。

spring:
  application:
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3) 複数のユーザーサービスインスタンスを開始する

サービスに複数のインスタンスがあるシナリオを示すために、SpringBoot スタートアップ構成を追加し、ユーザー サービスを開始します。

まず、元のユーザー サービスの起動設定をコピーします。

画像-20230717153021479

画像-20230717165615969

上記では、変更オプションの [VM の追加] オプションをチェックして追加する必要があります。-Dserver.port=8082

画像-20230717165713001

2 つのユーザー サービス インスタンスを開始します。

画像-20230717171459086

画像-20230717171414195

4) 完全なサービスプルインオーダーサービス

サービス プルとは、サービス名に基づいてサービス リストを取得し、サービス リストに対して負荷分散を実行することです。

  1. OrderService のコードを変更し、アクセスする URL パスを変更し、IP とポートの代わりにサービス名を使用します。

    String url = "http://userservice/user/" + order.getUserId();
    

  2. order-service プロジェクトのスタートアップ クラス OrderApplication の RestTemplate に負荷分散アノテーションを追加します。

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
          
          
        return new RestTemplate();
    }
    

Spring は、サービス名 userservice に従って eureka-server 側からインスタンス リストを取得し、負荷分散を完了するのに自動的に役立ちます。

4. リボンの負荷分散

1. 負荷分散の原理

画像-20230717174345639

1)ロードバランサーインターセポート

画像-20230717174646863

ここでの intercept メソッドはユーザーの HttpRequest リクエストをインターセプトし、いくつかのことを実行します。

  • request.getURI(): リクエスト URI を取得します。この場合は http://user-service/user/8 です。
  • originalUri.getHost(): URI パスのホスト名を取得します。これは実際にはサービス ID です。user-service
  • this.loadBalancer.execute(): サービス ID とユーザーのリクエストを処理します。

こちらthis.loadBalancerLoadBalancerClientそのタイプで、引き続きフォローしていきます。

2)ロードバランサークライアント

画像-20230717191213064

  • getLoadBalancer(serviceId): サービス ID に従って ILoadBalancer を取得します。ILoadBalancer はサービス ID を eureka に取り、サービス リストを取得して保存します。
  • getServer(loadBalancer): 組み込みの負荷分散アルゴリズムを使用して、サービス リストから 1 つを選択します。この例では、ポート 8082 上のサービスが取得されたことがわかります。

3) 負荷分散戦略 IRule

画像-20230717191248461

画像-20230717191257955

画像-20230717191306387

4) まとめ

SpringCloudRibbon の最下層はインターセプターを使用して、RestTemplate によって送信されたリクエストをインターセプトし、アドレスを変更します。画像でまとめるとこうなります。

画像-20230717191419279

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

  • RestTemplate リクエストをインターセプト http://userservice/user/1
  • ibbonLoadBalancerClient は、リクエスト URL からサービス名を取得します。これは user-service です。
  • DynamicServerListLoadBalancer は、ユーザーサービスに従って eureka からサービスリストを取得します。
  • eureka はリスト、localhost:8081、localhost:8082 を返します。
  • IRule は組み込みの負荷分散ルールを使用します。リストから 1 つを選択します (localhost:8081 など)。
  • ibbonLoadBalancerClient はリクエスト アドレスを変更し、userservice を localhost:8081 に置き換え、http://localhost:8081/user/1 を取得して、実際のリクエストを開始します。

2. 負荷分散戦略

負荷分散戦略

負荷分散のルールは IRule インターフェイスで定義され、IRule にはさまざまな実装クラスがあります。

画像-20230717191607976

さまざまなルールの意味は次のとおりです。

組み込みの負荷分散ルールクラス ルールの説明
ラウンドロビンルール サービスのリストをポーリングしてサーバーを選択するだけです。これは、リボンのデフォルトの負荷分散ルールです。
可用性フィルタリングルール 次の 2 つのサーバーは無視してください。 (1) デフォルトでは、このサーバーが 3 回接続に失敗すると、このサーバーは「短絡」状態に設定されます。短絡状態は 30 秒間続き、再び接続に失敗すると、短絡の継続時間は幾何級数的に増加します。(2) 同時実行性が高すぎるサーバー。サーバーの同時接続数が多すぎる場合、AvailabilityFilteringRule ルールで構成されたクライアントもそれを無視します。同時接続数の上限は、クライアントの ..ActiveConnectionsLimit プロパティによって構成できます。
WeightedResponseTimeRule 各サーバーに重み値を割り当てます。サーバーの応答時間が長いほど、このサーバーの重みは低くなります。このルールはサーバーをランダムに選択し、この重み値はサーバーの選択に影響します。
ゾーン回避ルール サーバーの選択は、その地域で利用可能なサーバーに基づいて行われます。ゾーンを使用してサーバーを分類します。このゾーンは、コンピューター室、ラックなどとして理解できます。次に、ゾーン内の複数のサービスをポーリングします。
BestAvailableルール 短絡しているサーバーを無視し、同時実行性の低いサーバーを選択します。
ランダムルール 利用可能なサーバーをランダムに選択します。
再試行ルール 再試行メカニズムの選択ロジック

デフォルトの実装は、ポーリング スキームである ZoneAvoidanceRule です。

カスタム負荷分散戦略

負荷分散ルールは、IRule 実装を定義することで変更できます。方法は 2 つあります。

  1. コード メソッド: order-service の OrderApplication クラスで、新しい IRule を定義します。
@Bean
public IRule randomRule(){
    
    
    return new RandomRule();
}
  1. 構成ファイルによる方法: order-service の application.yml ファイルで、新しい構成を追加すると、ルールを変更することもできます。
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

通常、デフォルトの負荷分散ルールは変更せずに使用されることに注意してください。

3. ハンガーローディング

リボンはデフォルトで遅延読み込みを使用します。つまり、LoadBalanceClient は最初にアクセスされたときにのみ作成され、要求時間は非常に長くなります。

ハンガー ロードは、最初の訪問にかかる時間を短縮するために、プロジェクトの開始時に作成されます。次の構成を通じてハンガー ロードを有効にします。

ribbon:
  eager-load:
    enabled: true
    clients: userservice

おすすめ

転載: blog.csdn.net/qq_54351538/article/details/131773486