QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

処理時間のかかるリモートオブジェクトのメソッドを呼び出すとエラーになるのですが

実行環境

WindowsXP Pro SP1
.NET Framework1.1 SP1

Singleton型リモートオブジェクトを使用しています。
処理に時間がかかるメソッドを実行すると120秒前後のところで
必ず、例外(System.Runtime.Remoting.RemotingException等)が発生してしまいます。

試しにマイクロソフトのサンプル

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconremotingexamplehostinginiis.asp

にThread.Sleepでウエイトを挿入すると同様の現象が発生しました。

念のためにSingleton用のサンプル(一番下に貼っておきます)も作って見ましたが結果は一緒でした。

ウエイトを120秒にすると必ず落ちます。
どんどん時間を減らしていくと105秒では落ちるが104秒だとOKでした。

この現象はIISをリモートオブジェクトのコンテナにした場合のみに発生しています。

フォーマッタをバイナリ、XMLどちらにしてもダメでした。

リース期間、タイムアウトを設定してもダメでした。

デリゲートを使用した非同期呼び出しを行ってもダメでした。

回避方法をご存知の方がいらっしゃいましたら、ぜひご教授おねがいします。

現象再現サンプル



\------------------------ ServiceClass.cs ------------------------
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Web;

public class ServiceClass : MarshalByRefObject {
   public string GetServerString(){
      Thread.Sleep(1000 * 120);
      return "Hi";
   }
}

\------------------------ Web.config ------------------------

<configuration>
   <system.runtime.remoting>
      <application>
         <service>
            <wellknown mode="Singleton" type="ServiceClass, ServiceClass" objectUri="ServiceClass.rem"/>
         </service>
         <channels>
            <channel ref="http"/>
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

\------------------------ Client.cs ------------------------

using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Security.Principal;

public class Client {
   public static void Main(string[] Args){
        ServiceClass service = (ServiceClass)Activator.GetObject(typeof(ServiceClass), 
                                "http://localhost/HttpBinary/ServiceClass.rem");
        Console.WriteLine("The server says : " + service.GetServerString());
   }
}


質問者:アッキー

回答

なるほどです。
やはり、実務では様々な視点でみて「適切である」ということを決定するのですね。
大変参考になりました。

というか、こんなにも考えなくてはいけないことがあるのかと、
感心しました。

投稿者:nanbu

編集 履歴 (0)

 「webへの書き込み禁止」なところにいるので、日中は読めますが、書き込みできません。夜、早朝は、妻に「書き込み数が2位以下になるまで禁止」と言われているので(^^;、妻の目を盗んでのアクセスとなります。遅いアクセスはご容赦ください。
#っつうか、元々Webのコミュニケーションって、そういうものだし・・・

 どのような物であるか書いていないですから、どのようにも解釈できるわけですよね。私は、リッチクライアントを想像しました。

 また、たとえば夜間バッチ処理であったとしても、そこには「夜間」に終わらせなければならないという制限があります。時間を決めてメンテナンス時間をもうけ、その間に行う処理かもしれませんが、それにしても「メンテナンス時間」という制限があります。どのような機能であれ、「無限にある時間を無限に使える」わけではない、と思います。
 また、使う側はいい加減(作る側からすると)なもので、「1時間ぐらいならいいよ」といいながら、実際に1時間待たせると「遅い」と言います。

 知り合いのオペレータが体験したことですが、夜間メンテの直前にホストが異常停止し、復旧したのはメンテ終了時間の30分ほど前だった、ということがあったそうです。通常のバックアップでは全然時間が足りないので、その人は緊急度の高いデータのみバックアップし、その他のデータは優先度を低くしたプロセスで、実務中に行ったそうです。このように、いつ、何が発生するか分からないので、「1時間あるから、50分くらいかかってもいいや」というような設計は危険です。もちろん、「作った当初は2時間かかっていたけれど、何とか50分で終わるようにチューニングできた」というのは別です。

 私の「その辺の設計を見直す必要があるんじゃない?」というのは、「3分もらっているから、3分以内に終わればいいや」という安易な考えで設計しているなら、それを見直せ、ということです。3分以内に終わればいいやではなく、可能な限り早く終わるように設計(チューニング)するべき、ということです。データ量に左右されるような処理であるならなおさらです。その辺、何も書いていないので、クリティカルな方で考えています。

投稿者:Jitta

編集 履歴 (0)

 ほう!では、8時間、黙りになった端末の前で待ちますか?

私は、httpRuntimeのexecutionTimeoutの値と応答性には関連があるとは
認識しておりませんし、また、アッキーさんと同様にクライアントの実装や
リモートメソッドの実装に関して言及していませんので、上記の発言の意
図するところが思い当たりません。

私の認識に誤り・不足があればご指摘下さい。

投稿者:nanbu

編集 履歴 (0)

Jittaさんの書き込み (2004-09-27 06:22) より:

 もし、誰も操作する人がいない端末で行うものであったり、バックグラウンドで人知れず行う処理であれば、それでもいいでしょう。

なるほど、OKである場合もあるのですね。
アッキーさんの場合は、どういった処理だったのでしょう。
先の投稿で、処理内容には触れず「設計を見直す」という言葉が使用されていたため、
.NETリモーティングのホストをIISにする場合の、「共通の」
「実務ではこうすべき」とか、
「こうするのが行儀がよい」
パターンがあるのでは、と思いました。

Jittaさんの書き込み (2004-09-27 06:22) より:

しかし、何らかの形で人間が関わる処理であれば、遅くても1分以内、できれば20秒、最良は3秒以内にフィードバックを返すべきです。「お待ちください」を出したとしても、3分も待たせてはいけません。

これに関しては、
1.クライアント側で非同期呼び出しを使う方法と、
2.甕星さんの投稿のように、リモートメソッド内で実装する方法が思いつきますが、
.NET リモーティングのようなRPCの場合は、どのように実装するのがよりよいのでしょう。
私が見かけたサンプルでは、1.の非同期呼び出ししかありませんでした。

やはり、実行する処理によって使い分けるものなのでしょうか。

投稿者:nanbu

編集 履歴 (0)

nanbuさんの書き込み (2004-09-26 18:38) より:

なので、「設計を見直す」という意見の根拠がイマイチ、ピンときません。

「実務ではこうすべき」とか、

「こうするのが行儀がよい」

という意見があれば、ぜひ、ご教授願いたいと思います。

 ほう!では、8時間、黙りになった端末の前で待ちますか?

 もし、誰も操作する人がいない端末で行うものであったり、バックグラウンドで人知れず行う処理であれば、それでもいいでしょう。しかし、何らかの形で人間が関わる処理であれば、遅くても1分以内、できれば20秒、最良は3秒以内にフィードバックを返すべきです。「お待ちください」を出したとしても、3分も待たせてはいけません。「お待ち管債を出したまま、止まっているのではないか」と思わせます。

#1分、20秒は経験的な感覚によるもの
#3秒は何かのガイドで提示されていた値

投稿者:Jitta

編集 履歴 (0)

南部です。

Jittaさんの投稿にあるような視点はとても重要だと思います。
実際の業務レベルでは、どのように実装するのでしょう?

Jittaさん、甕星さんは、
「タイムアウト時間の設定に依存しないように設計を見直すべき」
という意見であると解釈しましたが(間違いであればご指摘下さい)、
甕星さんの投稿のように、
「タイムアウトが発生するほど時間のかかる処理はバックグラウンドで処理する」
とういうような実装にすべきなのでしょうか。

私は安易に、通常の運用では考えられない処理時間を
タイムアウトに設定すればいいかなと考えてしまいました。
例えば、業務時間が8時間と想定されているならそれを超えた場合はエラーにする、と。
httpRuntimeのexecutionTimeoutはこのような使用目的であり、
IISをホストとしたときの恩恵のひとつと認識していたためです。

なので、「設計を見直す」という意見の根拠がイマイチ、ピンときません。
「実務ではこうすべき」とか、
「こうするのが行儀がよい」
という意見があれば、ぜひ、ご教授願いたいと思います。

投稿者:nanbu

編集 履歴 (0)

本当にタイムアウトが発生するほど時間のかかる処理を行うなら、インターフェースの設計を見直したほうが良い。要求w受けた時点でバックグラウンドで処理を開始、データの取得は別のメソッドにするとかね。

投稿者:甕星

編集 履歴 (0)

 正常?何をもって“正常”とするの?たとえば、タイムアウト時間を180秒と設定して、実際に処理に200秒かかったら、どうするの?200秒ですむのだったら、250とかに設定すればいいけど、その上限はどうやったら出てくるの?その辺の設計を見直す必要があるんじゃない?

投稿者:Jitta

編集 履歴 (0)

南部さんのおっしゃるとおりWeb.conigに追加したら
正常に動作しました。どうもありがとうございます!

投稿者:アッキー

編集 履歴 (0)

南部です。

例外(System.Runtime.Remoting.RemotingException等)
等、、、なので、勝手に推測します。
外れていたらすみません。

その1:
-- 例外 --
System.Net.WebException: 基になる接続が閉じられました : 受信時に予期しないエラーが発生しました。
----------
この場合は、IISのWebサイトのプロパティで
「接続タイムアウト」を増やして下さい。

その2:
-- 例外 --
System.Runtime.Remoting.RemotingException:
............

もしくは、

System.Runtime.Serialization.SerializationException: BinaryFormatter バージョンに互換性がありません。バージョン 1.0 が必要ですが、バージョン 1008738336.1684104552 を受け取りました。
------
の場合、
Web.configの
/configuration/system.web要素の子に

を追加して下さい。
なお、executionTimeoutの単位は秒で、
既定値は90(machine.configの値)です。

なお、こちらでの動作確認環境は
Windows Server 2003
.NET Framework 1.1 SP1
です。

投稿者:nanbu

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。