2013-09-02 29 views
7

Sto implementando un'app che esegue molte chiamate di rete verso un sistema di riposizionamento controllato da noi. Recentemente abbiamo deciso di introdurre le intestazioni di cache sul lato server per salvare alcune preziose reti e tempo del server. Dato che non sappiamo in anticipo per quanto tempo i dati saranno validi, non stiamo inviando intestazioni Cache-control: max-age o Expires, tutto ciò che facciamo è inviare un'intestazione Last-Modified insieme a un E-tag, quindi colpiamo sempre il server ma le risposte sono piuttosto veloci la maggior parte di i tempi con un 304. All'inizio sembrava tutto a posto, con molte richieste in cache. Tuttavia, si verificano alcuni errori di dati casuali sull'app a causa della memorizzazione nella cache.NSURLCache che memorizza nella cache le risposte casuali che non devono essere memorizzate nella cache

Per qualche motivo non riesco a capire, a alcune richieste punto vengono localmente nella cache e utilizzati come dati "aggiornati", senza colpire il server, quando in realtà non lo sono. Il problema rimane lì fino a quando passa un po 'di tempo. Quindi tutto torna normalmente al server, esattamente come si comporterebbe con un'intestazione cache-control, ma senza di essa !. Quindi, la mia domanda è:


Come può NSURLCache insieme NSURLConnection decidere che una determinata richiesta non ha bisogno di andare online quando la richiesta originale non è venuto con Cache-control: max-age o Expires intestazioni? Qualcuno ha avuto effetti simili? E come posso risolverlo senza rimuovere l'intera cache?


Alcuni più di fondo informazioni:

  • Sto usando AFNetworking, ma si basa su NSURLConnection quindi non pensano cambia nulla
  • La cache utilizzata è l'impostazione predefinita [NSURLCache sharedURLCache] esempio
  • È una richiesta GET e quando controllo le intestazioni dalla risposta memorizzata nella cache questo è ciò che ottengo:

    po [response allHeaderFields]

    "Access-Control-Allow-Headers" = "Content-Type"; 
    "Access-Control-Allow-Methods" = "GET, POST, DELETE, PUT"; 
    "Access-Control-Allow-Origin" = "*"; 
    Connection = "keep-alive"; 
    "Content-Encoding" = gzip; 
    "Content-Length" = 522; 
    "Content-Type" = "application/json"; 
    Date = "Mon, 02 Sep 2013 08:00:38 GMT"; 
    Etag = "\"044ad6e73ccd45b37adbe1b766e6cd50c\""; 
    "Last-Modified" = "Sat, 31 Aug 2013 10:36:06 GMT"; 
    Server = "nginx/1.2.1"; 
    "Set-Cookie" = "JSESSIONID=893A59B6FEFA51566023C14E3B50EE1E; Path=/rest-api/; HttpOnly"; 
    
  • Non posso prevedere o riprodurre quando l'errore sta per accadere così soluzioni che si basano sulla cancellazione della cache non sono un'opzione.

  • Sto usando iOS5 +
+0

No possibilità che ci sia un problema di sincronizzazione dell'orologio tra il dispositivo e il server? Le specifiche dicono che il comportamento del client non è definito in quel caso (fino al cliente per fare ciò che è appropriato). Hai anche provato a utilizzare un codice di rete per ottenere ulteriori informazioni? – Alex

+0

il problema del tempo è stato il mio primo pensiero ma non sono riuscito a trovare uno scenario ripetibile (accade in modo casuale). Comunque, è successo sui dispositivi con tempo e lato server corretti, quindi non sembra essere così :(grazie per il suggerimento! –

risposta

2

Secondo la dichiarazione "ad alcune richieste punto vengono localmente nella cache e utilizzati come 'aggiornati' i dati senza colpire il server" Sono abbastanza sicuro che le vostre richieste sono la memoria cache.

NSURLCache memorizza nella cache i dati. non su disco. Quindi lascia che ti spieghi cosa potrebbe accadere con te.

Si avvia l'app. Effettua una chiamata di servizio Web recupera i dati dal server si effettua nuovamente una chiamata e recupera la risposta dalla memoria senza effettuare una chiamata al server e visualizza il risultato.

Si lascia l'app per qualche volta o si riavvia l'app. Controlla se i dati sono in memoria.Se non è disponibile, effettua nuovamente una chiamata al server e ripete lo stesso comportamento.

Si consiglia di scrivere il proprio caching del disco per lo stesso invece di fare affidamento su NSURLConnection e NSUrlCache. perché alcune delle politiche di caching non sono ancora state implementate da Apple.

+0

Grazie Vailbhav. Come ho detto, in realtà è un problema con la cache, ma è non che qualcosa non sia memorizzato nella cache, ma il contrario: qualcosa che non dovrebbe essere memorizzato nella cache viene memorizzato nella cache.Inoltre, viene salvato su disco, ma è previsto perché su iOS5 la cache neurale viene salvata su disco. –

4

Come può NSURLCache insieme NSURLConnection decidono che una particolare richiesta non ha bisogno di andare online quando ...

Sezione 13.2 di RFC 2616 dice:

Dal server di origine fanno non sempre forniscono tempi di scadenza espliciti, Le cache HTTP tipicamente assegnano tempi di scadenza euristici, impiegando algoritmi che utilizzano altri valori di intestazione (come il Last-M odificato tempo) per stimare un tempo di scadenza plausibile. La specifica HTTP/1.1 non fornisce algoritmi specifici, ma impone i vincoli del caso peggiore ai loro risultati. Poiché la scadenza euristica potrebbe compromettere la trasparenza semantica, è necessario utilizzare con cautela lo e incoraggiamo i server di origine a fornire il più possibile i tempi di scadenza espliciti di .

Quindi, è possibile che il sistema di caricamento degli URL decida che i dati memorizzati nella cache sono "abbastanza recenti" anche se non è stata fornita una durata specifica per i dati.

Per risultati ottimali, è necessario provare a fornire una durata specifica nelle intestazioni di risposta. Se aggiungere un'intestazione di questo tipo è impossibile, potresti invece modificare la richiesta. if-modified-since o cache-control potrebbero aiutare a evitare i dati memorizzati nella cache.

+1

Questa è la migliore risposta finora. Non risolve il problema, ma almeno il paragrafo sul tipo di RFC 2616 spiega cosa sto vivendo. Grazie! –

2

si prega di fare in modo che la vostra politica di cache NSURLRequest è impostato su NSURLRequestReturnCacheDataElseLoad

qui se si utilizza AFNetworking in AFHTTPClient.m è possibile ignorare il metodo

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method 
            path:(NSString *)path 
          parameters:(NSDictionary *)parameters 

sostituire la linea 470 con questo

quello che stai facendo è dire la richiesta di caricare la cache se il server non viene aggiornato .. se il server viene aggiornato allora ignorerà la cache e scaricare il contenuto dai server

FYI: memorizza i dati in NSURLCache memory..if si desidera archiviare i dati nel disco è possibile utilizzare la mia classe qui

https://github.com/shoeb01717/Disc-Cache-iOS

+0

Grazie, ma come spiegato, il problema non è che l'informazione non è stata cambiata, ma totalmente l'opposto: si nasconde quando non dovrebbe. Oltre alle cache iOS5 su disco, l'implementazione della mia classe probabilmente non sarà di grande aiuto, anche se proverò. –

+1

@shoeb: FYI, dato che ios5 NSURLCACHE consente di scegliere il disco o la memoria e di allocare anche le dimensioni. – Alex

+0

Grazie sapevo delle funzionalità di iOS5, ma la classe che ho creato ti permetterà anche di restituire la cache dal bundle principale dell'app .. –

Problemi correlati