El método de inicio HttpModule se llama varias veces - ¿por qué?


Estaba creando un módulo http y mientras depuraba noté algo que al principio (al menos) parecía un comportamiento extraño.

Cuando establezco un punto de interrupción en el método init del httpmodule puedo ver que el método init del módulo http está siendo llamado varias veces a pesar de que solo he iniciado el sitio web para la depuración y realizado una sola solicitud (a veces se golpea solo 1 vez, otras veces hasta 10 veces).

Sé que debo esperar varios casos de la HttpApplication que se está ejecutando y para cada uno se crearán los módulos http, pero cuando solicito una sola página, debe ser manejada por un solo objeto de aplicación http y, por lo tanto, solo dispara los eventos asociados una vez, pero aún así dispara los eventos varias veces para cada solicitud, lo que no tiene sentido, aparte de que debe haber sido agregado varias veces dentro de esa HttpApplication, lo que significa que es el mismo método de inicio httpmodule que se está llamando cada vez y no una nueva aplicación http se crea cada vez que llega a mi punto de interrupción(ver mi ejemplo de código en la parte inferior, etc.).

¿Qué podría estar yendo mal aquí ? ¿es porque estoy depurando y estableciendo un punto de interrupción en el módulo http?

Se ha dado cuenta de que parece que si arranco el sitio web para la depuración y paso rápidamente sobre el punto de interrupción en el httpmodule solo golpeará el método init una vez y lo mismo ocurre con el eventhandler. Si en cambio lo dejo colgar en el punto de interrupción durante unos segundos el método init está siendo llamado varias veces (parece que depende de cuánto tiempo espere antes de pasar por encima del punto de interrupción). Tal vez esto podría ser alguna función de compilación para asegurarse de que el httpmodule se inicializa y la aplicación http puede servir solicitudes , pero también parece algo que podría tener consecuencias catastróficas.

Esto podría parecer lógico, ya que podría estar tratando de terminar la solicitud y ya que he establecido el punto de interrupción que piensa que algo ha ido mal y tratar de llamar ¿el método init otra vez ? soo puede manejar la solicitud ?

Pero ¿es esto lo que está sucediendo y está todo bien (solo estoy adivinando), o es un problema real ?

Lo que me preocupa especialmente es que si algo lo hace colgar en el servidor "production/live" durante unos segundos, se agregan muchos controladores de eventos a través del init y, por lo tanto, cada solicitud a la página dispara repentinamente el eventhandler varias veces.

Este comportamiento podría traer rápidamente cualquier sitio abajo.

He mirado el código.net "original" usado para los httpmodules para formsauthentication y el rolemanagermodule, etc. pero mi código no es diferente al que usan esos módulos.

Mi código se ve así.

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

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

Aquí hay un ejemplo de cómo se hace en el RoleManagerModule desde. NET framework

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

¿Alguien sabe lo que está pasando?

(solo espero que alguien por ahí pueda decirme por qué está sucediendo esto y me asegure que todo está perfectamente bien) :)


ACTUALIZACIÓN:

He intentado reducir el problema y hasta ahora he encontrado que el método Init que se llama siempre está en un nuevo objeto de mi módulo http (contrario a lo que pensaba antes).

Parece que para la primera solicitud (al iniciar el sitio) todos los objetos HttpApplication que se están creando y sus módulos están tratando de servir a la primera solicitud y, por lo tanto, todos golpean el eventhandler que se está agregando. Yo no figura por qué está pasando esto.

Si solicito otra página todos los HttpApplication creados (y su moduless) intentarán de nuevo servir la petición causando que golpee el eventhandler varias veces.

Pero también parece que si luego salto de nuevo a la primera página (u otra) solo una aplicación HttpApplication comenzará a hacerse cargo de la solicitud y todo es como se esperaba, siempre y cuando no deje que se cuelgue en un punto de interrupción.

Si lo dejo colgar en un punto de interrupción, comienza a cree nuevos objetos HttpApplication y comience a agregar HttpApplications (más de 1) para servir/manejar la solicitud (que ya está en proceso de ser servida por la HttpApplication que actualmente está detenida en el punto de interrupción).

Supongo o espero que pueda ser una forma inteligente "detrás de escena" de ayudar a distribuir y manejar la carga y / o los errores. Pero no tengo ni idea. Espero que algunos por ahí me puedan asegurar que está perfectamente bien y cómo se supone que debe ser?

Author: MartinF, 2009-07-17

4 answers

  1. Inspeccionar el HttpContext.Actual.Request to see, para qué solicitud se dispara el inicio del módulo. Podría ser el navegador enviando múltiples solicitudes.

  2. Si está conectado a IIS, compruebe los registros de IIS para saber si se recibe alguna solicitud para el tiempo que se queda en el punto de interrupción.

 7
Author: Ramesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-17 02:43:15

Es normal que el método Init() sea llamado varias veces. Cuando se inicia una aplicación, el ASP.NET Worker process instanciará tantos objetos HttpApplication como crea que necesita, luego los agrupará (p. ej. vuelva a usarlos para nuevas solicitudes, similar a la agrupación de conexiones de base de datos).

Ahora para cada objeto HttpApplication, también instanciará una copia de cada IHttpModule que esté registrado y llamará al método Init muchas veces. Así que si 5 objetos HttpApplication son creado, se crearán 5 copias de su IHttpModule, y su método Init llamado 5 veces. Sentido?

Ahora, ¿por qué está instanciando 5 objetos HttpApplications dicen? Bueno, tal vez su página ASPX tiene enlaces a otros recursos que su navegador intentará descargar, css, javascript, WebResource.aspx, tal vez un iframe en alguna parte. O tal vez el ASP.NET Worker Process 'está en el estado de ánimo' para iniciar más de 1 objeto HttpApplication, que es realmente un detalle interno / optimización de la ASP.NET proceso que se ejecuta bajo IIS(o el servidor web integrado en VS).

Si desea que el código se ejecute una sola vez (y no desea utilizar el evento Application_StartUp en el Global.asax), puedes probar lo siguiente en tu módulo IHTTP:

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;
            }
        }
    }
}

He hecho algo similar y parece funcionar, aunque daría la bienvenida a las críticas de mi trabajo en caso de que me haya perdido algo.

 42
Author: Sunday Ironfoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-10 11:45:37
 2
Author: Greg Ogle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:32:26

El examen anterior bloquea el módulo IHTTP para todas las solicitudes, y luego, congela toda la aplicación. Si su solicitud de llamadas IHttpModule varias veces es necesaria para llamar al método HttpApplication CompleteRequest y eliminar la instancia HttpApplication del evento IHttpModule en EndRequest para eliminar la instancia de la HttpApplication de esta manera:

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
    }

Si necesita que las solicitudes de IHttpModule cada vez sin rerequest en postback utilice este código anterior.

 1
Author: kinki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-16 12:27:12