2015-05-07 12 views
8

Nella mia app iOS, ho una funzione di ricerca che recupera i risultati da un server. Gli aggiornamenti di ricerca vengono pubblicati non appena l'utente aggiorna la query, pertanto in questo modo vengono eseguite più richieste in successione.iOS e Go - Keep-Alive con NSURLSession

Quindi la mia domanda è: come posso garantire che il TCP keep-alive venga utilizzato su queste connessioni? Mi piacerebbe ridurre il più possibile la latenza, quindi è importante mantenere una connessione dopo la prima richiesta e riutilizzarla per le seguenti richieste.

Sto utilizzando NSURLSession e ho sentito che utilizza keep-alive per impostazione predefinita, ma come posso saperlo con certezza? La registrazione delle richieste sul server non mostra alcuna differenza tra ogni richiesta successiva, ma non mi aspetto di vedere alcuna modifica solo dalle informazioni dell'intestazione.

Qualsiasi aiuto qui? Sto usando Go sul mio server, quindi è possibile che abbia bisogno di qualche configurazione aggiuntiva anche da quel lato.

risposta

6

Credo che tu stia confondendo TCP keep-alive con HTTP keep-alive (connessioni permanenti). Questi sono concetti non correlati. Dalla tua domanda, probabilmente intendi connessioni persistenti HTTP.

In HTTP/1.1, le connessioni permanenti sono l'impostazione predefinita e vengono utilizzate da NSURLSession e quasi tutti i client HTTP/1.1. Devi chiedere di spegnerli. È possibile cercare un Connection: close nell'intestazione HTTP o sul lato server, è possibile controllare il campo Close dello http.Request. Ma sono sicuro che stai ottenendo connessioni persistenti. Ciò significa che non è necessario rinegoziare il tunnel TLS (o almeno l'handshake a tre vie TCP) per ogni richiesta. (Anche se fai richieste parallele, ci saranno ancora più connessioni che devi negoziare. HTTP/1.1 può gestire solo una cosa alla volta, e NSURLSession proverà a utilizzare un pool di connessioni per migliorare i tempi di risposta.)

I keep-alive TCP sono una cosa completamente diversa. Invia un "ping" periodico all'altro lato per assicurarsi che sia ancora raggiungibile. Ci sono molti modi in cui puoi perdere la connettività di rete e non saperlo fino alla prossima volta che provi a comunicare, e il sintomo normale è che la connessione si blocca e devi temporizzarlo. In teoria il keep-alive TCP è solo lo strumento per scoprirlo, ma non l'ho quasi mai trovato pratico. È difficile da configurare correttamente (specialmente in Cocoa). È quasi sempre necessario creare una funzionalità di "ping" di livello superiore per l'applicazione anziché affidarsi a questo.

Ma per risolvere il problema, HTTP/1.1 è probabilmente perfetto per te, ma dovrai gestire attentamente le tue risposte. Se fai una nuova richiesta per ogni lettera e rispondi a una risposta massiccia, allora funzionerà male. Manterrai occupato tutto il pool di connessioni scaricando le cose che stai per gettare via. È necessario concentrarsi prima su buoni algoritmi. Come minimo, probabilmente si desidera inviare solo pochi risultati alla volta e fornire un approccio di "paging" nella propria API per chiedere ulteriori risultati per la stessa ricerca.

+0

Grazie per le informazioni utili. Ho apportato alcuni miglioramenti significativi all'algoritmo da quando è stata posta la domanda, soprattutto implementando un timer in modo che la ricerca invii una richiesta solo quando l'utente smette di digitare per un momento. Ma sono curioso dell'approccio "paging" che dici - potresti chiarire cosa intendi con questo? – hundley

+1

@hundley paging significa che se ci sono più di un certo numero di risultati, viene restituito solo il primo set, in seguito i batch vengono recuperati aggiungendo una variabile di richiesta con quale "pagina" si desidera. Pensa a come i risultati di Google arrivano in serie. Importa solo se il numero di risultati può essere grande, naturalmente. Il tuo "aspetta una pausa" è una tecnica molto comune e molto utile. –

6

Per sapere con certezza cosa sta facendo TCP, è possibile abilitare CFNETWORK_DIAGNOSTICS. Dai documenti:

Durante lo sviluppo normale è possibile impostare questa variabile di ambiente tramite l'editor di schemi Xcode. Se hai bisogno di investigare problemi al di fuori di Xcode, puoi impostarlo a livello di programmazione usando il codice mostrato nel Listato 1.

listato 1 a livello di programmazione che consente la registrazione diagnostica CFNetwork

setenv("CFNETWORK_DIAGNOSTICS", "3", 1); 

Si dovrebbe fare questo proprio all'inizio della sequenza di lancio della app. Normalmente, inserire questo all'inizio del main è sufficiente, ma se si dispone di inizializzatori statici C++ che utilizzano CFNetwork, è necessario eseguirlo prima di essi.

CFNetwork registrazione diagnostica si avvia quando si utilizza prima CFNetwork, o qualsiasi quadro, come Fondazione, che utilizza CFNetwork-a quel punto stamperà un messaggio come quello mostrato nel Listato 2.

elenco 2 Un esempio di la registrazione diagnostica messaggio di avvio CFNetwork

2014-10-28 14:23:37.115 QTestbed[2626:60b] CFNetwork diagnostics log file created at: /private/var/mobile/Applications/76531F40-3291-4565-8C75-0438052C83BC/Library/Logs/CrashReporter/CFNetwork_com.example.apple-samplecode.QTestbed_2626.nwlrb 
Problemi correlati