Canary-Deployments mit Kotlin: Nahtloses Release ohne Angst

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum normales Deployment immer eine Lotterie ist?

\n

Jeder Entwickler hat mindestens einmal im Leben diesen Moment der Wahrheit erlebt: Du drückst den "Deploy"-Button und das Herz rutscht in die Hose. Was, wenn die neue Version die Datenbank lahmlegt? Was, wenn die Benutzer einen 500er-Fehler statt der Startseite sehen?

\n

Normales Deployment ist wie ein Fallschirmsprung ohne Reserve. Entweder funktioniert alles perfekt, oder du verbringst die Nacht mit Logs und versuchst zu verstehen, was schiefgelaufen ist. Aber es gibt einen Weg, diesen Prozess sicher zu machen – Canary-Deployments.

\n

In diesem Artikel schauen wir uns an, wie man Canary-Deployments in Kotlin mit Ktor und einem einfachen Load-Balancer implementiert. Du lernst, neuen Code zunächst an 5% der Benutzer auszuliefern und dann den Traffic schrittweise zu erhöhen. Und ja, wir schreiben Code, der wirklich funktioniert.

\n\n

Was ist ein Canary-Deployment und warum brauchst du es?

\n

Stell dir vor, du bist ein Kapitän. Anstatt sofort durch die Riffe zu segeln, schickst du ein kleines Boot (den Kanarienvogel) voraus. Wenn es durchkommt, folgt die gesamte Flotte. Wenn es sinkt, verlierst du nur ein Boot.

\n

In der IT-Welt sieht das so aus: Du rollst eine neue Version des Dienstes zunächst für eine kleine Gruppe von Benutzern aus. Wenn die Metriken in Ordnung sind, wird der Traffic erhöht. Wenn nicht, rollst du innerhalb von Sekunden zurück.

\n

Die Vorteile liegen auf der Hand:

\n
    \n
  • Risikominimierung – Fehler betreffen nur 1-5% der Zielgruppe.
  • \n
  • Schnelles Feedback – Du siehst Fehler, bevor sie zur Katastrophe werden.
  • \n
  • A/B-Testing – Du kannst die Leistung der alten und neuen Version vergleichen.
  • \n
  • Zero Downtime – Benutzer bemerken den Wechsel nicht.
  • \n
\n

Aber es gibt auch einen Wermutstropfen: Man muss Traffic verwalten, Metriken überwachen und den Prozess automatisieren können. Kotlin mit seiner Prägnanz und den Coroutinen eignet sich hervorragend für diese Aufgabe.

\n\n

Architektur eines Canary-Deployments in Kotlin

\n

Lasst uns eine einfache, aber funktionale Architektur aufbauen. Wir haben:

\n
    \n
  • Load-Balancer – Entscheidet, welcher Prozentsatz der Anfragen an die alte Version (stable) und welcher an die neue Version (canary) geht.
  • \n
  • Zwei Service-Instanzen – stable und canary, beide in Kotlin mit Ktor geschrieben.
  • \n
  • Monitoring – Zähler für Fehler und Antwortzeiten.
  • \n
\n

Der Load-Balancer trifft seine Entscheidung entweder basierend auf dem Header X-Canary oder per Zufallsverteilung. Wir gehen den zweiten Weg – er ist näher an der Realität.

\n\n

Code schreiben: Load-Balancer in Kotlin

\n

Beginnen wir mit dem Load-Balancer. Er nimmt Anfragen entgegen und leitet sie an einen der beiden Dienste weiter. Der Einfachheit halber verwenden wir den integrierten HTTP-Client von Ktor.

\n\n
import io.ktor.client.*\nimport io.ktor.client.engine.cio.*\nimport io.ktor.client.request.*\nimport io.ktor.client.statement.*\nimport io.ktor.server.application.*\nimport io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.response.*\nimport io.ktor.server.routing.*\nimport kotlinx.coroutines.runBlocking\nimport kotlin.random.Random\n\n// Konfiguration\nconst val STABLE_URL = "http://localhost:8081"\nconst val CANARY_URL = "http://localhost:8082"\nvar canaryPercent = 5 // Wir beginnen mit 5% Traffic\n\nfun main() {\n    val client = HttpClient(CIO)\n\n    embeddedServer(Netty, port = 8080) {\n        routing {\n            get("/api/data") {\n                val useCanary = Random.nextInt(100) < canaryPercent\n                val targetUrl = if (useCanary) CANARY_URL else STABLE_URL\n\n                val response = runBlocking {\n                    client.get("$targetUrl/api/data")\n                }\n\n                call.respondText(\n                    response.bodyAsText(),\n                    contentType = response.contentType()\n                )\n            }\n\n            // Endpunkt zum Ändern des Canary-Prozentsatzes\n            get("/canary/set/{perc                

Blogs

Buchempfehlungen