Moderne Websites sind komplex und müssen Daten oft asynchron im Hintergrund laden. JSON-Streaming ist eine Möglichkeit, das umzusetzen.
Was ist JSON-Streaming?
JSON-Streaming, kurz JSONS, ist eine einfache Technik, mit der wir die Suchlatenz für Nutzer reduzieren, besonders bei langsamen Verbindungen. Den größten Nutzen sehen mobile Nutzer mit HTTPS-Verbindungen, aber eigentlich profitieren alle. Für JSONS brauchen Sie keine komplizierten JSON-Parser. Senden Sie einfach JSON-Datensätze, die durch Zeilenumbrüche getrennt sind. Die Streaming-API von Twitter funktioniert seit Jahren so.
Warum Sie einen JSON-Stream nutzen sollten
Unser Prüfer für Benutzernamen in sozialen Netzwerken zeigt das Prinzip einfach. Er prüft per HTTP-HEAD-Anfrage bei Facebook, Twitter und Pinterest, ob der gesuchte Name verfügbar ist. Die Ergebnisse treffen in zufälliger Reihenfolge ein, und wir möchten sie möglichst schnell anzeigen. Wir könnten drei HTTPS-Anfragen senden, doch das bedeutet drei TCP-Verbindungen, drei SSL-Handshakes und so weiter. Wir vermeiden das und können vermutlich eine bestehende HTTPS-Verbindung wiederverwenden, wenn wir nur eine Anfrage senden:
https://instantdomainsearch.com/services/vanity/apple?hash=866016287
Die Streaming-Antwort ähnelt dem HTTP-Verfahren Chunked Transfer Encoding und baut darauf auf. Am besten sehen Sie die Funktionsweise, wenn Sie die Verbindung mit curl verfolgen:
curl --trace - "https://instantdomainsearch.com/services/vanity/apple?hash=866016287"
…
<= Recv data, 45 bytes (0x2d)
0000: 32 37 0d 0a 7b 22 54 79 70 65 22 3a 22 54 77 69 27..{"Type":"Twi
0010: 74 74 65 72 22 2c 22 49 73 52 65 67 69 73 74 65 tter","IsRegiste
0020: 72 65 64 22 3a 74 72 75 65 7d 0a 0d 0a red":true}...
{"Type":"Twitter","IsRegistered":true}
<= Recv data, 46 bytes (0x2e)
0000: 32 38 0d 0a 7b 22 54 79 70 65 22 3a 22 46 61 63 28..{"Type":"Fac
0010: 65 62 6f 6f 6b 22 2c 22 49 73 52 65 67 69 73 74 ebook","IsRegist
0020: 65 72 65 64 22 3a 74 72 75 65 7d 0a 0d 0a ered":true}...
{"Type":"Facebook","IsRegistered":true}
<= Recv data, 52 bytes (0x34)
0000: 32 39 0d 0a 7b 22 54 79 70 65 22 3a 22 50 69 6e 29..{"Type":"Pin
0010: 74 65 72 65 73 74 22 2c 22 49 73 52 65 67 69 73 terest","IsRegis
0020: 74 65 72 65 64 22 3a 74 72 75 65 7d 0a 0d 0a 30 tered":true}...0
0030: 0d 0a 0d 0a ....
{"Type":"Pinterest","IsRegistered":true}
== Info: Curl_http_done: called premature == 0
== Info: Connection #0 to host instantdomainsearch.com left intact
Vielleicht begegnen Ihnen dogmatische Aussagen, nach denen jeder Endpunkt genau ein Objekt zurückgeben sollte. Oder dass formatiertes JSON Zeilenumbrüche enthalten kann und man deshalb unbedingt einen Streaming-Parser braucht. Ignorieren Sie das. Antworten lassen sich ganz einfach an Zeilenumbrüchen aufteilen. Die Bibliothek jsonpipe ist ein guter Ausgangspunkt für Ihren Clientcode.
So sehen Sie den Unterschied, den JSON macht
Um die Auswirkungen auf mobile Nutzer zu sehen, können Sie mit rvictl auf einem Mac beobachten, wie ein echtes Mobilfunkmodul in einem echten Mobilfunknetz mit Ihrem Server kommuniziert. Eine HTTPS-Verbindung über meine Verizon-3G-Verbindung mit zwei Empfangsbalken sieht so aus. Die erste Spalte zeigt die Zeit in Sekunden:
0.000000 DNS 69 Standard query 0x5622 A instantdomainsearch.com
2.573090 DNS 85 Standard query response 0x5622 A instantdomainsearch.com A 130.211.25.142
Moment, die DNS-Auflösung dauerte 2,5 Sekunden? Wow. Vielleicht war das 3G-Modem im Ruhezustand. Endlich können wir die TCP-Verbindung aufbauen:
2.573822 TCP 64 57709 → 443 [SYN] Seq=0 Win=65535 Len=0 MSS=1388 WS=64 TSval=727045548 TSecr=0 SACK_PERM=1
2.574404 TCP 60 443 → 57709 [SYN, ACK] Seq=0 Ack=1 Win=42540 Len=0 MSS=1430 SACK_PERM=1 TSval=2852312183 TSecr=727045548 WS=128
Und den SSL/TLS-Austausch beginnen:
2.575790 TLSv1.2 285 Client Hello
3.582868 TLSv1.2 1428 [TCP Fast Retransmission] Server Hello
3.585061 TLSv1.2 127 Client Key Exchange
3.585771 TLSv1.2 58 Change Cipher Spec
3.586415 TLSv1.2 97 Encrypted Handshake Message
3.587729 TLSv1.2 103 Change Cipher Spec, Hello Request, Hello Request
Hallo! Erst jetzt, 3,5 Sekunden später, senden und empfangen wir endlich verschlüsselte Anwendungsdaten.
JSON reduziert Pakete und erhöht das Tempo
Jeder Tastendruck bei Instant Domain Search fragt mehrere Datenstrukturen nach Verfügbarkeit, Marktplatzergebnissen, Vorschlägen und weiteren Informationen ab. Wir bemerkten enorme Leistungsgewinne für Nutzer, als wir nicht mehr bei jedem Tastendruck so viele HTTPS-Verbindungen aufbauten, sondern die Ergebnisse über eine Verbindung pro Anfrage streamten. Dadurch blockieren deutlich weniger Pakete die Netzwerkverbindung des Nutzers. Der Vollständigkeit halber: Wir haben auch einen WebSocket ausprobiert. HTTPS-Verbindungen pro Anfrage erwiesen sich jedoch als der zuverlässigste Weg, unseren Nutzern schnelle Ergebnisse zu liefern.