Long Polling vs WebSocket in Kotlin: Was für Echtzeit wählen?
\n\nStellen Sie sich vor: Sie schreiben einen Chat in Kotlin, einen Börsenterminal oder ein Serverüberwachungssystem. Der Kunde muss Änderungen sofort sehen. Die traditionelle HTTP-Anfrage „hin und zurück“ ist hier nicht geeignet – die Daten müssen von selbst kommen, ohne ständige Benutzeraktionen.
\n\nIn der Welt von Kotlin gibt es zwei beliebte Ansätze: Long Polling und WebSocket. Beide ermöglichen eine Echtzeit-Interaktion, tun dies jedoch grundlegend unterschiedlich. Welchen soll man wählen? Lassen Sie es uns anhand praktischer Beispiele klären, ohne überflüssige Theorie und akademische Vorträge.
\n\nWas ist Long Polling (und warum es nicht tot ist)
\n\nLong Polling ist eine Technik, bei der der Client eine HTTP-Anfrage sendet und der Server nicht sofort antwortet, sondern die Verbindung offen hält, bis neue Daten verfügbar sind. Sobald Daten eintreffen, sendet der Server eine Antwort, der Client verarbeitet sie und öffnet sofort eine neue Anfrage. Der Zyklus wiederholt sich.
\n\nEs sieht aus wie normales HTTP, jedoch mit einem langen Timeout. Keine zusätzlichen Protokolle, keine Handshakes – alles funktioniert über Standard HTTP/1.1 oder HTTP/2.
\n\nBeispiel für Long Polling in Kotlin (Ktor Server + OkHttp Client)
\n\nServerteil mit Ktor (der Server wartet, bis eine Nachricht eintrifft):
\n\nimport io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.routing.*\nimport io.ktor.server.response.*\nimport io.ktor.http.*\nimport kotlinx.coroutines.*\n\nfun main() {\n embeddedServer(Netty, port = 8080) {\n routing {\n get("/long-poll") {\n // Simulation des Wartens auf eine neue Nachricht\n val message = withContext(Dispatchers.Default) {\n delay(5000) // warte 5 Sekunden (oder auf ein neues Ereignis)\n "Neue Nachricht: ${System.currentTimeMillis()}"\n }\n call.respondText(message, ContentType.Text.Plain)\n }\n }\n }.start(wait = true)\n}\n\n\nClient mit OkHttp:
\n\nimport okhttp3.*\n\nval client = OkHttpClient.Builder()\n .readTimeout(30, TimeUnit.SECONDS) // wichtiger Punkt!\n .build()\n\nfun startLongPolling() {\n val request = Request.Builder()\n .url("http://localhost:8080/long-poll")\n .build()\n\n client.newCall(request).enqueue(object : Callback {\n override fun onFailure(call: Call, e: IOException) {\n e.printStackTrace()\n // Polling bei Fehler unbedingt neu starten\n startLongPolling()\n }\n\n override fun onResponse(call: Call, response: Response) {\n response.use {\n if (response.isSuccessful) {\n println("Erhalten: ${response.body?.string()}")\n // Sofort die nächste Anfrage starten\n startLongPolling()\n }\n }\n }\n })\n}\n\n\nVorteile von Long Polling:
\n- \n
- Funktioniert überall, auch hinter Unternehmens-Proxys und in alten Browsern \n
- Einfaches Debugging – Sie sehen normale HTTP-Anfragen in den Logs \n
- Leicht in bestehende Infrastruktur integrierbar (Load Balancer, Caches, CDN) \n
Nachteile:
\n- \n
- Hohe Latenz – zwischen dem Senden der Anfrage und dem Erhalt der Antwort kann bis zu RTT (Round Trip Time) vergehen \n
- Der Server hält viele offene Verbindungen (jede Anfrage ist ein separater Thread/Coroutine) \n
- Bei Wiederverbindung können Nachrichten verloren gehen (falls keine Idempotenz implementiert wird) \n
WebSocket: Vollwertiger Duplex
\n\nWebSocket ist ein separates Protokoll (ws://), das nach einem HTTP-Handshake eine permanente bidirektionale Verbindung herstellt. Server und Client können jederzeit Nachrichten senden, ohne Overhead durch Header.
\n\n