AMQPを使用したSpring Remoting
1. 概要
シリーズのprevious installmentsで、Spring Remotingと関連テクノロジーを活用して、サーバーとクライアント間のHTTPチャネル上で同期Remote Procedure Callsを有効にする方法を説明しました。
この記事では、explore Spring Remoting on top of AMQP, which makes it possible to execute synchronous RPC while leveraging a medium that is inherently asynchronousを使用します。
2. RabbitMQのインストール
使用できるAMQPと互換性のあるさまざまなメッセージングシステムがありますが、RabbitMQは実績のあるプラットフォームであり、Spring –で完全にサポートされているため、両方の製品が同じ会社によって管理されているため、RabbitMQを選択します。 (重要)。
AMQPまたはRabbitMQに精通していない場合は、quick introductionを読むことができます。
したがって、最初のステップは、RabbitMQをインストールして開始することです。 インストールにはさまざまな方法があります。in the official guideに記載されている手順に従って、お好みの方法を選択してください。
3. Mavenの依存関係
サーバーとクライアントのSpring Bootアプリケーションをセットアップして、AMQP Remotingがどのように機能するかを示します。 Spring Bootの場合によくあることですが、正しいスターター依存関係as explained hereを選択してインポートする必要があります。
org.springframework.boot
spring-boot-starter-amqp
org.springframework.boot
spring-boot-starter-tomcat
埋め込まれたHTTPサーバーは必要ないため、spring-boot-starter-tomcatを明示的に除外しました。これは、Mavenがクラスパス内のすべての推移的な依存関係をインポートできるようにすると、代わりに自動的に起動されます。
4. サーバーアプリケーション
4.1. サービスを公開する
以前の記事で示したように、リモートサービスの可能性をシミュレートするCabBookingServiceを公開します。
Let’s start by declaring a bean that implements the interface of the service we want to make remotely callable.これは、サーバー側で実際にサービス呼び出しを実行するBeanです。
@Bean
CabBookingService bookingService() {
return new CabBookingServiceImpl();
}
Let’s then define the queue from which the server will retrieve invocations.この場合、コンストラクターで名前を指定して、名前を指定するだけで十分です。
@Bean
Queue queue() {
return new Queue("remotingQueue");
}
以前の記事ですでに知っているように、one of the main concepts of Spring Remoting is the Service Exporterは、あるソースから実際にcollects the invocation requestsであるコンポーネントであり、この場合はRabbitMQキュー─and invokes the desired method on the service implementationです。
この場合、AmqpInvokerServiceExporterを定義します。これは、ご覧のとおり、AmqpTemplateへの参照が必要です。 AmqpTemplateクラスはSpring Frameworkによって提供され、JdbcTemplateがデータベースの処理を容易にするのと同じように、AMQP-互換のメッセージングシステムの処理を容易にします。
このようなAmqpTemplate Beanは、Spring Bootの自動構成モジュールによって自動的に提供されるため、明示的に定義しません。
@Bean AmqpInvokerServiceExporter exporter(
CabBookingService implementation, AmqpTemplate template) {
AmqpInvokerServiceExporter exporter = new AmqpInvokerServiceExporter();
exporter.setServiceInterface(CabBookingService.class);
exporter.setService(implementation);
exporter.setAmqpTemplate(template);
return exporter;
}
最後に、define a container that has the responsibility to consume messages from the queue and forward them to some specified listenerにする必要があります。
次に、前の手順で作成したconnect this container to the service exporter,、to allow it to receive the queued messagesを作成します。 ここで、ConnectionFactoryは、AmqpTemplateと同じ方法で、Spring Bootによって自動的に提供されます。
@Bean
SimpleMessageListenerContainer listener(
ConnectionFactory facotry,
AmqpInvokerServiceExporter exporter,
Queue queue) {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(facotry);
container.setMessageListener(exporter);
container.setQueueNames(queue.getName());
return container;
}
4.2. 設定
Spring Bootが基本オブジェクトを構成できるようにapplication.propertiesファイルを設定することを忘れないでください。 明らかに、パラメータの値は、RabbitMQがインストールされた方法にも依存します。
たとえば、RabbitMQがこの例が実行されているのと同じマシンで実行されている場合、次の構成が適切な構成になる可能性があります。
spring.rabbitmq.dynamic=true
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.host=localhost
5. クライアントアプリケーション
5.1. リモートサービスを呼び出す
それでは、クライアントに取り組みましょう。 繰り返しますが、define the queue where invocation messages will be written toにする必要があります。 クライアントとサーバーの両方が同じ名前を使用していることを再確認する必要があります。
@Bean
Queue queue() {
return new Queue("remotingQueue");
}
クライアント側では、サーバー側よりも少し複雑なセットアップが必要です。 実際、関連するBindingと一緒にdefine an Exchangeを実行する必要があります。
@Bean
Exchange directExchange(Queue someQueue) {
DirectExchange exchange = new DirectExchange("remoting.exchange");
BindingBuilder
.bind(someQueue)
.to(exchange)
.with("remoting.binding");
return exchange;
}
ExchangesおよびBindingsとしてのRabbitMQの主要な概念に関する優れたイントロがhereで利用可能です。
Spring BootはAmqpTemplateを自動構成しないため、routing keyを指定して自分で設定する必要があります。 その際、routing keyとexchangeが、前の手順でExchangeを定義するために使用したものと一致することを再確認する必要があります。
@Bean RabbitTemplate amqpTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
template.setRoutingKey("remoting.binding");
template.setExchange("remoting.exchange");
return template;
}
次に、他のSpring Remoting実装で行ったように、define a FactoryBean that will produce local proxies of the service that is remotely exposedを実行します。 ここではあまり凝っていませんが、リモートサービスのインターフェイスを提供するだけです。
@Bean AmqpProxyFactoryBean amqpFactoryBean(AmqpTemplate amqpTemplate) {
AmqpProxyFactoryBean factoryBean = new AmqpProxyFactoryBean();
factoryBean.setServiceInterface(CabBookingService.class);
factoryBean.setAmqpTemplate(amqpTemplate);
return factoryBean;
}
これで、リモートサービスをローカルBeanとして宣言されているかのように使用できます。
CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));
5.2. セットアップ
また、クライアントアプリケーションの場合、application.propertiesファイルの値を適切に選択する必要があります。 一般的な設定では、これらはサーバー側で使用されるものと正確に一致します。
5.3. 例を実行する
これは、RabbitMQを介したリモート呼び出しを示すのに十分なはずです。 次に、RabbitMQ、サーバーアプリケーション、およびリモートサービスを呼び出すクライアントアプリケーションを起動しましょう。
舞台裏で起こることは、AmqpProxyFactoryBean will build a proxy that implements the CabBookingServiceです。
メソッドがそのプロキシで呼び出されると、RabbitMQにメッセージをキューに入れ、呼び出しのすべてのパラメーターと、結果を送り返すために使用されるキューの名前を指定します。
メッセージは、実際の実装を呼び出すAmqpInvokerServiceExporterから消費されます。 次に、結果をメッセージに収集し、着信メッセージで指定された名前のキューに配置します。
AmqpProxyFactoryBeanは結果を受け取り、最後に、サーバー側で最初に生成された値を返します。
6. 結論
この記事では、Spring Remotingを使用してメッセージングシステム上にRPCを提供する方法を説明しました。
おそらくRabbitMQの非同期性を活用することを好む主なシナリオに進む方法ではありませんが、一部の選択された限定されたシナリオでは、同期呼び出しが理解しやすく、開発が迅速かつ簡単になる場合があります。
いつものように、ソースはover on GitHubにあります。