1概要

このシリーズのリンク:/spring-remoting-http-invoker[前回の記事]では、サーバーとクライアントの間のHTTPチャネル上で同期リモート呼び出しを有効にするためのSpring Remotingとその関連テクノロジの活用方法について説明しました。

この記事では、

AMQP

の上にある

Spring Remoting

を探ります。これは、本質的に非同期** であるメディアを活用しながら、同期

RPC

を実行することを可能にします。


2 RabbitMQ

のインストール


AMQP

と互換性のあるさまざまなメッセージングシステムを使用できますが、それは実証済みのプラットフォームであり、

Springで完全にサポートされているので

RabbitMQ__を選択しています。

あなたが

AMQP



RabbitMQ

に詳しくないなら、私たちのリンクを読むことができます:/rabbitmq[簡単な紹介]。

したがって、最初のステップは

RabbitMQ

をインストールして起動することです。インストールするにはさまざまな方法があります –

公式ガイド

に記載されている手順に従ってご希望の方法を選択してください。


3 Mavenの依存関係

AMQP Remotingがどのように機能するかを示すために、サーバーとクライアントのSpring Bootアプリケーションを設定します。

Spring Boot

の場合と同様に、正しいスターターの依存関係、link:/spring-boot-startersを選択してインポートする必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>


spring-boot-starter-tomcat

を明示的に除外しました。組み込みの

HTTP

サーバーは必要ないからです。これは、

Maven

がクラスパス内のすべての推移的な依存関係をインポートできるようにすると、代わりに自動的に起動されます。


4サーバーアプリケーション


4.1. サービスを公開する

前の記事で示したように、リモートサービスをシミュレートする

CabBookingService

を公開します。

  • リモート呼び出し可能にするサービスのインターフェースを実装するBeanを宣言することから始めましょう** これは、実際にサーバー側でサービス呼び出しを実行するBeanです。

@Bean
CabBookingService bookingService() {
    return new CabBookingServiceImpl();
}

  • サーバーが呼び出しを取得するキューを定義しましょう** この場合は、名前を指定してコンストラクタで指定すれば十分です。

@Bean
Queue queue() {
    return new Queue("remotingQueue");
}

以前の記事からすでに知っているように、

Spring Remoting

の主な概念の1つは

Service Exporter


です。これは実際には何らかのソースからの呼び出し要求を収集したもので、この場合は

RabbitMQ

キューですサービス実装上の望ましい方法

この場合、

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;
}

最後に、キューからメッセージを消費し、それらを特定のリスナーに転送する責任を持つ

container

を定義する必要があります。

次に、この

container

を、前の手順で作成した

service exporterに接続します。ここで

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

がこの例を実行するのと同じマシンで

RabbitMQ

を実行する場合、次のような構成が妥当な構成になります。

spring.rabbitmq.dynamic=true
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.host=localhost


5クライアントアプリケーション


5.1. リモートサービスを起動する

今クライアントに取り組みましょう。繰り返しますが、呼び出しメッセージが書き込まれるキューを定義する必要があります。クライアントとサーバーの両方が同じ名前を使用していることを再確認する必要があります。

@Bean
Queue queue() {
    return new Queue("remotingQueue");
}

クライアントサイドでは、サーバーサイドよりも少し複雑な設定が必要です。実際、関連する

Binding

を持つ

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

の主な概念に関する優れた紹介は、http://www.rabbitmq.com/tutorials/tutorial-four-java.html[こちら]から入手できます。


Spring Boot



AmqpTemplate

を自動設定しないので、r

__outing 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

実装と同じように、

リモートで公開される

サービスのローカルプロキシを生成する

FactoryBean

を定義します。ここであまりにも派手なものは何もない、我々はただリモートサービスのインターフェースを提供する必要がある:

@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



CabBookingService


を実装するプロキシを構築するということです。

そのプロキシでメソッドが呼び出されると、そのメソッドは呼び出しのすべてのパラメータと結果の返送に使用されるキューの名前を指定して

RabbitMQ

のメッセージをキューに入れます。

メッセージは、実際の実装を呼び出す

AmqpInvokerServiceExporter

から消費されます。次に、結果をメッセージにまとめて、着信メッセージで指定された名前のキューに入れます。


AmqpProxyFactoryBean

は結果を受け取り、最後に元々サーバーサイドで生成された値を返します。


6. 結論

この記事では、

Spring Remoting

を使用してメッセージングシステム上でRPCを提供する方法を説明しました。


RabbitMQ

の非同期性を活用することをお勧めする主なシナリオに進むのはおそらく方法ではありませんが、一部の限られたシナリオでは、同期呼び出しの方が理解しやすく、開発が簡単になります。

いつものように、あなたはhttps://github.com/eugenp/tutorials/tree/master/spring-remoting/remoting-amqp[over on GitHub]にソースを見つけるでしょう。