質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

423閲覧

RabbitMQチュートリアルのRPCパターン(サーバ側)のソースコードでWhileループが必要な理由

yokota-g

総合スコア14

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2022/01/15 15:50

RabbitMQチュートリアルのRemote procedure call (RPC)について、サーバ側コード(RPCServer.java)にはchannel.basicConsumeのあとにWhileループがあります。チュートリアルのその他のパターンではWhileループがなくてもクライアント側からのリクエストを待ち続けることができるのに、なぜRPCパターンの場合はWhileループが必要なのか分かりませんでした。
ご存知の方がいましたら、ご教示をお願いいたします。

RabbitMQチュートリアル:RPC
https://www.rabbitmq.com/tutorials/tutorial-six-java.html

RPCServer.java
https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/java/RPCServer.java

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xebme

2022/01/16 01:09

RPCServerのwhileをコメントにしたらどんな動作をしますか。 あなたの見解を追記してください。
yokota-g

2022/01/16 01:29

whileをコメントにしたらクライアントのリクエストを待たずに終了しました。 RPCが他のパターンと違うところとして、下記の2行がtryの条件に記載されていました。  Connection connection = factory.newConnection()  Channel channel = connection.createChannel() 試しに、whileのコメント化と合わせてtryを取り除いてみると、リクエストを待つようにはなり、動作としても一見問題無いように見えます。
guest

回答1

0

ベストアンサー

試した環境

  • Mac OS 12.1 (Intel)
  • OpenJDK 64-Bit Server VM (build 17+35-LTS, mixed mode, sharing)
  • RabbitMQ 3.9.12

プログラム

RPCは、リクエスト/レスポンスがペアになった双方向通信です。サーバーはコールバック用のラムダ式の中で、フィボナッチ数列の第n項を計算して、結果をクライアントに返します。

Remote Procedure Call(rpc)
RPCServer.java
RPCClient.java

クライアントは連続して32回のリクエストを送信して、それぞれ32回のレスポンスを受信します。その間、RPCサーバーが動き続けていないと応答を返せません。動き続けているということは、RPCServerがメッセージブローカーに接続していて、キューを処理できる状態にあるということです。つまり、RPCServerを止めずに、Webサーバーのように常時動作させておきたいのだと思います。

実験

RPCServerの最後のwhile(true)をコメントにすると、RPCServerは1回だけリクエストを処理してレスポンスを返したのちmain()から抜けます。main()を抜けるとRPCServerプロセスが終了して、メッセージブローカーとの接続が切れます。

この時、RPCClientは1回分のレスポンスを受け取り、2回目のリクエストを送信したところでレスポンス待ちになります。メッセージブローカーの先にリクエストを処理してくれるRPCServerがいないから。

RPCServerのwhile(true)はプロセスを終了させずに処理続行するのに必要。これは、アプリの作りとしてそうしているに過ぎません。

考えてみたいこと

キューを利用するシステムは、Webサーバーのように常時動作しなくても良いのでは。もっとゆるい条件で、例えば、RPCServerを32回起動したとしても、RPCClientに正しいレスポンスを返せれば、問題ないと思われます。

試してみると、RPCServerは再起動するとリクエストを処理できませんでした。


追記 (2022-01-24)

「考えてみたいこと」は本題から外れているので無視してください。まず、RCPServerを理解するための技術的な知識を書き、次に、while(true)について意見を述べます。

【技術的な知識】

thread

  • Javaプロセスは、スレッド(daemon以外のスレッド)が全て終了した時点で、終了する
  • RabbitMQのConnection/Channelを生成すると、スレッドが起動し、Connection/Channelを閉じるとスレッドが終了する
    • ExecutorServiceを利用。送受信や、ブローカーの生死確認、シャットダウンのため
    • 本来の目的のChannel処理だけでなく、管理用のスレッドが起動されます

mainスレッドが終了したとき、他にスレッドが生きていればプロセスは終了しません。チュートリアルのプログラムでは、Connectionを作成して閉じなければ、スレッドが生きています。プロセスは終わらないので、CTL-Cで中断します。

try-with-resources

  • try(<リソース設定>) {} の形式。catch, finallyはオプション
  • リソース設定で宣言できる変数は、AutoCloseableインターフェイスを実装するクラス
  • tryブロックを抜けると、AutoCloseableリソースを、宣言が内側のものから順に閉じる

try-with-resoucesを使ってConnection/Channelを利用すると、tryブロックを抜けた時点でConnection/Channelが閉じられ、スレッドが終わる。RPCServerプログラムは、try-with-resoucesを抜けると、mainスレッドが1つだけ生きていて、main()メソッドを抜けたところでスレッドがいなくなり、プロセスが終了する。

notify/wait

RPCserverでは、mainスレッドをビジーウェイトせずに無限ループさせるために使っています。目的は、try-with-resourcesブロックに留まり続けて、生成したConnection配下のChannelのスレッドで、コールバック処理を行わせるためです。

【個人的な意見】

RPCServerでwhile(true) を使う本当の理由はチュートリアル作成者に聞くしかありませんが、RPCServerのやり方が好ましいと思います。

  • try-with-resourcesを使ってChannel/Connectionを明に閉じることで、リソースの利用スコープを制限することができる。
    • Channelを生成すると、メッセージブローカー側にも、ピアのerlang処理が作成される
  • while(true) をwhile(<サーバーの稼働条件>)とすれば、きちんとリソースを解放して、サーバーを行儀良く終了させることができる。

RabbitMQのFAQを調べてみてはいかが。

(RabbitMQについては、わからないことが多く、 調べが進めば追記するかもしれません。)

利用したjarを追記します。

bash

1CLASSPATH=$RABBITMQ_LIB/slf4j-simple-1.7.33.jar:$RABBITMQ_LIB/slf4j-api-1.7.33.jar:$RABBITMQ_LIB/amqp-client-5.14.1.jar

投稿2022/01/16 05:37

編集2022/01/23 00:23
xebme

総合スコア1083

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xebme

2022/01/16 06:57

>チュートリアルのその他のパターンではWhileループがなくてもクライアント側からのリクエストを待ち続けることができるのに、なぜRPCパターンの場合はWhileループが必要なのか分かりませんでした。 この質問に答えていませんね。『考えてみたいこと』に答えなければならない。
xebme

2022/01/16 06:59

メッセージをdurableにするなどして試してみます。
yokota-g

2022/01/16 11:29

回答ありがとうございます。 追記・修正欄にも記載したのですが、私の方でも色々試してみた結果、 ・Whileループは、まるまるコメントアウト ・tryは削除 としても、目的の動作は達成しているように見えました。 java8化したときに、オブジェクト形式のコールバックにbasicPublishやbasicAckを仕込むようになって、whileループは実はいらなくなったのではないか?と思っています(自信は無いです)。
xebme

2022/01/23 00:26

時間が取れず、amqp-clientのソースコードを読んだだけで、回答を書きました。何かわかれば追記します。
yokota-g

2022/01/23 12:32

基本的な話だったのかもしれませんがtry-with-resourcesの理解がありませんでした。記載頂いた回答で不明点のイメージが付いてきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問