36

httpモジュールを作成していて、デバッグ中に、最初は(少なくとも)奇妙な動作のように見える何かに気づきました。

httpmoduleのinitメソッドにブレークポイントを設定すると、デバッグのためにWebサイトを起動して単一の要求を行っただけなのに、 http module initメソッドが数回呼び出されていることがわかります(1回だけヒットすることもあります)。 、他の場合は10倍)。

HttpApplicationの複数のインスタンスが実行され、httpモジュールごとに作成されることを期待する必要があることはわかっていますが、単一のページを要求すると、単一のhttpアプリケーションオブジェクトによって処理されるため、関連付けられたイベントは1回だけ発生します。ただし、リクエストごとにイベントを数回発生させますが、これは意味がありません。ただし、そのhttpApplication内に複数回追加されている必要があります。つまり、毎回呼び出されるのと同じhttpmodule initメソッドであり、新しいhttpアプリケーションではありません。ブレークポイントに到達するたびに作成されます(下部のコード例などを参照してください)。

ここで何がうまくいかない可能性がありますか?デバッグしていて、httpモジュールにブレークポイントを設定しているからですか?

デバッグのためにWebサイトを起動し、httpmoduleのブレークポイントをすばやくステップオーバーすると、initメソッドが1回だけヒットし、eventhandlerにも同じことが当てはまるようです。代わりに、ブレークポイントで数秒間ハングさせた場合、initメソッドが数回呼び出されます(ブレークポイントをステップオーバーするまでの待機時間によって異なるようです)。これは、httpmoduleが初期化され、httpアプリケーションが要求を処理できることを確認するための組み込み機能である可能性がありますが、壊滅的な結果をもたらす可能性があるもののようにも見えます。

リクエストを終了しようとしている可能性があり、ブレークポイントを設定したため、問題が発生したと見なしてinitメソッドを再度呼び出そうとするため、これは論理的に見える可能性があります。リクエストを処理できますか?

しかし、これは起こっていることであり、すべてがうまくいっていますか(私は推測しています)、それとも本当の問題ですか?

私が特に懸念しているのは、何かが「本番/ライブ」サーバーで数秒間ハングする場合、initを介して多くのイベントハンドラーが追加されるため、ページへの各リクエストが突然イベントハンドラーを数回起動することです

この動作により、サイトがすぐにダウンする可能性があります。

私はformsauthenticationやrolemanagermoduleなどのhttpmodulesに使用される「元の」.netコードを見てきました...しかし、私のコードはそれらのモジュールが使用するものと何ら変わりはありません。

私のコードは次のようになります。

public void Init(HttpApplication app)
{
    if (CommunityAuthenticationIntegration.IsEnabled)
    {
        FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];         

        formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
    }
}

.NETFrameworkのRo​​leManagerModuleでどのように実行されるかの例を次に示します。

public void Init(HttpApplication app)
{
    if (Roles.Enabled)
    {
        app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
        app.EndRequest += new EventHandler(this.OnLeave);
    }
}

誰かが何が起こっているのか知っていますか?

(私はただ誰かがこれが起こっている理由を教えてくれて、すべてが完全にうまくいくことを私に保証してくれることを願っています):)


アップデート:

私は問題を絞り込もうとしましたが、これまでのところ、呼び出されているinitメソッドは常にhttpモジュールの新しいオブジェクト上にあることがわかりました(以前考えていたのとは逆です)。

最初のリクエスト(サイトの起動時)では、作成されているすべてのHttpApplicationオブジェクトとそのモジュールがすべて最初のリクエストを処理しようとしているため、追加されているイベントハンドラーにヒットしているようです。なぜこれが起こっているのか本当に理解できません。

別のページをリクエストすると、作成されたすべてのHttpApplication(およびそれらのモジュール)が再度リクエストを処理しようとし、イベントハンドラーに複数回ヒットします。

しかし、最初のページ(または別のページ)に戻ると、1つのHttpApplicationのみが要求の処理を開始し、すべてが期待どおりに行われるようです-ブレークポイントでハングさせない限り。

ブレークポイントでハングさせると、新しいHttpApplicationのオブジェクトの作成が開始され、リクエストを処理/処理するためのHttpApplications(1つ以上)の追加が開始されます(現在、で停止しているHttpApplicationによって処理されています。ブレークポイント)。

負荷やエラーの分散と処理を支援するインテリジェントな「舞台裏」の方法である可能性があると思います。しかし、私には手がかりがありません。私はそこにいる人がそれが完全に素晴らしいこととそれがどうあるべきかを私に保証できることを願っていますか?

4

4 に答える 4

50

Init()メソッドが複数回呼び出されるのは正常です。アプリケーションが起動すると、ASP.NETワーカープロセスはHttpApplication必要と思われる数のオブジェクトをインスタンス化し、それらをプールします(たとえば、データベース接続プールと同様に、新しい要求に再利用します)。

これで、オブジェクトごとに、登録されている各HttpApplicationオブジェクトの1つのコピーがインスタンス化IHttpModuleされ、Initメソッドが何度も呼び出されます。したがって、5つHttpApplicationのオブジェクトが作成されると、5つのコピーがIHttpModule作成され、Initメソッドが5回呼び出されます。わかる?

では、なぜ5つHttpApplicationのオブジェクトをインスタンス化するのでしょうか。ASPXページには、ブラウザがダウンロードしようとする他のリソース、css、javascript、WebResource.aspx、おそらくどこかにあるiframeへのリンクがあるかもしれません。または、ASP.NETワーカープロセスが複数HttpApplicationのオブジェクトを開始する気分になっている可能性があります。これは、IIS(または組み込みのWebサーバー)で実行されているASP.NETプロセスの内部の詳細/最適化です。

一度だけ実行されることが保証されているコードが必要な場合(およびGlobal.asaxでApplication_StartUpイベントを使用したくない場合)、IHttpModuleで次のことを試すことができます。

private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();

public void Init(HttpApplication context)
{
    if (!HasAppStarted)
    {
        lock (_syncObject)
        {
            if (!HasAppStarted)
            {
                // Run application StartUp code here

                HasAppStarted = true;
            }
        }
    }
}

私は似たようなことをしました、そしてそれはうまくいくようです、しかし私が何かを逃した場合に備えて私の仕事の批評を歓迎します。

于 2010-03-10T11:45:37.680 に答える
8
  1. HttpContext.Current.Requestを調べて、モジュールのinitが起動されたリクエストを確認します。ブラウザが複数のリクエストを送信している可能性があります。

  2. IISに接続している場合は、IISログをチェックして、ブレークポイントに滞在している間に要求が受信されたかどうかを確認してください。

于 2009-07-17T02:43:15.917 に答える
3

ここでは、何を使用する必要があるか、いつ、どのように機能するかについて少し説明します。 Global.asaxでApplication_StartとInitをいつ使用するのですか?

編集:続きを読む

ASP列:HTTPモジュール

情報:ASP.NETのアプリケーションインスタンス、アプリケーションイベント、およびアプリケーションの状態

于 2009-07-17T01:18:08.720 に答える
1

上記の例では、すべてのリクエストに対してIHttpModuleをロックしてから、アプリケーション全体をフリーズします。IHttpModuleがリクエストを数回呼び出す場合は、HttpApplicationメソッドCompleteRequestを呼び出し、次のようにHttpApplicationのインスタンスを削除するために、EndRequestイベントでIHttpModuleのHttpApplicationインスタンスを破棄します。

public class TestModule :IHttpModule
    {
        #region IHttpModule Members

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
            context.EndRequest += new EventHandler(context_EndRequest);
        }

        void context_EndRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            app.CompleteRequest();
            app.Dispose();
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            //your code here
        }

        #endregion
    }

ポストバックで再リクエストせずに毎回IHttpModuleリクエストが必要な場合は、上記のコードを使用してください。

于 2010-03-16T08:05:50.153 に答える