スレッドを使用して、IIS で長時間実行されるジョブを実行できますか?
-
22-08-2019 - |
質問
ASP.Net アプリケーションでは、ユーザーが Web ページ上のボタンをクリックすると、イベント ハンドラーを通じてサーバー上のオブジェクトがインスタンス化され、そのオブジェクトのメソッドが呼び出されます。このメソッドは外部システムにアクセスして処理を行うため、時間がかかる可能性があります。そこで、私がやりたいのは、そのメソッド呼び出しを別のスレッドで実行して、「リクエストが送信されました」というメッセージをユーザーに返すことができるようにすることです。私はこれをファイア・アンド・フォーゲットとして実行することにかなり満足していますが、ユーザーがオブジェクトのステータスをポーリングし続けることができればさらに良いでしょう。
わからないのは、ユーザー セッションの有効期限が切れた場合でも、IIS がスレッドの実行を継続できるかどうかです。ユーザーがイベントを起動し、サーバー上でオブジェクトをインスタンス化し、新しいスレッドでメソッドを起動すると想像してください。ユーザーは「リクエストが送信されました」というメッセージに満足し、ブラウザを閉じます。最終的に、このユーザー セッションは IIS でタイムアウトになりますが、スレッドはまだ実行中で、作業を行っている可能性があります。IIS はスレッドの実行を継続させますか、それともユーザー セッションの有効期限が切れたらスレッドを強制終了してオブジェクトを破棄しますか?
編集:回答とコメントから、これを行うための最良の方法は、長時間実行される処理を IIS の外に移動することであることがわかりました。他のすべてとは別に、これはアプリドメインのリサイクル問題を扱います。実際には、限られた時間内にバージョン 1 をリリースする必要があり、既存のフレームワーク内で作業する必要があるため、サービス層を避けたいため、IIS 内でスレッドを起動するだけで済みます。実際には、ここでの「長時間実行」はわずか数分であり、Web サイトの同時実行性は低いため、問題ないはずです。ただし、次のバージョンでは、必ず別のサービス層に分割する必要があります。
解決
あなたが望むものを達成することができますが、それは一般的に悪い考えです。彼らは、共有ホスティングシステム上でインストール可能とインストールする必要がWindowsサービスの依存を取らないしたいので、いくつかのASP.NETのブログやCMSエンジンは、このアプローチを取ります。通常、アプリが起動したとき、彼らは、Global.asaxの中に長い実行中のスレッドをキックオフし、そのスレッドのプロセスがタスクをキューに入れられています。
の要求を処理するためにIIS / ASP.NETに利用可能なリソースを減らすことに加えて、あなたものAppDomainがリサイクルされたときに殺されたスレッドの問題があり、それがインである一方で、あなたは、タスクの持続性に対処する必要があります飛行、などのAppDomainが復帰する際のバックアップ作業を開始します。
あなたはweb.configファイルを更新する場合は、など、多くの場合、アプリケーションドメインがデフォルトの間隔で自動的に再利用されることを覚えておいてください、など。
あなたが永続性とあなたのスレッドは、いつでも殺されるのトランザクションの側面を扱うことができる場合は、、そして、あなたには、いくつかの間隔でサイト上の要求を行い、いくつかの外部プロセスを持つことにより、AppDomainのリサイクルを回避することができます - ので、そのサイトであればあなたはそれがX分以内に自動的にバックアップを再度起動することが保証されているリサイクルされます。
繰り返しますが、これは一般的に悪い考えです。
編集:ここではアクションでこの技術のいくつかの例があります:
コミュニティサーバー:使用しますスケジュールされた間隔でコードを実行するバックグラウンドスレッド対Windowsサービスする 作成ウェブサイトまずの
を開始し、バックグラウンドスレッドEDIT(遠い遠い未来から) - 。最近、私が使用する Hangfireする
他のヒント
私は国立大学志望の浪人生では、受け入れの答えです。
を背景にスレッドはタスクの開始 Task.Factory.StartNew
とするにはASP.NET.全てのグールする必要がありますの理解と協力して、施設の統治シャットダウンしました。
にASP.NETできる登録作業が必要な停止を優雅に関の停止を HostingEnvironment.RegisterObject
方法。見 この記事 のコメントのための議論が交わされる。
(ジェラルド-デ-グラウ氏のコメントがありま HostingEnvironment.QueueBackgroundWorkItem
ることに RegisterObject
登録スケジューラの背景に商品。全体の新しい方法がお勧めですることもできます。)
としての主題にしたという話をよく聞きますので念の検討、代替の導入をwindowsのサービス(または別のプロセス申請):
- な些細な展開ウェブ展開
- な展開は、純粋にAzure webサイト
- によっては自然のバックグラウンドタスク、プロセス性が増してます。その手段のいずれか一のIPCまたは本サービスにアクセスの共通データベースです。
また、いくつかの先進シナリオがあっても必要性の背景のスレッドを走らせることになり、同じアドレス空間とを承りますのでご相談ください。を見ることASP.NET できないことが大きな強みとなっている可能。います。
あなたはそれが将来の要求を処理することができない、そのスレッドを残しているため、このタスクのためのIISのスレッドプールからのスレッドを使用したいとは思わないでしょう。あなたは本当に非同期ASP.NET 2.0 のあるページが、それに見ることができますどちらか、正しい答えではないでしょう。あなたは Microsoftメッセージキュー。基本的に、あなたはそのタスクを実行する担当になりキューと他のバックグラウンド・プロセス(おそらくWindowsサービス)へのタスクの詳細を追加します。しかし、一番下の行は、バックグラウンドプロセスは、IISから完全に分離されていることである。
私は、このような要件については、 HangFire して使用することをお勧めします。その素敵な火災やバックグラウンドでエンジンの実行を忘れては、それが永続ストレージに裏打ちされた信頼性の高いので、異なるアーキテクチャをサポートしています。
良いスレッドとサンプルコードはここにあります: http://forums.asp.net/t /1534903.aspx?PageIndex=2する
私も生きているアプリケーションプールを保つのを助けるために、スレッドからの私のウェブサイト上で生きているページを保つ呼び出すのアイデアをおもちゃにしました。あなたは本当に良い回復処理を必要とするこの方法を使用している場合、アプリケーションはいつでもリサイクル可能性があるため、覚えておいてください。多くはこれを言及しているあなたは、他のサービスオプションへのアクセス権を持っている場合は正しいアプローチではありませんが、これを共有ホスティングのためには、あなただけのオプションのいずれかになります。
スレッドが処理している間に生きているアプリケーションプールを保つのを助けるために、あなたは自分のサイトにリクエストを作ることができます。あなたのプロセスが長い時間を実行している場合、これは生きているアプリケーションプールを保つのを助けることがあります。
string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx");
public static string GetUrlPageSource(string url)
{
string returnString = "";
try
{
Uri uri = new Uri(url);
if (uri.Scheme == Uri.UriSchemeHttp)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
CookieContainer cookieJar = new CookieContainer();
req.CookieContainer = cookieJar;
//set the request timeout to 60 seconds
req.Timeout = 60000;
req.UserAgent = "MyAgent";
//we do not want to request a persistent connection
req.KeepAlive = false;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
StreamReader sr = new StreamReader(stream);
returnString = sr.ReadToEnd();
sr.Close();
stream.Close();
resp.Close();
}
}
catch
{
returnString = "";
}
return returnString;
}
私たちは、この道を開始し、我々のアプリは、1台のサーバー上だったとき、それは実際には[OK]を働きました。我々は複数のマシンにスケールアウト(またはWeb garenで複数のw3wpを使用)したい場合は、我々は再評価および作業キューを管理する方法を見て、エラー処理、再試行して正しく一つだけを確実にするために、ロックのトリッキーな問題に持っていましたサーバーは、次の項目をピックアップ。
...我々は書き込みバックグラウンド処理エンジンのビジネスではありません実現ので、我々は既存のソリューションのために見て、私たちは素晴らしいOSSプロジェクトを使って上陸<のhref =「http://hangfire.io/」のrel = "nofollowを"> hangfire の
セルゲイOdinokovはで始めるのは非常に簡単です、あなたは仕事が持続し、キューに入っているかのバックエンドを交換することができます本物の宝石を作成しました。 Hangfireは、バックグラウンドスレッドを使用しますが、雇用を持続、再試行を処理し、作業キューの中にあなたの可視性を提供します。だから、hangfireジョブは堅牢であり、その他のAppDomainのすべての気まぐれがリサイクルされて生き残る
その基本的な設定は、ストレージとしてSQL Serverを使用していますが、その時間はスケールアップしたときには、RedisのかMSMQのためにスワップアウトすることができます。また、すべてのジョブとその状態を可視化プラスあなたはジョブキューの再することを可能にするための優れたUIを持っています。
私のポイントは、あなたがバックグラウンドスレッドでやりたいのは完全に可能ではあるが、それはスケーラブルで堅牢にするために多くの仕事があることです。シンプルなワークロードのためのその罰金が、物事が複雑に得るとき、私は多くの目的に構築されたライブラリを使用するのではなく、この取り組みを通過することを好みます。
オフカバースコットHanselman氏のブログをチェックし、利用可能なオプションのいくつかのより多くの視点のためにasp.netでバックグラウンドジョブを処理するためのいくつかのオプション。
(彼はhangfire熱烈な見直しを行いました) フィル・ハークの<のhref = "http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-inを読んまた、ジョンによって参照としてその価値-asp-net.aspx /」のrel = 『nofollowを』>アプローチは問題がある、そしてどのように優雅のAppDomainがアンロードされたスレッド上で作業を停止する。理由についてブログで
あなたは、そのタスクを実行するWindowsサービスを作成することはできますか?その後、アクションを実行するためにWindowsサービスを呼び出すためにWebサーバーから.NETリモートを使用できますか?その場合は、それは私が何をするのかです。
これはIISに中継する必要がなくなり、その処理能力の一部を制限する。
でないならば、私はプロセスが行われている間そこに座ってするようにユーザーを強制します。あなたはそれが完了し、IISによって殺されていないことを確認して道ます。
IIS で長時間実行される作業をホストする方法が 1 つサポートされているようです。 ワークフローサービス 特に以下と組み合わせて、このために設計されているようです Windows サーバー AppFabric. 。この設計では、長時間実行される作業の自動永続化と再開をサポートすることで、アプリケーション プールのリサイクルが可能になります。
あなたは、バックグラウンドでタスクを実行することができ、彼らは要求が終了した後も完了します。 にキャッチされない例外がスローさせてはいけません。通常、あなたは常にあなたの例外をスローします。例外は新しいスレッドでスローされた場合、それは<のhref = "http://geekswithblogs.net/EltonStoneman/archive/2011/09/30/uncaught-exceptions-in-task-threads-will-killをクラッシュします-iis ---偶数と-WCF-エラーhandling.aspx」のrel = "nofollowを"> IISワーカープロセス - w3wp.exeのに、あなたは、もはや要求のコンテキストであるため。それはまた、あなたがそれらを使用している場合は、インプロセスのメモリバックアップされたセッションに加えて、実行している他のバックグラウンドタスクを殺すために起こっています。これは実際には落胆している理由である、診断するのは難しいだろう。
ただ、非同期タスクを実行するためのサロゲートプロセスを作成します。それはほとんどの場合、より最適なアプローチであるが、それは(Windowsサービスである必要はありません。MSMQはキルオーバー方法です。