1. マイクロサービスを理解する
1. 単一構造
ビジネスのすべての機能は 1 つのプロジェクトで開発され、展開用に 1 つのパッケージにパッケージ化されます。
アドバンテージ
- シンプルな構造
- 導入コストが低い
欠点がある
- 高結合
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-fPfsQXAn-1689593800699)(https://picture.wangkay.tech/blog/image-20230717100100447.png)]
2. 分散アーキテクチャ
システムは業務機能ごとに分割され、各業務モジュールはサービスと呼ばれる独立したプロジェクトとして開発されます。
アドバンテージ
- カップリングを減らす
- サービスのアップグレードと拡張に貢献
3. マイクロサービス
マイクロサービスは、適切に設計されたアーキテクチャを備えた分散アーキテクチャ ソリューションです。マイクロサービス アーキテクチャの特徴は次のとおりです。
- 単一の責任: マイクロサービスの分割粒度は小さく、各サービスは固有のビジネス機能に対応するため、単一の責任を達成し、繰り返しのビジネス開発を回避できます。
- サービス指向: マイクロサービスはビジネス インターフェイスを外部に公開します
- 自律性: 独立したチーム、独立したテクノロジー、独立したデータ、独立した展開
- 強力な分離: サービス コールは分離され、耐障害性があり、連鎖的な問題を回避するために機能が低下します。
4. マイクロサービス構造
マイクロサービス ソリューションを実装するには技術的なフレームワークが必要であり、世界中のインターネット企業が独自のマイクロサービス実装技術を積極的に試しています。中国で最もよく知られているのは SpringCloud と Alibaba の Dubbo です。
5. 企業のニーズ
二、スプリングクラウド
- SpringCloudは現在、中国で最も広く使用されているマイクロサービス フレームワークです。
- SpringCloud は、さまざまなマイクロサービス機能コンポーネントを統合し、SpringBoot に基づいてこれらのコンポーネントの自動アセンブリを実現するため、すぐに使用できる優れたエクスペリエンスを提供します。
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) サービスコール関係
- サービス プロバイダー: インターフェイスを他のマイクロサービス呼び出しに公開します。
- サービスコンシューマ: 他のマイクロサービスによって提供されるインターフェイスを呼び出す
- プロバイダーとコンシューマーの役割は実際には相対的なものです
- サービスはサービスプロバイダーとサービスコンシューマーの両方になることができます
3. エウレカ登録センター
1. エウレカの紹介
Eureka は、Netflix のオープンソース サービス登録および検出コンポーネントであり、分散システムでマイクロサービス アーキテクチャを構築するためのコア ツールの 1 つです。Eureka レジストリの主な目標は、高可用性、動的な検出、サービス間の負荷分散を実現することです。
マイクロサービス アーキテクチャでは、システムが複数の小さなサービスに分割され、それぞれが独立したプロセスで実行され、相互に連携してシステム全体の機能を提供します。これらのサービスは、分散環境で通信および検出できる必要があり、これを行うのが Eureka レジストリです。
Eureka レジストリには 2 つの主要コンポーネントがあります。
-
Eureka Server: これはレジストリの中核であり、クラスター内の 1 つ以上のサーバー上で実行されます。各サービス(マイクロサービス アプリケーション)は、サービス名、ネットワーク アドレス、健全性ステータスなどの独自の情報を Eureka Server に登録します。Eureka Server は、登録されているすべてのサービス情報を記録するサービス レジストリを維持します。
-
Eureka Client: これはマイクロサービス アプリケーションであり、サービス コンシューマとして自身を Eureka Server に登録し、定期的にハートビートを送信してその健全性状態を示します。同時に、エウレカクライアントはエウレカサーバーからサービスレジストリも取得し、他のサービスを呼び出す必要がある場合にはレジストリから該当サービスの情報を取得してサービス間の通信を実現します。
Eureka レジストリには次の主な機能があります。
-
高可用性: Eureka Server は、登録センターの高可用性を確保するためにクラスターでの実行をサポートしており、ノードに障害が発生した場合でも、他のノードがサービスの登録および検出機能を提供できます。
-
動的検出: サービスの登録と検出は動的です。新しいサービスがオンラインまたはオフラインになると、Eureka Server は適時にレジストリを感知して更新できるため、他のサービスは最新のサービス情報を動的に取得できます。
-
負荷分散: 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 サービスを構築する手順は次のとおりです。
-
プロジェクトを作成し、spring-cloud-starter-netflix-eureka-server の依存関係を導入する
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
スタートアップクラスを記述し、 @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); } }
-
application.yml ファイルを追加し、次の構成を記述します。
server: port: 10086spring: application: name: eurekaserver eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka/
-
サービスを開始する
マイクロサービスを開始し、ブラウザでアクセスします: http://127.0.0.1:10086
次の結果が成功することを確認してください。
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 スタートアップ構成を追加し、ユーザー サービスを開始します。
まず、元のユーザー サービスの起動設定をコピーします。
上記では、変更オプションの [VM の追加] オプションをチェックして追加する必要があります。-Dserver.port=8082
2 つのユーザー サービス インスタンスを開始します。
4) 完全なサービスプルインオーダーサービス
サービス プルとは、サービス名に基づいてサービス リストを取得し、サービス リストに対して負荷分散を実行することです。
-
OrderService のコードを変更し、アクセスする URL パスを変更し、IP とポートの代わりにサービス名を使用します。
String url = "http://userservice/user/" + order.getUserId();
-
order-service プロジェクトのスタートアップ クラス OrderApplication の RestTemplate に負荷分散アノテーションを追加します。
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
Spring は、サービス名 userservice に従って eureka-server 側からインスタンス リストを取得し、負荷分散を完了するのに自動的に役立ちます。
4. リボンの負荷分散
1. 負荷分散の原理
1)ロードバランサーインターセポート
ここでの intercept メソッドはユーザーの HttpRequest リクエストをインターセプトし、いくつかのことを実行します。
request.getURI()
: リクエスト URI を取得します。この場合は http://user-service/user/8 です。originalUri.getHost()
: URI パスのホスト名を取得します。これは実際にはサービス ID です。user-service
this.loadBalancer.execute()
: サービス ID とユーザーのリクエストを処理します。
こちらthis.loadBalancer
がLoadBalancerClient
そのタイプで、引き続きフォローしていきます。
2)ロードバランサークライアント
- getLoadBalancer(serviceId): サービス ID に従って ILoadBalancer を取得します。ILoadBalancer はサービス ID を eureka に取り、サービス リストを取得して保存します。
- getServer(loadBalancer): 組み込みの負荷分散アルゴリズムを使用して、サービス リストから 1 つを選択します。この例では、ポート 8082 上のサービスが取得されたことがわかります。
3) 負荷分散戦略 IRule
4) まとめ
SpringCloudRibbon の最下層はインターセプターを使用して、RestTemplate によって送信されたリクエストをインターセプトし、アドレスを変更します。画像でまとめるとこうなります。
基本的なプロセスは次のとおりです。
- 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 にはさまざまな実装クラスがあります。
さまざまなルールの意味は次のとおりです。
組み込みの負荷分散ルールクラス | ルールの説明 |
---|---|
ラウンドロビンルール | サービスのリストをポーリングしてサーバーを選択するだけです。これは、リボンのデフォルトの負荷分散ルールです。 |
可用性フィルタリングルール | 次の 2 つのサーバーは無視してください。 (1) デフォルトでは、このサーバーが 3 回接続に失敗すると、このサーバーは「短絡」状態に設定されます。短絡状態は 30 秒間続き、再び接続に失敗すると、短絡の継続時間は幾何級数的に増加します。(2) 同時実行性が高すぎるサーバー。サーバーの同時接続数が多すぎる場合、AvailabilityFilteringRule ルールで構成されたクライアントもそれを無視します。同時接続数の上限は、クライアントの ..ActiveConnectionsLimit プロパティによって構成できます。 |
WeightedResponseTimeRule | 各サーバーに重み値を割り当てます。サーバーの応答時間が長いほど、このサーバーの重みは低くなります。このルールはサーバーをランダムに選択し、この重み値はサーバーの選択に影響します。 |
ゾーン回避ルール | サーバーの選択は、その地域で利用可能なサーバーに基づいて行われます。ゾーンを使用してサーバーを分類します。このゾーンは、コンピューター室、ラックなどとして理解できます。次に、ゾーン内の複数のサービスをポーリングします。 |
BestAvailableルール | 短絡しているサーバーを無視し、同時実行性の低いサーバーを選択します。 |
ランダムルール | 利用可能なサーバーをランダムに選択します。 |
再試行ルール | 再試行メカニズムの選択ロジック |
デフォルトの実装は、ポーリング スキームである ZoneAvoidanceRule です。
カスタム負荷分散戦略
負荷分散ルールは、IRule 実装を定義することで変更できます。方法は 2 つあります。
- コード メソッド: order-service の OrderApplication クラスで、新しい IRule を定義します。
@Bean
public IRule randomRule(){
return new RandomRule();
}
- 構成ファイルによる方法: order-service の application.yml ファイルで、新しい構成を追加すると、ルールを変更することもできます。
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
通常、デフォルトの負荷分散ルールは変更せずに使用されることに注意してください。
3. ハンガーローディング
リボンはデフォルトで遅延読み込みを使用します。つまり、LoadBalanceClient は最初にアクセスされたときにのみ作成され、要求時間は非常に長くなります。
ハンガー ロードは、最初の訪問にかかる時間を短縮するために、プロジェクトの開始時に作成されます。次の構成を通じてハンガー ロードを有効にします。
ribbon:
eager-load:
enabled: true
clients: userservice