Guidato dall'insostituibile Reflector del buon Roeder, e grazie ad un po' di tempo disponibile, stamane ho deciso di "ficcare il naso" nella versione 2.0 della HttpPipeline di ASP.NET.

Come ovvio, di modifiche ce ne sono, ma vi anticipo una chicca che ho scoperto esaminando il meccanismo di accodamento delle richieste del runtime; Vediamo il seguente codice estratto dal reflector:

...
HttpRequestPriority priority1 = RequestQueue.GetRequestPriority(wr);

if ((priority1 != HttpRequestPriority.Critical) && (this._count >= this._queueLimit))
{
   HttpRuntime.RejectRequestNow(wr, false);
   return null;
}
this.QueueRequest(wr, flag1, (priority1 > HttpRequestPriority.Normal));
...

Siamo nella classe che governa l'accodamento delle richieste, e nella prima riga si legge la priorità della richiesta; Nel blocco "if", sostanzialmente si dice questo: se il limite di richieste accodabili è stato raggiunto e la priorità non è "critical" allora scarta la richiesta;

Questa di per se è già una novità, dato che nei framework precedenti una richiesta non godeva di una priorità. Il valore di HttpRequestPriority viene letto dal nodo system.web/httpRuntime del web.config. Se andate nella documentazione della beta1 e guardate tra gli attributi documentati vedrete che requestPriority semplicemente non esiste. Questo però sembra essere un errore della documentazione, perchè se invece leggete l'overview della classe HttpRuntimeSection (il wrapper dell'omonima sezione sezione del web.config) l'attributo esiste.

Non del tutto appagato della scoperta, ho deciso di spulciare il metodo QueueRequest, che tra i vari parametri accetta due boolean, "isLocal" e "isHighPri". Ecco il sorgente del metodo:

private void QueueRequest(HttpWorkerRequest wr, bool isLocal, bool isHighPri)
{
      RequestQueue queue1 = this;
      lock (queue1)
      {
            if (isLocal)
            {
                  this._localQueue.Enqueue(wr);
            }
            else if (isHighPri)
            {
                  this._highPriQueue.Enqueue(wr);
            }
            else
            {
                  this._externQueue.Enqueue(wr);
            }
            this._count += 1;
      }

      ...omissis...
}

Notate nulla di strano? Io credo di sì. La RequestQueue non è una, ma sono trè!

"Egli è uno e trino" potrei dire se fossi cattolico...

C'è una coda per le richieste locali, una per quelle esterne e una per quelle "critiche". Il fw considera locali le richieste provenienti da 127.0.0.1 (poteva essere diversamente) ed esterne tutte le altre.

La caratteristica delle richieste critiche è di essere accodate sempre (occhio, ho detto accodate, non eseguite), anche quando il limite massimo del workerprocess è stato raggiunto. Come si legge in un trafiletto della documentazione, questa caratteristica è stata aggiunta per poter avere delle pagine "ad accesso amministrativo" che consentano di effettuare manutenzioni anche in condizioni di altissimo carico del sistema. L'esatta dicitura è: "to change security properties on a portal site or to cancel long-running business-logic"

Un'ultima curiosità: Guardando nel metodo DequeueRequest() che ha l'incarico di estrarre una richiesta da una delle tre code, per mandarla in esecuzione la prima coda ed essere valutata è la local e non la critica come si sarebbe portati a pensare;

Morale? Se dovete fare una manutenzione su un server "sotto pressione" scendete nel datacenter e sedetevi davanti al server; Avrete molte più possibilità che questo vi ascolti... ;-)

Ok, passatemi la lanterna e fatemi largo; la buia tana del coniglio mi attende.

tags: - categories:

Aggiungi Commento