マイクロサービス入門 ---SpringCloud (1)
1. マイクロサービスを理解する
インターネット業界の発展に伴い、サービスに対する要件はますます高くなり、サービス アーキテクチャはモノリシック アーキテクチャから、現在一般的なマイクロサービス アーキテクチャへと徐々に進化しています。これらのアーキテクチャの違いは何ですか?
1.0.学習目標
マイクロサービス アーキテクチャの長所と短所を理解する
1.1. モノリシックアーキテクチャ
モノリシック アーキテクチャ: すべてのビジネス機能は 1 つのプロジェクトで開発され、パッケージとして展開されます。
モノリシック アーキテクチャの長所と短所は次のとおりです。
アドバンテージ:
- シンプルなアーキテクチャ
- 導入コストが低い
欠点:
- 高度な結合 (維持とアップグレードが困難)
1.2. 分散アーキテクチャ
分散アーキテクチャ: システムを業務機能ごとに分割し、各業務機能モジュールを独立したプロジェクトとして開発し、サービスと呼びます。
分散アーキテクチャの長所と短所:
アドバンテージ:
- サービス結合を減らす
- サービスのアップグレードと拡張に貢献
欠点:
- サービス呼び出し関係が複雑
分散アーキテクチャによりサービスの結合は軽減されますが、サービスを分割する際には考慮すべき問題がまだ多くあります。
- サービス分割の粒度を定義するにはどうすればよいですか?
- サービス間で通話するにはどうすればよいですか?
- サービス呼び出し関係を管理するにはどうすればよいですか?
人々は、分散アーキテクチャを制約するための一連の効果的な標準を開発する必要があります。
1.3.マイクロサービス
マイクロサービスのアーキテクチャ上の特徴:
- 単一の責任: マイクロサービスはより小さな粒度に分割されており、各サービスは固有のビジネス機能に対応し、単一の責任を実現します。
- 自律性: 独立したチーム、独立したテクノロジー、独立したデータ、独立した展開と配信
- サービス指向: サービスは、言語やテクノロジーに依存しない、統一された標準インターフェイスを提供します。
- 強力な分離: 問題の連鎖を避けるために、サービス コールは分離され、耐障害性があり、ダウングレードされる必要があります。
マイクロサービスの上記の特性は、実際に分散アーキテクチャの標準を設定し、サービス間の結合をさらに減らし、サービスの独立性と柔軟性を提供します。高い凝集性と低い結合性を実現します。
したがって、マイクロサービスは、優れたアーキテクチャ設計を備えた分散アーキテクチャ ソリューションであると考えることができます。
しかし、計画をどのように実行するのでしょうか? どのテクノロジースタックを選択すればよいでしょうか? 世界中のインターネット企業は、独自のマイクロサービス実装ソリューションを積極的に試しています。
中でもJava分野で最も注目を集めているのがSpring Cloudが提供するソリューションだ。
1.4.スプリングクラウド
SpringCloud は現在、中国で最も広く使用されているマイクロサービス フレームワークです。公式ウェブサイトのアドレス:https://spring.io/projects/spring-cloud。
SpringCloud は、さまざまなマイクロサービス機能コンポーネントを統合し、SpringBoot に基づいてこれらのコンポーネントの自動アセンブリを実装するため、すぐに使用できる優れたエクスペリエンスを提供します。
共通のコンポーネントには次のものがあります。
さらに、SpringCloud の最下層は SpringBoot に依存しており、次のようにバージョン互換性があります。
授業で学習したバージョンは Hoxton.SR10 なので、対応する SpringBoot のバージョンはバージョン 2.3.x です。
1.5. 概要
-
モノリシック アーキテクチャ: シンプルで便利、高度に結合されているが拡張性が低く、小規模プロジェクトに適しています。例: 学生管理システム
-
分散アーキテクチャ: 疎結合で拡張性が優れていますが、アーキテクチャは複雑で困難です。JD.com、Taobao などの大規模なインターネット プロジェクトに適しています。
-
マイクロサービス: 優れた分散アーキテクチャ ソリューション
① 利点: 分割粒度が小さく、サービスの独立性が高く、結合度が低い
② デメリット: アーキテクチャが非常に複雑なため、運用、保守、監視、展開がより困難になります。
-
SpringCloud は、さまざまな優れたマイクロサービス機能コンポーネントを統合した、マイクロサービス アーキテクチャのワンストップ ソリューションです
2. サービス分割とリモート通話
分散アーキテクチャはサービスの分割と切り離すことができず、マイクロサービスについても同様です。
2.1. サービス分割の原則
ここでは、マイクロサービスを分割する際のいくつかの原則を要約します。
- 異なるマイクロサービスに対して同じビジネスを繰り返し開発しないでください。
- マイクロサービス データは独立しており、他のマイクロサービスのデータベースにはアクセスしません
- マイクロサービスは、他のマイクロサービスが呼び出すためのインターフェイスとして独自のビジネスを公開できます。
2.2.サービス分割の例
プレコース資料のマイクロサービス クラウド デモを例に挙げると、その構造は次のとおりです。
Cloud-demo: 親プロジェクト、管理の依存関係
- order-service: 注文マイクロサービス、注文関連のビジネスを担当します。
- user-service: ユーザー関連のビジネスを担当するユーザー マイクロサービス
必要とする:
- 注文マイクロサービスとユーザー マイクロサービスは両方とも独自のデータベースを持ち、互いに独立している必要があります。
- 注文サービスとユーザー サービスは両方とも、Restful インターフェイスを外部に公開します。
- オーダー サービスがユーザー情報をクエリする必要がある場合、ユーザー サービスの Restful インターフェイスのみを呼び出すことができ、ユーザー データベースにクエリを実行することはできません。
2.2.1. SQL ステートメントのインポート
まず、事前授業資料によって提供されたcloud-order.sql
合計をcloud-user.sql
mysql にインポートします。
cloud-order テーブルは、cloud-user テーブルの id フィールドを保持します。
クラウドオーダー.sql
/*
Navicat Premium Data Transfer
Source Server : local
Source Server Type : MySQL
Source Server Version : 50622
Source Host : localhost:3306
Source Schema : heima
Target Server Type : MySQL
Target Server Version : 50622
File Encoding : 65001
Date: 01/04/2021 14:57:18
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
`price` bigint(20) NOT NULL COMMENT '商品价格',
`num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);
SET FOREIGN_KEY_CHECKS = 1;
クラウドユーザー.sql
/*
Navicat Premium Data Transfer
Source Server : local
Source Server Type : MySQL
Source Server Version : 50622
Source Host : localhost:3306
Source Schema : heima
Target Server Type : MySQL
Target Server Version : 50622
File Encoding : 65001
Date: 01/04/2021 14:57:18
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '柳岩', '湖南省衡阳市');
INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
INSERT INTO `tb_user` VALUES (6, '范兵兵', '山东省青岛市');
SET FOREIGN_KEY_CHECKS = 1;
2.2.2. デモプロジェクトのインポート
IDEA を使用して、プレコース教材で提供されるデモをインポートします。
プロジェクトの構造は次のとおりです。
インポート後、IDEA の右下隅にポップアップ ウィンドウが表示されます。
ポップアップ ウィンドウをクリックし、以下に示すように選択します。
次のようなメニューが表示されます。
プロジェクトで使用される JDK を構成します。
2.3. リモート呼び出しケースの実装
order-service サービスには、ID に基づいて注文をクエリするためのインターフェイスがあります。
ID に基づいて注文をクエリすると、図に示すように、戻り値は Order オブジェクトになります。
user が null の場合
user-service には、ID に基づいてユーザーをクエリするためのインターフェイスがあります。
クエリ結果は次の図に示されています。
2.3.1. ケースの要件:
order-serviceのIDに基づく注文クエリ業務を変更する オーダークエリ時にオーダーに含まれるuserIdを元にユーザー情報をクエリし、まとめて返す必要があります。
したがって、order-service で user-service への http リクエストを開始し、http://localhost:8081/user/{userId} インターフェイスを呼び出す必要があります。
一般的な手順は次のとおりです。
- RestTemplateのインスタンスをSpringコンテナに登録する
- order-service サービスの OrderService クラスの queryOrderById メソッドを変更して、Order オブジェクトの userId に基づいてユーザーをクエリします。
- クエリされたユーザーを Order オブジェクトに入力し、一緒に返します
2.3.2. RestTemplateの登録
まず、order-service サービスの OrderApplication スタートアップ クラスに RestTemplate インスタンスを登録します。
package cn.itcast.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.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.3.3. リモート通話の実装
order-service サービスの cn.itcast.order.service パッケージにある OrderService クラスの queryOrderById メソッドを変更します。
2.4. プロバイダーとコンシューマー
サービス呼び出し関係には、次の 2 つの異なる役割があります。
サービスプロバイダー: ビジネス内の他のマイクロサービスによって呼び出されるサービス。(他のマイクロサービスへのインターフェースを提供します)
サービスコンシューマ: ビジネス内の他のマイクロサービスを呼び出すサービス。(他のマイクロサービスによって提供される呼び出しインターフェイス)
ただし、サービス プロバイダーとサービス利用者の役割は絶対的なものではなく、ビジネスに対して相対的なものです。
サービス A がサービス B を呼び出し、サービス B がサービス C を呼び出す場合、サービス B の役割は何ですか?
- A が B に電話をかけるビジネスの場合: A はサービス コンシューマ、B はサービス プロバイダーです。
- B が C に電話をかけるビジネスの場合: B はサービス コンシューマ、C はサービス プロバイダーです。
したがって、サービス B はサービス プロバイダーとサービス コンシューマの両方になることができます。
3.エウレカ登録センター
図に示すように、サービス プロバイダーのユーザー サービスが複数のインスタンスをデプロイする場合:
いくつかの質問について考えてみましょう。
- order-service がリモート呼び出しを開始するとき、ユーザー サービス インスタンスの IP アドレスとポートをどのようにして知るのでしょうか?
- ユーザーサービスインスタンスのアドレスが複数ありますが、order-service を呼び出すときにどのように選択すればよいですか?
- order-service は、ユーザー サービス インスタンスがまだ正常であるかダウンしているかをどのようにして知るのでしょうか?
3.1.エウレカの構造と機能
これらの問題は、Spring Cloud の登録センターを使用して解決する必要があります。最もよく知られている登録センターは Eureka で、その構造は次のとおりです。
前述の各質問に答えてください。
質問 1: order-service はどのようにして user-service インスタンスのアドレスを知るのでしょうか?
住所情報を取得する手順は次のとおりです。
- user-serviceサービスインスタンス起動後、eureka-server(エウレカサーバー)に情報を登録します。これをサービス登録といいます
- eureka-server は、サービス名とサービス インスタンスのアドレス リスト間のマッピング関係を保存します。
- order-service は、サービス名に基づいてインスタンスのアドレスリストを取得します。これはサービス ディスカバリまたはサービス プルと呼ばれます
質問 2: order-service は、複数の user-service インスタンスから特定のインスタンスをどのように選択しますか?
- order-service は、負荷分散アルゴリズムを使用してインスタンス リストからインスタンス アドレスを選択します。
- インスタンスアドレスへのリモート呼び出しを開始します。
質問 3: order-service は、特定のユーザー サービス インスタンスがまだ正常であるかダウンしているかをどのようにして知るのでしょうか?
- ユーザー サービスは、一定の間隔 (デフォルトは 30 秒) で eureka サーバーへのリクエストを開始し、ハートビートと呼ばれる独自のステータスを報告します。
- 一定期間ハートビートが送信されない場合、eureka-server はマイクロサービス インスタンスに障害があるとみなし、そのインスタンスをサービス リストから削除します。
- order-service がサービスをプルすると、障害のあるインスタンスを削除できます。
注: マイクロサービスはサービス プロバイダーとサービス コンシューマーの両方になることができるため、eureka はサービス登録、サービス検出、その他の機能を eureka-client に均一にカプセル化します。
したがって、次の実践的なステップは次のとおりです。
3.2. eureka-serverの構築
まず、全員が中央サーバー eureka-server を登録します。これは独立したマイクロサービスである必要があります。
3.2.1. eureka-server サービスの作成
Cloud-demo 親プロジェクトの下に、サブモジュールを作成します。
モジュール情報を入力します。
次に、サービス情報を入力します。
3.2.2.eureka 依存関係の導入
SpringCloud によって eureka に提供されるスターター依存関係を導入します。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.2.3.スタートアップクラスの書き込み
eureka-server サービスのスタートアップ クラスを作成します。eureka の登録センター機能を有効にするために @EnableEurekaServer アノテーションを必ず追加してください。
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.2.4.設定ファイルの書き込み
次の内容を含む application.yml ファイルを作成します。
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
3.2.5.サービスの開始
マイクロサービスを開始し、ブラウザーでアクセスします: http://127.0.0.1:10086
次の結果が表示されれば、成功したことがわかります。
3.3.サービス登録
次に、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 スタートアップ構成を追加し、ユーザー サービスを開始します。
まず、元のユーザー サービスの起動設定をコピーします。
次に、ポップアップ ウィンドウで次の情報を入力します。
これで、2 つのユーザー サービスのスタートアップ構成が SpringBoot ウィンドウに表示されます。
ただし、最初のポートはポート 8081、2 番目のポートはポート 8082 です。
2 つのユーザー サービス インスタンスを開始します。
eureka-server 管理ページを表示します。
3.4.サービスの検出
次に、order-service のロジックを変更します。eureka-server からユーザー サービス情報をプルして、サービス ディスカバリを実現します。
1) 依存関係を導入する
前述したように、サービス検出とサービス登録はすべて eureka-client 依存関係にカプセル化されているため、この手順はサービス登録と一致します。
order-service の pom ファイルに、次の eureka-client 依存関係を導入します。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2) 設定ファイル
サービス検出では、エウレカ アドレスも知る必要があるため、2 番目のステップはサービス登録と一致しており、エウレカ情報を構成します。
order-service で、application.yml ファイルを変更し、サービス名と eureka アドレスを追加します。
spring:
application:
name: orderservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
3) サービスのプルと負荷分散
最後に、eureka-server から user-service サービスのインスタンス リストを取得し、負荷分散を実装します。
ただし、これらのアクションを実行する必要はなく、いくつかの注釈を追加するだけで済みます。
order-service の OrderApplication で、RestTemplate Bean に @LoadBalanced アノテーションを追加します。
order-service サービスの cn.itcast.order.service パッケージの下にある OrderService クラスの queryOrderById メソッドを変更します。アクセスした URL パスを変更し、IP とポートをサービス名に置き換えます。
Spring は、userservice サービス名に基づいて eureka-server 側からインスタンス リストを取得し、負荷分散を完了するのに自動的に役立ちます。
4.リボンの負荷分散
前節では負荷分散機能を実装するために @LoadBalanced アノテーションを追加しましたが、これはどのような原理でしょうか?
4.1. 負荷分散の原理
Spring Cloud の最下層では、実際にはリボンと呼ばれるコンポーネントを使用して負荷分散機能を実装しています。
では、送信したリクエストは明らかに http://userservice/user/1 でしたが、なぜ http://localhost:8081 になったのでしょうか?
4.2. ソースコードの追跡
なぜサービス名を入力するだけでアクセスできるのでしょうか?また、事前に IP とポートを取得する必要があります。
どうやら誰かがサービス名に基づいてサービス インスタンスの IP とポートを取得するのを手伝ってくれたようです。つまりLoadBalancerInterceptor
、このクラスは RestTemplate リクエストをインターセプトし、サービス ID に基づいて Eureka からサービス リストを取得し、負荷分散アルゴリズムを使用して実際のサービス アドレス情報を取得し、サービス ID を置き換えます。
私たちはソースコードの追跡を実施します。
1)ロードバランサーインターセポート
ここでの intercept メソッドがユーザーの HttpRequest リクエストをインターセプトし、いくつかのことを実行することがわかります。
request.getURI()
: リクエスト URI を取得します。この場合は http://user-service/user/8originalUri.getHost()
: URI パスのホスト名を取得します。これは実際にはサービス ID です。user-service
this.loadBalancer.execute()
: サービス ID とユーザー リクエストを処理します。
タイプは次のとおりthis.loadBalancer
です。引き続きフォローしてみましょう。LoadBalancerClient
2)ロードバランサークライアント
引き続き実行メソッドに従います。
コードは次のようなものです:
- getLoadBalancer(serviceId): サービス ID に基づいて ILoadBalancer を取得します。ILoadBalancer はサービス ID を取得して eureka からサービス リストを取得し、保存します。
- getServer(loadBalancer): 組み込みの負荷分散アルゴリズムを使用して、サービス リストから 1 つを選択します。この例では、ポート 8082 のサービスが取得されていることがわかります。
リリース後、再度アクセスして追跡したところ、「8081:
負荷分散は確かに達成されました」という結果が得られたことがわかりました。
3) 負荷分散戦略 IRule
先ほどのコードでは、サービスの取得で負荷分散を実行するメソッドが使用されていることがわかりますgetServer
。
引き続きフォローアップしてみましょう:
ソース コードのchooseServer メソッドをトレースし続けると、次のコードが見つかりました。
このルールが誰であるかを見てみましょう:
ここでのルールのデフォルト値は one ですRoundRobinRule
。クラスの紹介を参照してください:
これがポーリングの意味ではありませんか?
この時点で、負荷分散プロセス全体を明確に理解できました。
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 を取得して、実際のリクエストを開始します。
4.3. 負荷分散戦略
4.3.1. 負荷分散戦略
負荷分散ルールは IRule インターフェイスで定義され、IRule にはさまざまな実装クラスがあります。
さまざまなルールの意味は次のとおりです。
組み込みの負荷分散ルールクラス | ルールの説明 |
---|---|
ラウンドロビンルール | サービス リストをポーリングしてサーバーを選択するだけです。これは、リボンのデフォルトの負荷分散ルールです。 |
可用性フィルタリングルール | 次の 2 種類のサーバーは無視してください。 (1) デフォルトでは、このサーバーが 3 回接続に失敗すると、このサーバーは「短絡」状態に設定されます。短絡状態は 30 秒間続きますが、再度接続に失敗すると、短絡時間は幾何級数的に増加します。(2) 同時実行性が高すぎるサーバー。サーバーへの同時接続の数が多すぎる場合、AvailabilityFilteringRule ルールが設定されているクライアントもそれを無視します。同時接続数の上限は、クライアントの ..ActiveConnectionsLimit プロパティによって構成できます。 |
WeightedResponseTimeRule | 各サーバーに重み値を与えます。サーバーの応答時間が長いほど、サーバーの重みは小さくなります。このルールはサーバーをランダムに選択し、この重み値はサーバーの選択に影響します。 |
ゾーン回避ルール | サーバーの選択は、その地域で利用可能なサーバーに基づいて行われます。ゾーンを使用してサーバーを分類します。このゾーンは、コンピューター室、ラックなどとして理解できます。次に、ゾーン内の複数のサービスをポーリングします。 |
BestAvailableルール | ショートサーキットしているサーバーを無視し、同時実行数が低いサーバーを選択します。 |
ランダムルール | 利用可能なサーバーをランダムに選択します。 |
再試行ルール | リトライ機構の選択ロジック |
デフォルトの実装は、ポーリング スキームである ZoneAvoidanceRule です。
4.3.2. カスタマイズされた負荷分散戦略
負荷分散ルールは、次の 2 つの方法で IRule 実装を定義することで変更できます。
- コード メソッド: order-service の OrderApplication クラスで、新しい IRule を定義します。
@Bean
public IRule randomRule(){
return new RandomRule();
}
- 構成ファイルによる方法: order-service の application.yml ファイルで、新しい構成を追加すると、ルールを変更することもできます。
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
通常、デフォルトの負荷分散ルールは変更せずに使用されることに注意してください。
4.4.ハングリーロード
リボンはデフォルトで遅延読み込みを使用します。つまり、LoadBalanceClient は最初のアクセスまで作成されず、要求時間は非常に長くなります。
プロジェクトの開始時にハングリー ローディングが作成され、最初の訪問の時間が短縮されます。次の構成を通じてハングリー ローディングを有効にします。
ribbon:
eager-load:
enabled: true
clients: userservice
5.ナコス登録センター
国内企業は一般的に登録センターなどアリババの技術を尊重しており、Spring Cloud アリババも Nacos と呼ばれる登録センターを立ち上げた。
5.1. Nacos の理解とインストール
Nacosは Alibaba の製品であり、現在Spring Cloudのコンポーネントです。Eurekaに比べて機能が豊富で、中国での人気が高いです。
5.2. nacosへのサービス登録
Nacos は SpringCloudAlibaba のコンポーネントであり、SpringCloudAlibaba も SpringCloud で定義されたサービス登録およびサービス検出の仕様に従います。したがって、マイクロサービスに Nacos を使用する場合と Eureka を使用する場合に大きな違いはありません。
主な違いは次のとおりです。
- 依存関係が違う
- サービスアドレスが異なります
1) 依存関係を導入する
<dependencyManagement>
SpringCloudAlibaba 依存関係をCloud-demo 親プロジェクトの pom ファイルに導入します。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
次に、nacos-discovery 依存関係を user-service と order-service の pom ファイルに導入します。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
注: eureka の依存関係をコメントアウトすることを忘れないでください。
2) nacosアドレスの設定
user-service と order-service の application.yml に nacos アドレスを追加します。
spring:
cloud:
nacos:
server-addr: localhost:8848
注: eureka のアドレスをコメントアウトすることを忘れないでください。
3) 再起動
マイクロサービスを再起動した後、nacos 管理ページにログインすると、マイクロサービスの情報を確認できます。
5.3. サービス階層型ストレージモデル
サービスには複数のインスタンスを含めることができます。たとえば、ユーザー サービスには次のインスタンスを含めることができます。
- 127.0.0.1:8081
- 127.0.0.1:8082
- 127.0.0.1:8083
たとえば、これらのインスタンスが全国のさまざまなコンピューター室に分散されている場合は、次のようになります。
- 127.0.0.1:8081、上海コンピュータ室
- 127.0.0.1:8082、上海コンピューター室
- 127.0.0.1:8083、杭州コンピューター室
Nacos は、同じコンピュータ ルーム内のインスタンスを 1 つのクラスタに分割します。
つまり、ユーザー サービスはサービスです。サービスには、杭州や上海などの複数のクラスターを含めることができます。各クラスターには複数のインスタンスを含めることができ、図に示すように階層モデルを形成できます。
マイクロサービスが相互にアクセスする場合、ローカル アクセスの方が高速であるため、同じクラスター インスタンスへのアクセスを試行する必要があります。現在のクラスターが使用できない場合にのみ、他のクラスターにアクセスできます。例えば:
杭州コンピューター室のオーダーサービスは、同じコンピューター室のユーザーサービスを優先する必要があります。
5.3.1. ユーザーサービス用のクラスターの設定
user-service の application.yml ファイルを変更し、クラスター構成を追加します。
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
2 つのユーザー サービス インスタンスを再起動すると、nacos コンソールに次の結果が表示されます。
ユーザーサービスの起動設定を再度コピーし、プロパティを追加します。
-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH
構成を次の図に示します。
UserApplication3 を起動した後、nacos コンソールを再度確認します。
5.3.2. 同一クラスター内での優先順位によるロードバランシング
デフォルトでは、ZoneAvoidanceRule
同じクラスター内の優先順位に基づいてロード バランシングを実現することはできません。
したがって、Nacos は、NacosRule
同じクラスターのインスタンスに優先順位を付けることができる実装を提供します。
1) order-service のクラスター情報を構成する
order-service の application.yml ファイルを変更し、クラスター構成を追加します。
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
2) 負荷分散ルールを変更する
order-service の application.yml ファイルを変更し、負荷分散ルールを変更します。
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
5.4. 重みの設定
実際の展開では、次のシナリオが発生します。
サーバー機器の性能にはばらつきがあり、インスタンスが配置されているマシンの性能が良いものもあれば、性能が悪いものもあり、性能の良いマシンにはより多くのユーザーのリクエストを受け入れられることが期待されます。
ただし、デフォルトでは、NacosRule は同じクラスター内でランダムに選択され、マシンのパフォーマンスの問題は考慮されません。
そこでNacosではアクセス頻度を制御するための重み設定を用意しており、重みが大きいほどアクセス頻度が高くなります。
nacos コンソールで、user-service のインスタンス リストを見つけて、[編集] をクリックして重みを変更します。
ポップアップ編集ウィンドウで重みを変更します。
注: 重みを 0 に変更すると、インスタンスにはアクセスできなくなります。
5.5. 環境隔離
Nacos は、環境分離機能を実装するための名前空間を提供します。
- nacos には複数の名前空間が存在する可能性があります
- 名前空間の下にはグループ、サービスなどが存在する場合があります。
- 異なる名前空間は互いに分離されており、たとえば、異なる名前空間にあるサービスは相互に認識されません。
5.5.1.名前空間の作成
デフォルトでは、すべてのサービス、データ、およびグループは、public という名前の同じ名前空間内にあります。
ページ上の新規ボタンをクリックして名前空間を追加できます。
次に、フォームに記入します。
ページに新しい名前空間が表示されます。
5.5.2. マイクロサービスの名前空間の設定
マイクロサービスの名前空間の構成は、構成を変更することによってのみ実現できます。
たとえば、order-service の application.yml ファイルを変更します。
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ
namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID
order-service を再起動した後、コンソールにアクセスすると、次の結果が表示されます。
この時点で order-service にアクセスすると、名前空間が異なるため userservice が見つからず、コンソールにエラーが報告されます。
5.6.ナコスとエウレカの違い
Nacos サービス インスタンスは 2 つのタイプに分類されます。
-
一時インスタンス: インスタンスが一定期間以上ダウンしている場合、サービス リストから削除されます。これがデフォルトのタイプです。
-
非一時インスタンス: インスタンスがダウンしてもサービス リストから削除されず、永続インスタンスと呼ぶこともできます。
サービス インスタンスを永続インスタンスとして構成します。
spring:
cloud:
nacos:
discovery:
ephemeral: false # 设置为非临时实例
Nacos と Eureka の全体的な構造は、サービスの登録、サービスのプル、ハートビートの待機など似ていますが、いくつかの違いもあります。
-
ナコスとエウレカの共通点
- どちらもサービスの登録とサービスのプルをサポートしています。
- すべてのサービス プロバイダーの健全性検査のハートビート方式をサポートします。
-
ナコスとエウレカの違い
- Nacos は、サーバーがプロバイダーのステータスをアクティブに検出することをサポートします。一時インスタンスはハートビート モードを採用し、非一時インスタンスはアクティブ検出モードを採用します。
- 異常なハートビートのある一時的なインスタンスは削除されますが、一時的ではないインスタンスは削除されません。
- Nacos はサービス リスト変更のメッセージ プッシュ モードをサポートしており、サービス リストはよりタイムリーに更新されます。
- Nacos クラスターはデフォルトで AP モードを使用します。クラスター内に非一時インスタンスがある場合は CP モードが使用され、Eureka は AP モードを使用します。
中央に配置された画像: