2016-08-29 4 views
2

Webサーバーにリクエストが送信され、REST APIが呼び出されたとします。この要求には時間がかかるサーバーの仕事があります。したがって、Webサーバーコードは、他のサーバーにジョブを委任してスケーラブルなソリューションを提供します。このシナリオは、通常、Publisher-Subscriberパターンを使用して実装されます。REST APIでサブスクライバを使用するにはどうすればよいですか?

これまでのところ良い結果が得られましたが、その結果を依頼したい場合はどうすればいいですか?私は出版社と購読者を別の方法で回すことができるので、今すぐREST APIコードは、結果の準備が整ったときに通知を受けるために一部の出版社が待つことになります。

このシナリオの問題点は、通知を購読することが非同期で行われることです(それ自体完璧です)。したがって、このようになりますRabbitMQのからの通知を待っている春のREST APIを実装する:

@RequestMapping(value = "/url", method = RequestMethod.GET) 
public ResponseEntity url() 
{ 
    ConnectionFactory factory = new ConnectionFactory(); 
    factory.setHost("localhost"); 
    Connection connection = factory.newConnection(); 
    Channel channel = connection.createChannel(); 
    String command = "Job Description"; 
    channel.basicPublish("", "Heavy Worker", null, command.getBytes()); 

    Consumer consumer = new DefaultConsumer(channel) 
    { 
     @Override 
     public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) 
      throws IOException 
     { 
      String result = new String(body, "UTF-8"); 
      //return the result as the HTTP response 
     } 
    }; 
    channel.basicConsume("Heavy Job Result", true, consumer); 
} 

私は上記のコード例で説明しようとしている問題があるchannel.basicConsume("Heavy Job Result", true, consumer);後、応答がクライアントに返されることとJavaは"Heavy Job Result"が準備されるのを待つことはありません。

ノーポーリングの方法でメッセージの要求をハングアップさせる方法は知られていますか?

答えて

3

解決策は、重い作業が完了するまでにかかる時間によって異なります。あなたのための残りを処理する

@RequestMapping(value = "/url", method = RequestMethod.GET) 
public CompletableFuture<ResponseEntity> url() { 
    return CompletableFuture.supplyAsync(() -> { 
    // do your computations here 
    }); 
} 

春:それはあなたのサーバーのタイムアウトは、あなたがしなければならないすべてはCompletableFutureかそこらのようなListentableFutureを返すことによって、あなたのウェブIOをブロックしていない、のために設定されるよりも短い時間で完了した場合。

サーバーのタイムアウトよりも時間がかかる場合は、WebSocketを使用して、ジョブの完了時にサーバーからクライアントにメッセージを送信する処理を行うことができます。 Spring WebSocket Supportをご覧ください。流れは次のようになります。

  1. は新しいスレッドで長時間実行プロセッサに要求に
  2. 手それを受け取る(例えばCompletableFuture.runAsync())
  3. リターンこの新しいスレッド
  4. をキックオフ直後の応答ジョブが終了したら
  5. は、あなたはそれはあなたが
+0

@Mehranを含めるどんなデータで完成されたフロントエンドにメッセージを送信する - あなたが有用な答えを見つけた場合、受け入れてください。 – SergeyB

関連する問題