ダボ
記事ディレクトリ
1.ダボの概要
- Dubboは、高性能のリモートサービス呼び出しソリューションとSOAサービスガバナンスソリューションを提供するためのJavaRPCフレームワークです。
簡単に言うと、Dubboは、コンシューマーに呼び出しインターフェイスを提供するために使用されます(インターフェイスをレジストリに登録します)
- ダボ操作フローチャート
ノードの役割の説明:
●プロバイダー:サービスを公開するサービスプロバイダー
●コンシューマー:リモートサービスを呼び出すサービスコンシューマー
●コンテナー:サービスを実行するコンテナー
●レジストリ:サービスの登録と検出のためのレジストリ
●モニター:サービスの数をカウントする監視センター通話と通話時間
- Dubbo実行プロセスのテキスト説明
(1)コンテナを起動し、サービスプロバイダーをロードして実行します
(2)プロバイダーが起動したら、提供するサービスをレジストリに登録します
(3)コンシューマーが起動したら、必要なサービスをレジストリにサブスクライブします
(4)レジストリは、管理プロバイダーによって提供されるURLに使用されます。ZooKeeperは、Dubboが推奨する登録センターです
(5)監視センターはプロセス全体を管理します
- 失敗や変更を検討する
(1)レジストリはプロバイダーアドレスリストをコンシューマーに返します。変更がある場合、レジストリは変更されたデータをコンシューマーにプッシュします。
(2)コンシューマーはプロバイダーアドレスリストからプロバイダーを選択して呼び出します。呼び出しが失敗した場合、別のものを選択します
(3)コンシューマーとプロバイダーは、通話数と通話時間をメモリに記録し、統計を1分ごとに監視センターに送信します
2、ダボの実行例
1つはプロバイダーとして、もう1つはコンシューマーとして、2つのモジュールを作成します。コンシューマーは、Dubboを介してサービスによって提供されるサービスをリモートで呼び出し、テストのために2つのパーティを別々に開始できます。
注:両方の当事者は、Mavenを介してプロバイダーのサービスを呼び出すことに依存せずに、独立して実行可能な戦争プロジェクトである必要があります
- 両当事者が使用する必要のあるインターフェースの開発
インターフェイスを独立したモジュールとして使用する理由:
(1)プロバイダーは特定のメソッド(サービス)を定義するためにこのインターフェースを実装する必要があるため、このインターフェースを定義する必要があります
(2)コンシューマーは、インターフェース内のメソッドを呼び出すためにこのインターフェースを定義する必要があります(これによって提供されるサービスを使用)インターフェース)
これにより、このインターフェイスの定義が2者間で重複します。インターフェイスが変更されると、2者の変更が煩雑になるため、パブリックインターフェイスは独立したモジュールと見なされます。
package com.itheima.service;
public interface UserService {
public String sayHello();
}
//并且需要将此模块install成为jar包
- プロバイダー開発
(1)pom.xmlファイルの内容
<groupId>com.itheima</groupId>
<artifactId>dubbo-service</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- war项目 -->
<!-- jar包版本控制 -->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<dubbo.version>2.7.4.1</dubbo.version>
<zookeeper.version>4.0.0</zookeeper.version>
</properties>
<dependencies>
<!--Dubbo服务所需jar包-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!--ZooKeeper服务所需jar包-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!--依赖公共的接口模块-->
<dependency>
<groupId>com.itheima</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--以及其余必须的如spring、springmvc、Log4J等jar包-->
<!--以及tomcat服务器的插件-->
</dependencies>
(2)web.xmlのコンテンツ
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- 监听Spring配置文件 -->
<param-value>classpath*:spring/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(3)UserServiceImplのコンテンツ
//导入公共接口所在类的包
/**
* 1. @Service注解是Dubbo包下的,并不是Spring包下的
* 2. 使用了此注解的类提供的方法将会对外发布,并将访问地址,端口等注册到注册中心中
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello Dubbo !";
}
}
(4)applicationContext.xmlのコンテンツ
<!--Dubbo的配置-->
<!-- 1. 配置项目的名称(自定义),用于注册中心计算项目之间依赖关系,唯一 -->
<dubbo:application name="dubbo-service"/>
<!-- 2. 配置注册中心的地址,用于连接注册中心,address为Zookeeper所在Linux的ip地址及ZooKeeper端口号 -->
<dubbo:registry address="zookeeper://192.168.200.130:2181"/>
<!-- 3. 配置Dubbo的包扫描,使用了Dubbo包下的@Service注解的类会被发布为服务 -->
<dubbo:annotation package="com.itheima.service.impl" />
- 消費者開発
(1)pom.xmlのコンテンツ
<groupId>com.itheima</groupId>
<artifactId>dubbo-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- war项目 -->
<!-- jar包版本控制 -->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<dubbo.version>2.7.4.1</dubbo.version>
<zookeeper.version>4.0.0</zookeeper.version>
</properties>
<dependencies>
<!--Dubbo服务所需jar包-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!--ZooKeeper服务所需jar包-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!--依赖公共的接口模块-->
<dependency>
<groupId>com.itheima</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- web模块并没有直接依赖service模块,通过远程调用方式 -->
<!--以及其余必须的如spring、springmvc、Log4J等jar包-->
<!--以及tomcat服务器的插件-->
</dependencies>
(2)web.xmlのコンテンツ
<!-- Springmvc -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
(3)UserControllerのコンテンツ
//导入公共接口所在类的包
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 1. @Reference注解导入的为Dubbo包
* 2. @Reference注解作用:
* (1) 从zookeeper注册中心获取提供方的访问url
* (2) 进行远程调用RPC
* (3) 将结果封装为一个代理对象,赋值给userService对象
*/
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
(4)springmvc.xmlのコンテンツ
<mvc:annotation-driven/>
<!-- 扫描使用了Controller注解的类 -->
<context:component-scan base-package="com.itheima.controller"/>
<!--dubbo的配置-->
<!-- 1.配置项目的名称,唯一 -->
<dubbo:application name="dubbo-web" >
<!-- 在同一台机器上同时部署提供方和消费方需要区分二者,否则二者同时使用默认端口22222,冲突 -->
<!-- 实际开发中,提供方与消费方通常部署在不同的机器上,无需关心此项-->
<dubbo:parameter key="qos.port" value="33333"/>
</dubbo:application>
<!-- 2. 配置注册中心的地址-->
<dubbo:registry address="zookeeper://192.168.200.130:2181"/>
<!-- 3. 配置dubbo包扫描,扫描使用了Dubbo包下的@Reference注解 -->
<dubbo:annotation package="com.itheima.controller" />
- 運用結果
(1)プロバイダーとコンシューマーの2つの戦争プロジェクトとして、サービスモジュールとWebモジュールでこのコマンドを別々に実行します
(2)Webモジュール実行後のログ情報は以下のとおりです。
(3)操作効果は以下のとおりです。
3、シリアル化
プロバイダー(プロデューサー)とコンシューマー(コンシューマー)がPojoタイプを渡す必要がある場合、PojoクラスはIOパッケージの下にSerializableインターフェイスを実装し、送信用のバイナリストリームになる必要があります。
4、アドレスキャッシュ
-
質問:登録センターが電話を切った後、サービスに正常にアクセスできますか?
-
回答:はい。コンシューマーは、サービスを初めて呼び出すときにプロデューサーのアドレスをローカルにキャッシュし、後でこのアドレスにアクセスするときにレジストリを通過しないためです。プロデューサーのアドレスが変更されると、レジストリは通知します。メカニズムはコンシューマーに通知します。新しいアドレス;
注:登録センターが切断された後、既存の消費者はサービスにアクセスできますが、新しい消費者はサービスにアクセスできなくなります
5、タイムアウト
-
消費者がプロデューサーのサービスに電話をかけるとき、ブロッキングや待機などがあると、消費者は永遠に待機します
-
あるピーク時に、多数のリクエストがブロックされると、アバランシェ現象が発生します
-
Dubboは、タイムアウトメカニズムを使用してこの問題を解決します。タイムアウト期間を設定します。この時間内にサービスアクセスを完了できない場合、Dubboは自動的に切断し、タイムアウトエラーを報告します。
-
タイムアウト属性を使用してタイムアウト期間を設定します。デフォルト値はミリ秒単位の1000です。
//timeout属性设置超时时间,单位毫秒;
@Service(timeout = 3000)
- コンシューマー
@Reference
アノテーションでもtimeout属性を使用できますが、プロデューサーでサービスを定義すると必要な時間を見積もり、タイムアウト設定が容易になるため、通常はプロデューサーで使用することをお勧めします。
6、もう一度やり直してください
-
タイムアウト期間が設定されています。この時間内にサービスコールを完了できない場合、接続は自動的に切断され、エラーが報告されます。
-
ネットワークジッターがある場合(ネットワークが不安定で一時的に中断されているが、すぐに回復する)、要求は失敗します
-
ダボはそのような問題を回避するために再試行メカニズムを使用します
-
retries属性を使用して再試行回数を設定します。デフォルトは2回です(さらに最初のリクエスト、合計3回)。
//retries属性设置重传次数
@Service(timeout = 3000, retries = 3)
7つの複数のバージョン
-
プロデューサーのサービスの新しいバージョンが表示されると、すべてのコンシューマーがこのバージョンにアクセスできるわけではありませんが、一部のコンシューマーは最初にこのバージョンを呼び出すことができ、問題がないことを確認した後、すべてのコンシューマーがこのバージョンを呼び出すことができます。灰色度リリースと呼ばれます
-
Dubboは、version属性を使用して、同じインターフェースの異なるバージョンを設定および呼び出します。
プロデューサーコード:
@Service(version = "v1.0", timeout = 3000)
public class UserServiceImpl1 implements UserService {
...}
@Service(version = "v2.0")
public class UserServiceImpl2 implements UserService {
...}
消費者コード:
@Reference(version = "v2.0")
private UserService userService;
//成功调用v2.0版本的服务
8、負荷分散
- コンシューマーは、負荷分散戦略を使用してプロデューサークラスターにアクセスする必要があります。4つのタイプがあります。
(1)ランダム:デフォルトの戦略。重みでランダムな確率を設定すると、重みが大きいほどアクセスしやすくなります
(2)RoundRobin:要求によるポーリング
(3)LeastActive:応答時間が短いほど簡単になりますアクセスされる
(4)ConsistentHash:同じリクエストが常に同じサービスを呼び出す
注:4つの戦略は、Nginxの負荷分散戦略に似ています
- プロデューサー構成、weight属性を使用して重みを設定します。デフォルト値は100です。
@Service(weight = 200)
- コンシューマー構成、負荷分散属性を介してポリシーを設定します。デフォルト値はランダムです
@Reference(loadbalance = "random")
@Reference(loadbalance = "roundrobin")
@Reference(loadbalance = "leastactive")
@Reference(loadbalance = "consistenthash")
- 注:同じマシンで複数のサービスを開始するには、次の2つのポートを変更する必要があります。競合を防ぐために、各サービスを同じにすることはできません。
9つのクラスターフォールトトレランス
- クラスターのフォールトトレランスモードは次のとおりです。
(1)フェイルオーバークラスター:デフォルトモード;失敗再試行、デフォルト再試行2回、再試行構成の使用;障害が発生した場合、エラーを報告し、他のサーバーを2回再試行します。通常、読み取り操作に使用され、書き込み操作は遅延などにより書き込みを引き起こす可能性があります。 。受信データの重複
(2)Failfast Cluster:高速障害。呼び出しを開始します。失敗した場合、エラーは再試行せずにすぐに報告されます。通常、書き込み操作に使用されます。
(3)フェイルセーフクラスター:フェイルセーフクラスター:例外が発生した場合、エラーは報告されず、無視され、空の結果が返されます。
(4)フェイルバッククラスター:失敗からの自動回復。要求が失敗した後、バックグラウンドは失敗した要求を記録し、定期的に再送信します。
(5)フォーククラスター:複数のサービスを並行して呼び出し、1つが成功する限り戻ります
(6)ブロードキャストクラスター:すべてのプロバイダーに通話をブロードキャストし、プロバイダーを1つずつ呼び出し、いずれかの通話が失敗した場合はエラーを報告します
- コンシューマー構成、クラスター属性を使用してクラスターフォールトトレランスモードを設定します。デフォルト値はフェイルオーバーです
@Reference(cluster = "failover")
X.サービスの低下
-
サーバーのプレッシャーが高い場合、実際の状況に応じて一部のサービスがリリースされ、サービスの全体的な効率的な運用を確保するためにコアサービスのみが予約されます
-
サービスをダウングレードするには2つの方法があります
(1)mock = force:return null:コンシューマーがサービスに対して行うすべての呼び出しがnull値を返すことを意味します。これは、サービスをシールドすることと同じです。
(2)mock = fail:return null:サービスへのコンシューマーの呼び出しが失敗した(再試行する)ことを示し、エラーを報告せずにnull値を返します
- コンシューマー構成、モック属性を使用してサービス劣化方法を設定します
@Reference(mock = "force : return null")