2015-05-19 24 views
12

Ho un sito Web MVC asp.net che sta consumando una pausa API per ricevere i suoi dati. Sto utilizzando attività asincrone per eseguire le richieste in quanto possono esserci molte in ogni pagina. Dopo un po 'di tempo di attività, il sito Web ha generato il seguente errore durante il tentativo di ricezione dei dati.Errore nel chiamare HttpClient.GetAsync: La connessione sottostante è stata chiusa

La connessione sottostante è stata chiusa: si è verificato un errore imprevisto in una trasmissione.

Ho letto che questo potrebbe essere dovuto alle impostazioni maxconnection sul web.config ma aumentando questo non sembra fare molta differenza.

Sto anche utilizzando la memorizzazione nella cache per ridurre il carico sull'api. L'attività viene memorizzata nella cache in modo che il risultato possa essere utilizzato in seguito.

L'unico modo che ho trovato per risolvere questo problema è riciclando il pool di applicazioni. Qualsiasi aiuto sarebbe apprezzato.

/* Code from page_load */ 

var currenciesTask = ApiClient.GetAsync<CurrencyListWrapper>("currencies"); 
var blogArticleTask = ApiClient.GetAsync<BlogArticleListWrapper>("blog/articles", "limit=10"); 
var seoPageTask = ApiClient.GetAsync<SEOPageListWrapper>("seopages"); 

await Task.WhenAll(currenciesTask, blogArticleTask, seoPageTask); 


/* Code from data access later */ 

public class ApiClient : HttpClient 
{ 
    public static Task<T> GetAsync<T>(string operation, string query = null, bool cache = true) 
    { 
    // Check if task is in cache 
    string cacheName = null; 

    if (cache) 
    { 
     cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage()); 

     var cachedTask = HttpRuntime.Cache[cacheName]; 

     if (cachedTask != null) 
     { 
     return (Task<T>)cachedTask; 
     } 

    } 

    // Get data task 
    var task = GetAsyncData<T>(operation, query); 

    // Add to cache if required 
    if (task != null && cache) 
    { 
     App.AddToCache(cacheName, task); 
    } 

    return task; 
    } 

    public static async Task<T> GetAsyncData<T>(string operation, string query = null) 
    { 
    using (ApiClient client = new ApiClient()) 
    { 
     string url; 

     if (query != null) 
     { 
     url = String.Format("{0}?{1}", operation, query); 
     } 
     else 
     { 
     url = String.Format("{0}", operation); 
     } 

     var response = await client.GetAsync(url); 

     return (await response.Content.ReadAsAsync<T>()); 
    } 
    } 
} 
+0

Questo errore sembra provenire da IIS. Il più delle volte questo è qualcosa di specifico che incasina il Protocollo. Le cause possono essere correlate a SSL o Compatibilità con il framework ... ** domande di coppia **: ** 1) ** stai usando SSL? ** 2) ** Quale versione di .Net utilizza il pool di app in IIS? –

+0

Grazie per la risposta. Sì, stiamo usando SSL sul sito web e sul servizio web a cui si sta connettendo. Il pool di applicazioni sta usando .Net v4.0.30319. – markvpc

+0

Controllare il certificato, la registrazione cert con IIS, controllare i collegamenti. Se tutto sembra a posto, potresti persino provare a rimuovere e registrare nuovamente il certificato. Sospetto che sia confuso dal protocollo. i problemi del protocollo causano eccessive strette di mano e portano a thread di richieste zombie. –

risposta

3

Questo è sbagliato,

Il compito viene memorizzato nella cache in modo che il risultato può essere utilizzato in seguito.

Si suppone che si memorizzi nella cache il risultato, non l'attività. Alla fine della prima esecuzione, il tuo HttpClient viene chiuso e quando si tenta di recuperare l'attività memorizzata nella cache, non funzionerà.

public class ApiClient : HttpClient 
{ 
    public static async Task<T> GetAsync<T>(string operation, string query = null, bool cache = true) 
    { 
    // Check if task is in cache 
    string cacheName = null; 

    if (cache) 
    { 
     cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage()); 

     T cachedResult = (T)HttpRuntime.Cache[cacheName]; 

     if (cachedResult!= null) 
     { 
     return Task.FromResult(cachedResult); 
     } 

    } 

    // Get data task 
    var result = await GetAsyncData<T>(operation, query); 

    // Add to cache if required 
    if (result != null && cache) 
    { 
     App.AddToCache(cacheName, result); 
    } 

    return result; 
    } 

    public static async Task<T> GetAsyncData<T>(string operation, string query = null) 
    { 
    using (ApiClient client = new ApiClient()) 
    { 
     string url; 

     if (query != null) 
     { 
     url = String.Format("{0}?{1}", operation, query); 
     } 
     else 
     { 
     url = String.Format("{0}", operation); 
     } 

     var response = await client.GetAsync(url); 

     return (await response.Content.ReadAsAsync<T>()); 
    } 
    } 
} 
+0

Grazie, ci proverò. C'è una riga che ho dovuto correggere per farlo funzionare. return attende Task.FromResult (cachedResult); – markvpc

0

Akash potrebbe avere ragione. Ma sembra più o meno un problema di connessione con il pool di applicazioni. Imposta il limite di connessione 0 per renderlo illimitato nel pool di applicazioni. Avere un blocco finally in voi codice e

gc.collect(); 

metodo di raccolta dei rifiuti di essere chiamati a rimuovere le connessioni inutilizzate per far spazio a altro collegamento.

+0

Grazie, il limite di connessione sul pool di applicazioni è già impostato su 0. Esaminerò la garbage collection. – markvpc

Problemi correlati