- - PR -
WebアプリにおけるDLLの更新方法について
1
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-07-11 14:02
いつも参考にさせていただいております。
早速質問なのですが .NET(C#)でWebサービスの開発をしております。 要件として以下の3つがあります。 1.WEBサービス内で大量(数百〜)のDLLを使用する。 2.使用するDLLはあらかじめ参照設定しておくのではなく Assembly assembly = Assembly.LoadFrom(strDLLPath); Type[] type = assembly.GetTypes(); MyClass obj = (MyClass)assembly.CreateInstance(type[0].ToString()); string strReturn = obj.execute(); のように、実行時にSystem.Reflection.Assemblyクラスを使用してロードして実行する。 3.WEBサービスで使用するDLLはサービスを止めることなく更新する必要がある。 始め、WEBサービスのbinフォルダにDLLを配置していました。 これによりDLLを上書きした場合に、アプリケーションドメインの再起動が発生し 常に最新のDLLをコールすることができていました。 ところがDLLの数が増えるに従い、 アプリケーションドメインの再起動時間(DLL更新後初回実行時にかかる時間)が極めて膨大になってしまったため、 DLL配置先をWEBサービスのbinフォルダから別のフォルダ「例:c:¥test¥bin」に変更し Assembly assembly = Assembly.LoadFrom(@"c:¥test¥bin¥sample.dll"); のように別フォルダからロードするように変更したのですが 今度はメモリにロードされているDLLの上書きが出来なくなってしまいました (当然といえば当然ですが)。 実現したい動作としましては ・DLLの上書きを常に行うことができる ・上書きされたものがWEBサービスの動作に反映される ・WEBサービスアプリの初回実行時間が遅くならない(アプリケーションドメインの再起動が発生しないのが一番です)。 というものなのですが、解決策があれば教えて頂けませんでしょうか。 宜しくお願いします。 | ||||||||||||
|
投稿日時: 2005-07-12 15:55
配置先を変更することで再起動時間を解決できると考えたのは何故なのでしょうか? | ||||||||||||
|
投稿日時: 2005-07-12 16:04
ryuujiさん、返信有難うございます。
初回起動時の起動時間が極めて遅かったので、原因究明をした結果、 Webサービスのbinフォルダ内にあるファイル(DLL)の数(サイズにも)の増加に 伴うことが判明しました。 そこで、DLLの配置先を変更した次第です。 これにより、確かに初回起動時間は極端に短くなりました(数分→数秒)が、 上記のような問題が発生してしまったのです。 | ||||||||||||
|
投稿日時: 2005-07-12 16:41
不思議ですね。アセンブリのサイズは初回呼出し時のコンパイル時間に影響するにしてもファイル数は何に影響しているのでしょう。AppDomainが起動する際にASP.NETが監視対象であるPrivatePath内のアセンブリを読み込んでいるのかも知れません。 となると↓はあまり意味がない気がしますが、 http://weblogs.asp.net/bhouse/archive/2005/05/01/405230.aspx PrivatePathの設定方法の話題です。詳細はMSDNにも記載されています。 適宜アセンブリをロード/アンロードできれば良いのかも知れませんが、メモリはGCまかせなので難しい気がしてきました。。。運用時にアセンブリを入れ替える際、AppDomainを再起動できるツール/手段を用意するとかぐらいしか思い付きません。すいません。 | ||||||||||||
|
投稿日時: 2005-07-12 18:50
ASP.NETではbinフォルダに存在するアセンブリはすべてシャドーコピーした後でコンパイルされ利用されるはず。ということでそのあたりで問題がでているのかもしれませんね。 ただ、そのシャドーコピーのおかげでサービスを止めずにアセンブリの更新ができるので。。。 ちょっとうまい方法は考え付きませんねぇ。 | ||||||||||||
|
投稿日時: 2005-07-12 20:47
私がそんなに大規模な開発をしたことがないから、なのでしょうが、数百になる時点でアプリケーションを分けます。。。だって、保守し切れないじゃないですか。
あと、保守の運用として、いつでも更新、なんて運用はしません。だって、怖いじゃないですか。入れ替え作業中に誰かがデータベースを触っていたら、なんて考えると。そんな運用のテスト、どうやったら「大丈夫」と言えるか、思いつきません。 ということで、私も人間系で何とかする、ことしか思いつきません。すみません。 | ||||||||||||
|
投稿日時: 2005-07-15 19:36
ryuujiさん、どっとねっとふぁんさん、Jittaさん、返信ありがとうございます。
お返事が遅くなって申し訳ございません。 まず、
に関してですが おっしゃるとおりAppDomainの起動時にアセンブリを読み込んでいると思われる挙動をしています。 例えばトータルで1MBのDLLを 1.10KB×100個 2.1MB×1個 にした場合、 原則はサイズとファイル数のどちらにも比例(トータルサイズに比例)することから (どちらかと言えば2の方が起動が早いですが)、 AppDomainの起動時にアセンブリを読み込んでいると判断しました。 実際のDLL利用時にロードしてくれればいいんですけどね。。 次にWEBサービスのbinフォルダ以外にPrivatePathの設定を行い、動作を確認してみましたが、このフォルダも結局はシャドウコピーをするわけではないらしく、 起動は早いものの、メモリにロードされているDLLの上書きは出来ませんでした。
どうしても解決方法が見つからなかったら最終的にはJittaさんのおっしゃるとおり アプリケーションを分けようとは思っています。 ただ、保守しきれないことはないと思いますし、 アプリケーションを分けたところで保守のしやすさがそこまで変わるとは思わないので、 できれば1アプリケーションで実現したいところです。
いつでも更新するというわけではないですが DLL入れ替え作業中に誰かがデータベースを触っている可能性は当然ありますよね。 この場合、DLL内のメソッドが実行されている最中などにも メモリ上のDLLは更新される可能性があるのでしょうか。 (例えば、上書きしたときに実行中のプロセスが終了するまでまって、次のタイミングでメモリを更新といったことはやってくれないのでしょうか) | ||||||||||||
|
投稿日時: 2005-07-16 05:20
あれ?これ、どういう意味で書いたんだろう? 確かに、そうですよね。Web アプリケーションだと、分けたところでセッションが切れるから、余計に難しいのに。すみません、忘れてくださいm(..)m
bin ディレクトリが書き換えられると、ワーカープロセスがリセットする…と書いてあったと思います。
これから判断すると、書き換わった時点でワーカープロセスが再起動することで DLL もメモリから捨てられる、と思います。 これの動作は変更できるかどうか、知りません。変更できるとすると、デバッグがしづらいですよね(^-^; 変更して、三角ボタンをクリックして実行!!でも、実行されるのは変更される前のアセンブリ...とか。 このほか、「終了」というのは、ちょっと難しいですね。ワーカープロセスは、いつまでアプリケーションドメインを保持していればよい、ユーザからのリクエストが来ない、というのを判断できませんから。デフォルトでは、20分くらい要求がなければ、終了すると思います。 _________________ |
1