2009-08-18 10 views
5

Quando si effettua una richiesta HttpWeb all'interno di una stored procedure CLR (come indicato nel seguente codice), la prima chiamata dopo il server Sql viene (ri) avviata o dopo un determinato (ma indeterminato) periodo di il tempo attende per un certo periodo di tempo sulla chiamata al metodo GetResponse().HttpWebRequest viene eseguito lentamente la prima volta all'interno di SQLCLR

C'è un modo per risolvere questo problema che non implica un "hack" come avere un lavoro di SQL Server Agent eseguito ogni pochi minuti per provare e assicurare che la prima chiamata "lenta" sia fatta dall'agente e non codice di produzione "reale"?

function SqlString MakeWebRequest(string address, string parameters, int connectTO) 
{ 
    SqlString returnData; 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Concat(address.ToString(), "?", parameters.ToString())); 
    request.Timeout = (int)connectTO; 
    request.Method = "GET"; 
    using (WebResponse response = request.GetResponse()) 
    { 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     using (StreamReader reader = new StreamReader(responseStream)) 
     { 
     SqlString responseFromServer = reader.ReadToEnd(); 
     returnData = responseFromServer; 
     } 
    } 
    } 
    response.Close(); 

    return returnData; 
} 

(gestione degli errori e altro codice non critico ben rimosso per brevità)


Vedi anche this Sql Server forums thread.

+0

Quanto dura questa prima chiamata tempo di attesa rispetto al 2 ° + orario di chiamata? Di solito è questa chiamata allo stesso URI? – BigBlondeViking

+0

Credo (in cima alla mia testa) '30 secondi, e la chiamata è fatta per un URL che è un indirizzo IP, quindi non credo che il DNS sarebbe un problema :( – Rob

+0

Hai pensato di guardare il Traffico HTTP con qualcosa come WireShark? O è stato escluso tutto sul filo. –

risposta

10

Questo era un problema per me usando HttpWebRequest in un primo momento. È dovuto alla classe alla ricerca di un proxy da utilizzare. Se si imposta il valore dell'oggetto su null/Nothing, verrà eseguito il zip lungo il percorso.

+0

Questo sembra essere stato la causa della * maggior parte * della (molto) durata della chiamata iniziale. Ma c'è ancora (forse) una piccola differenza rimanente. Qualche idea su cos'altro potrebbe rendere le chiamate iniziali più lente (quando usi 'HttpWebRequest')? –

0

C'è sempre un ritardo la prima volta che SQLCLR carica i gruppi necessari. Questo dovrebbe essere il caso non solo per la funzione MakeWebRequest, ma anche per qualsiasi funzione .NET nello SQLCLR.

+0

Purtroppo questo non è il problema qui, o non sembra esserlo, poiché qualsiasi altra funzione nel nostro CLR Assembly può essere chiamata ed eseguita, ma la prima volta che questa viene chiamata blocca su "request.GetResponse()" – Rob

0

HttpWebRequest fa parte dell'assembly System.Net, che non fa parte di supported libraries. Consiglierei di utilizzare la libreria System.Web.Services per effettuare chiamate di servizi Web dall'interno di SQLCLR.

+0

Ancora, non il problema. Stiamo utilizzando altre parti di System.Net senza alcun problema. "Supportato" o altrimenti è irrilevante nel contesto di questa domanda. Inoltre, System.Web.Services è per * creare * servizi web, non caricare pagine web/chiamare servizi Web. – Rob

1

Non è sicuro, ma se il ritardo è sufficiente per consentire le ricerche DNS iniziali potrebbe essere il colpevole? (quanto tempo è il ritardo versi una normale chiamata?)

e/o

è l'URI interno alla rete/o di una rete interna diversa?

ho visto alcuni ritardi di rete strani da utilizzando i profili di bilanciamento del carico all'interno di una rete che non è giusto setup, i firewall, bilanciatori di carico-, e di altri profili di rete potrebbe essere "combattere" le connessioni iniziali ...

io non sono un bravo ragazzo di networking, ma si potrebbe desiderare di vedere ciò che una SA ha da dire su questo su serverfault.com così ...

buona fortuna

0

ho testato e il mio primo freddo eseguire (dopo il riavvio del servizio SQL) era in 3 secondi (non 30 come il tuo), tutti gli altri sono in 0 secondi.

L'esempio di codice che ho usato per generare una DLL:

using System; 
using System.Data; 
using System.Net; 
using System.IO; 
using System.Data.SqlClient; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 

namespace MySQLCLR 
{ 
    public static class WebRequests 
    { 
     public static void MakeWebRequest(string address, string parameters, int connectTO) 
     { 
      string returnData; 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Concat(address.ToString(), "?", parameters.ToString())); 
      request.Timeout = (int)connectTO; 
      request.Method = "GET"; 
      using (WebResponse response = request.GetResponse()) 
      { 
       using (Stream responseStream = response.GetResponseStream()) 
       { 
        using (StreamReader reader = new StreamReader(responseStream)) 
        { 
         returnData = reader.ReadToEnd(); 
         reader.Close(); 
        } 
        responseStream.Close(); 
       } 
       response.Close(); 
      } 
      SqlDataRecord rec = new SqlDataRecord(new SqlMetaData[] { new SqlMetaData("response", SqlDbType.NVarChar, 10000000) }); 
      rec.SetValue(0, returnData); 
      SqlContext.Pipe.Send(rec); 
     } 
    } 
} 
+0

Ho appena confermato con il mio collega che il ritardo è di circa 15 secondi, non il 30 che pensavo fosse e questo si verifica dopo il riavvio di Sql Server o un certo periodo di inattività che dobbiamo ancora identificare (cioè durante la notte) – Rob

+0

Quindi il problema si trova altrove, semplicemente non abbiamo un ambiente per riprodurlo. Pensi che 3s per la partenza a freddo siano inaccettabili? –

4

Mi sembra come la verifica della firma del codice. Le DLL di sistema spedite da MS sono tutte firmate e SQL verifica le firme al momento del caricamento. Apparentemente l'elenco di revoche di certificati è scaduto e il motore di verifica certificato scade recuperando un nuovo elenco. Ho scritto un messaggio su questo problema prima del Fix slow application startup due to code sign validation e il problema è descritto anche in questo articolo di Technet: Certificate Revocation and Status Checking.

La soluzione è piuttosto arcano e comporta la modifica del Registro del tasto: HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CertDllCreateCertificateChainEngine\Config:

  • ChainUrlRetrievalTimeoutMilliseconds Questo è ogni singolo timeout CRL di controllo delle chiamate. Se è 0 o non è presente, viene utilizzato il valore predefinito di 15 secondi. Cambia questo timeout a un valore ragionevole come 200 millisecondi.
  • ChainRevAccumulativeUrlRetrievalTimeoutMilliseconds Questo è il timeout di recupero CRL aggregato. Se impostato su 0 o non presente, viene utilizzato il valore predefinito di 20 secondi. Cambia questo timeout a un valore come 500 millisecondi.

C'è anche una soluzione più specifica per Microsoft signed assemblies (questo è dalla documentazione Biztalk, ma si applica a qualsiasi carico di montaggio):

caricare manualmente Microsoft Certificate revoca elenca

Quando si avvia un'applicazione .NET, il framework .NET tenta di scaricare l'elenco di revoche di certificati (CRL) per qualsiasi firma come blaggio. Se il tuo sistema non ha accesso diretto a a Internet, o è limitato all'accesso al dominio Microsoft.com , questo potrebbe ritardare l'avvio di BizTalk Server . Per evitare questo ritardo all'avvio dell'applicazione, è possibile eseguire i passaggi seguenti per scaricare e installare manualmente il codice nella lista di revoche di certificati sul proprio sistema.

  1. scaricare gli ultimi aggiornamenti da CRL http://crl.microsoft.com/pki/crl/products/CodeSignPCA.crl e http://crl.microsoft.com/pki/crl/products/CodeSignPCA2.crl.
  2. Spostare i file CodeSignPCA.crl e CodeSignPCA2.crl nel sistema isolato .
  3. Dal prompt dei comandi, immettere il seguente comando per utilizzare l'certutil utility per aggiornare l'archivio certificati locale con il CRL scaricato al punto 1: certutil -addstore CA c: \ CodeSignPCA.crl

I file CRL vengono aggiornati regolarmente, , quindi è necessario prendere in considerazione l'impostazione di un'attività di download che si sta scaricando e installazione degli aggiornamenti CRL. Per visualizzare l'ora dell'aggiornamento successivo, fare doppio clic sul file .crl e visualizzare il valore del campo Aggiornamento successivo .

+0

Ovviamente è un po 'insolito che il server che effettua le chiamate al servizio web non riesca ad accedere al server CRL in modo che possa essere disattivato, ma i sintomi sembrano molto simili al controllo CRL. –

+0

Questo è molto utile sapere. Ho riscontrato il problema del timeout del CRL in un altro formato (codice C# .NET che carica le immagini TIFF fa una richiesta CRL che va in time-out perché i PC non sono collegati a Internet, causando il carico dell'immagine a 30 secondi). La modifica del registro è un po 'dubbia, ma caricare il CRL manualmente sembra essere una soluzione ragionevole. – Conceptdev

+0

@Craig: Sì, in pratica qualsiasi creazione di appdomain può colpire questo ed è quasi impossibile da diagnosticare a meno che tu non ne sia a conoscenza. Primo colpo su un sito web ASP, prima chiamata in una DLL, l'applicazione si blocca per 30 secondi al caricamento, tutti i sintomi dello stesso problema. –

Problemi correlati