ダボサービスコントロール

Dubbo が提供する機能をサービス ガバナンスの観点から紹介しましたが、今日は他の側面から Dubbo が提供する機能を見ていきます。サービス ガバナンスの記事と同様に、この記事の目的は、サービスの管理と制御において Dubbo によって提供される機能の使用方法を学習することであり、実装原則は含まれていません。

工学構造

うーん~~

これは、コンピューターが拡張性がありすぎて、IDEA がメモリを非常に消費するため、サブプロジェクトに従ってテスト プロジェクトをマージしました。現在使用しているプロジェクト構造は次のとおりです。

サブモジュール名は、構成メソッド + 関数の 2 つの部分で構成されます。例: XMLProvider。XML 構成メソッドに基づくサービス プロバイダーを意味します。

ヒント: IDEA は、「記憶のライオン」CLionl に追いつきつつあります。

ローカルスタブ(スタブ)

Dubbo を使用する場合、サービス ユーザーはインターフェイスを統合するだけで、すべての実装はサービス プロバイダー上で行われます。ただし、シナリオによっては、サービス ユーザーがいくつかのロジック処理を完了して、RPC インタラクションによるパフォーマンスの消費を削減できることを期待します。 : パラメータ検証をサービス ユーザーに配置して、サービス呼び出し元とのネットワーク インタラクションを 1 つ削減します。

このシナリオでは、Dubbo が提供するローカル スタブ機能を使用できます。サービスプロバイダーのエンジニアリング構造は次のとおりです。

xml-provider-api モジュールは、外部サービスを提供するインターフェイス XMLProviderService を定義します。コードは次のとおりです。

public interface XMLProviderService {
	String say(String message);
}

インターフェイス スタブ XMLProviderServiceStub のコードは次のとおりです。

public class XMLProviderServiceStub implements XMLProviderService {

	private final XMLProviderService xmlProviderService;

	public XMLProviderServiceStub(XMLProviderService xmlProviderService) {
		this.xmlProviderService = xmlProviderService;
	}

	@Override
	public String say(String message) {
		if (StringUtils.isBlank(message)) {
			return "message不能为空!";
		}

		try {
			return this.xmlProviderService.say(message);
		} catch (Exception e) {
			return "远程调用失败:" + e.getMessage();
		}
	}
}

次に、サービス コンシューマーのプロジェクトでインターフェイス スタブを構成します。

<dubbo:reference id="xmlProviderService" interface="com.wyz.api.XMLProviderService" stub="com.wyz.api.stub.XMLProviderServiceStub"/>

ヒント: ローカル スタブを使用するには、スタブの実装クラスに、Proxy インスタンス (サービス ユーザーによって生成された Proxy インスタンス) を渡すコンストラクターが必要です。

局所迷彩(モック)

ローカルカモフラージュとは、 「 Dubbo の高度な機能: サービス ガバナンス」で説明したサービスの低下のことですが、今日は少し追加します。ローカル マスカレードはローカル スタブのサブセットです。ローカル スタブは RPC 呼び出しリンク内のさまざまなエラーと例外を処理できますが、ローカル マスカレードはフォールト トレラントな処理を必要とする RpcException (ネットワーク障害、応答タイムアウトなど) の処理に重点を置いています。

XMLProviderService にローカル マスカレード サービス XMLProviderServiceMock を追加します。プロジェクト構造は次のとおりです。

XMLProviderServiceMock のコードは次のとおりです。

public class XMLProviderServiceMock implements XMLProviderService {

	@Override
	public String say(String message) {
		return "服务出错了!";
	}
}

構成ファイルは次のように構成できます。

<dubbo:reference id="xmlProviderService" interface="com.wyz.api.XMLProviderService" mock="true"/>

この構成では、Mock の実装は「インターフェイス名 + Mock サフィックス」の方法に従って名前を付ける必要があります。この名前付け方法を使用したくない場合は、完全修飾名を使用できます。

<dubbo:reference id="xmlProviderService" interface="com.wyz.api.XMLProviderService" mock="com.wyz.api.mock.XMLProviderServiceMock"/>

Tips : Mockを再度「繰り返す」のは、前回の記事でミスがあったためです。<dubbo:reference>ラベルにはやるべき設定を書いたのです<dubbo:service>が、エラーの理由がプロジェクトにはまだ書かれていません。私は「紙に書かれたことはいつも浅いですが、この問題は実践しなければならないことを決して知りません」という言葉を本当に遵守しました。

パラメータコールバック

Dubbo は、サービス プロバイダーがサービス コンシューマーを「リバース」呼び出すことができるパラメーター コールバック機能をサポートしています。この機能は、ロング リンクによって生成されるリバース プロキシに基づいて実現され、非同期呼び出しと同様の効果が得られます 支払いの例を見てみましょう。

PaymentService インターフェイスを XMLProvider プロジェクトの xml-provider-api モジュールに追加し、PaymentService の結果を通知する PaymentNotifyService を追加します。

public interface PaymentService {
	void payment(String cardNo, PaymentNotifyService paymentNotifyService);
}

public interface PaymentNotifyService {
	void paymentNotify(String message);
}

PaymentService インターフェイスは、XMLProvider プロジェクトの xml-provider-service モジュールに実装されています。

public class PaymentServiceImpl implements PaymentService {
	@Override
	public void payment(String cardNo, PaymentNotifyService paymentNotifyService) {
		System.out.println("向卡号[" + cardNo + "]付钱!");
		// 业务逻辑
		paymentNotifyService.paymentNotify("付款成功");
	}
}

PaymentService#paymentメソッドを実行し、PaymentNotifyService#paymentNotifyメソッドを呼び出して実行結果をサービス呼び出し元に通知します。

XMLConsumer プロジェクトに PaymentNotifyService インターフェースを実装します。

public class PaymentNotifyServiceImpl implements PaymentNotifyService {
	@Override
	public void paymentNotify(String message) {
		System.out.println("支付结果:" + message);
	}
}

この時点でのプロジェクト構造を見てください。

次に、XML の構成です。パラメーター コールバックでは、サービス プロバイダーの XMLProvider プロジェクトの xml-provider-service モジュールの構成に注意する必要があります。

<bean id="paymentServiceImpl" class="com.wyz.service.impl.PaymentServiceImpl"/>
<dubbo:service interface="com.wyz.api.PaymentService" ref="paymentServiceImpl" callbacks="10">
  <dubbo:method name="payment">
    <dubbo:argument index="1" callback="true"/>
  </dubbo:method>
</dubbo:service>

メソッドの 2 番目のパラメーター (インデックスは 0 から始まります) は、コールバック パラメーターとして4 行目の構成によって<dubbo:argument index="1" callback="true"/>決定されます。コールバックは、コールバックの総数ではなく、同じ長いリンクの下でのコールバックの数を制限します。PaymentService#payment

ヒント: 実際の決済ビジネス シナリオでは、非同期処理の傾向が強くなります。たとえば、サービス プロバイダーが決済リクエストを受信すると、決済ビジネスを処理するための新しいスレッドが開始され、通知インターフェイスが呼び出され、メイン スレッドが戻ります。支払いリクエストが正常に受信されたことを示します。

非同期呼び出し

非同期呼び出しにより、サービス プロバイダーは、バックグラウンドで要求処理を実行し続けながら、すぐに応答を返すことができます。サービス コンシューマーが応答結果を要求すると、サービス プロバイダーは結果を返します。

DUbbo は 2 つの非同期呼び出しメソッドをサポートしています。

  • CompletableFuture インターフェースを使用する
  • RpcContext を使用する

DUbbo 2.7 以降、DUbbo は非同期プログラミングの基礎としてCompletableFutureインターフェイスを使用します。

CompletableFuture を使用して非同期呼び出しを実装する

まず、CompletableFuture を使用して非同期呼び出しを実装し、CompletableFutureAsyncService インターフェイスを宣言する方法を見てみましょう。

public interface CompletableFutureAsyncService {
	CompletableFuture<String> async(String message);
}

次に、インターフェイスの実装が続きます。

public class CompletableFutureAsyncServiceImpl implements CompletableFutureAsyncService {
	@Override
	public CompletableFuture<String> async(String message) {
		return CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread().getName() + " say : " + message);

			try {
				TimeUnit.SECONDS.sleep(10);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
			return "异步调用成功!";
		});
	}
}

XML 構成は、一般的な DubboRPC インターフェイス構成、つまり xml-provider-service モジュールの構成と同じです。

<bean id="completableFutureAsyncServiceImpl" class="com.wyz.service.impl.CompletableFutureAsyncServiceImpl" />
<dubbo:service interface="com.wyz.api.CompletableFutureAsyncService" ref="completableFutureAsyncServiceImpl" />

XMLConsumer モジュールの構成:

<dubbo:reference id="completableFutureAsyncService" interface="com.wyz.api.CompletableFutureAsyncService"/>

使い方も非常に簡単です。

CompletableFuture<String> completableFuture = completableFutureAsyncService.async("Hello");
System.out.println(completableFuture.get());

ヒント

  • Dubbo で CompletableFuture を使用する場合と CompletableFuture を単独で使用する場合に違いはありません~~
  • CompletableFutureAsyncServiceImpl の実装でインターフェイス名を出力する目的は、非同期呼び出しの効果を明確に示すことです。
  • CompletableFuture#supplyAsync(Supplier<U> supplier)デフォルトではForkJoinPool#commonPool();を使用します。
  • オーバーロードされたメソッドでは、CompletableFuture#supplyAsync(Supplier<U> supplier, Executor executor)カスタム スレッド プールを使用できます。

AsyncContext を使用して非同期呼び出しを実装する

CompletableFuture の使用に加えて、Dubbo によって定義された AsyncContext を介して非同期呼び出しを実装することもできます。最初にインターフェイスとインターフェイス実装を作成しましょう。

public interface RpcContextAsyncService {
	String async(String message);
}

public class RpcContextAsyncServiceImpl implements RpcContextAsyncService {

	@Override
	public String async(String message) {
		final AsyncContext asyncContext = RpcContext.startAsync();
		new Thread(() -> {
			asyncContext.signalContextSwitch();
			asyncContext.write(Thread.currentThread().getName() + " say : " + message);
		}).start();
		// 异步调用中,这个返回值完全没有意义
		return null;
	}
}

サービス プロバイダーの構成は、他の Dubbo インターフェイスの構成と同じです。

<bean id="rpcContextAsyncServiceImpl" class="com.wyz.service.impl.RpcContextAsyncServiceImpl"/>
<dubbo:service interface="com.wyz.api.RpcContextAsyncService" ref="rpcContextAsyncServiceImpl"/>

次に、サービス コンシューマの構成です。これには async パラメータを追加する必要があります。

<dubbo:reference id="rpcContextAsyncService" interface="com.wyz.api.RpcContextAsyncService" async="true"/>

最後に、サービス コンシューマで RPC インターフェイスを呼び出します。

rpcContextAsyncService.async("Thanks");

Future<String> future = RpcContext.getServiceContext().getFuture();
System.out.println(future.get());

一般化コール

Dubbo の汎用呼び出しは、サービス プロバイダー API (SDK) に依存せずにサービスを呼び出す実装方法を提供します。主なシナリオはゲートウェイ プラットフォームの実装にありますが、通常、ゲートウェイの実装は他のサービスの API (SDK) に依存すべきではありません。

Dubbo は公式に 3 つの一般化呼び出しメソッドを提供します。

  • API を介した汎用呼び出しの使用
  • Spring 経由の汎用呼び出しの使用 (XML 形式)
  • Protobuf オブジェクト一般化呼び出し

ここでは、汎用呼び出しを XML 形式で設定する方法を紹介します。

準備

まず、サービス プロビジョニング用の GenericProvider プロジェクトを準備します。プロジェクトの構造は次のとおりです。

インターフェイスはプロジェクト、つまり実装クラス GenericProviderService および GenericProviderServiceImpl で定義されます。コードは次のとおりです。

public interface GenericProviderService {
	String say(String message);
}

public class GenericProviderServiceImpl implements GenericProviderService {
	@Override
	public String say(String message) {
		return "GenericProvider say:" + message;
	}
}

generic-dubbo-provider.xml では、GenericProvider によって提供されるサービスのみを通常どおりに構成する必要があります。

'<bean id="genericProviderServiceImpl" class="com.wyz.service.impl.GenericProviderServiceImpl"/>
<dubbo:service interface="com.wyz.service.api.GenericProviderService" ref="genericProviderServiceImpl" generic="true"/>

application.yml ファイルの構成については詳しく説明しません。

サービスコンシューマの構成

XMLConsumer プロジェクトに戻り、まず Dubbo サービス参照を構成し、次のコンテンツを xml-dubbo-consumer.xml に追加します。

<dubbo:reference id="genericProviderService" generic="true" interface="com.wyz.service.api.GenericProviderService"/>

パラメータ generic は、これが汎用呼び出しサービスであることを宣言しますこのとき、IDEA は「」を赤色でマークし、「クラス 'GenericProviderService' を解決できません」というプロンプトを表示します。パッケージの下に GenericProviderService インターフェイスが存在しないinterface="com.wyz.service.api.GenericProviderServiceため、これに注意を払う必要はありません。com.wyz.service.api

次に、GenericProviderService インターフェイスを使用してみましょう。

ApplicationContext context = SpringContextUtils.getApplicationContext();
// genericProviderService是XML中定义的服务id
GenericService genericService = (GenericService) context.getBean("genericProviderService");

// $invoke的3个参数分别为:方法名,参数类型,参数
Object result = genericService.$invoke("say", new String[]{"java.lang.String"}, new Object[]{"wyz"});
System.out.println(result);

このようにして、ApplicationContext を通じて GenericProviderService インターフェイスによって提供されるサービスを取得できます。

ヒント: ApplicationContext を取得するには SpringContextUtils を使用します。コードは次のとおりです。

@Component
public class SpringContextUtils implements ApplicationContextAware {
	private static ApplicationContext applicationContext = null;

	public static ApplicationContext getApplicationContext() {
		return SpringContextUtils.applicationContext;
	}

	@Override
	public void setApplicationContext(@Nonnull ApplicationContext applicationContext) throws BeansException {
		SpringContextUtils.applicationContext = applicationContext;
	}
}

エピローグ

さて、これまでのところ、私たちは Dubbo の共通機能の構成と使用法について知り、学んできました。もちろん、何年もの開発を経て、Dubbo はこれよりもはるかに多くの機能を提供します。さらに詳しく知りたい場合は、ドキュメントを参照してください。」 Alibaba が提供するエントリーからマスターまでの Apache Dubbo マイクロサービス フレームワーク」 。

次回の記事では、Dubbo の実装原理をサービス登録部分から正式に検討していきます。


この記事が役に立った場合は、たくさんの賞賛とサポートをお願いします。記事に間違いがあった場合は、批判と修正をお願いします。最後に、皆さんもぜひ、ハードコア Java テクノロジーを共有する金融マン

おすすめ

転載: blog.csdn.net/m0_74433188/article/details/132661862