WebSocket en Kotlin : création d'applications temps réel de niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi un WebSocket avancé en Kotlin ?

\n

Les applications web modernes exigent de plus en plus souvent une transmission instantanée des données : chats, notifications, jeux en ligne, cotations financières et tableaux de bord. Le protocole WebSocket de base permet d'établir une connexion bidirectionnelle permanente entre le client et le serveur, mais en pratique, le développement d'une application temps réel fiable et évolutive en Kotlin nécessite bien plus que la simple ouverture d'un socket.

\n

Dans cet article, nous dépasserons le cadre d'un simple serveur écho. Nous examinerons les patrons architecturaux pour gérer des milliers de connexions, la gestion des erreurs avec les coroutines Kotlin, le clustering de serveurs avec des courtiers de messages et les questions de sécurité. Ce contenu est destiné aux développeurs déjà familiers avec les bases de Kotlin et Ktor.

\n\n

1. Architecture d'un serveur WebSocket à haute charge avec Ktor

\n

Pour une solution de production, il ne suffit pas d'ajouter un gestionnaire webSocket. Il est nécessaire de concevoir la gestion des sessions, le cycle de vie de la connexion et l'isolation des gestionnaires. Examinons les éléments clés.

\n\n

Gestion des sessions et leur regroupement

\n

Chaque connexion WebSocket dans Ktor est représentée par un objet DefaultWebSocketSession. Pour envoyer des messages à un utilisateur spécifique ou à un groupe (par exemple, "salle de chat"), il faut stocker les sessions actives. Utilisez ConcurrentHashMap pour la sécurité des threads.

\n
import io.ktor.websocket.*\nimport java.util.concurrent.ConcurrentHashMap\n\nclass SessionManager {\n    private val sessions = ConcurrentHashMap<String, WebSocketSession>()\n    private val roomSessions = ConcurrentHashMap<String, MutableSet<String>>()\n\n    fun addUserToRoom(roomId: String, userId: String, session: WebSocketSession) {\n        sessions[userId] = session\n        roomSessions.computeIfAbsent(roomId) { mutableSetOf() }.add(userId)\n    }\n\n    suspend fun broadcastToRoom(roomId: String, message: String) {\n        roomSessions[roomId]?.forEach { userId ->\n            sessions[userId]?.send(Frame.Text(message))\n        }\n    }\n\n    fun removeUser(userId: String) {\n        sessions.remove(userId)\n        roomSessions.forEach { (_, users) -> users.remove(userId) }\n    }\n}
\n\n

Gestion du cycle de vie avec les coroutines

\n

Ktor utilise les coroutines pour gérer chaque connexion. Il est important de traiter correctement les exceptions et la fermeture du socket pour éviter les fuites mémoire. Utilisez try-catch à l'intérieur du bloc webSocket et appelez removeUser dans le bloc finally.

\n
install(WebSockets) {\n    pingPeriod = Duration.ofSeconds(15)\n    timeout = Duration.ofSeconds(30)\n    maxFrameSize = Long.MAX_VALUE\n    masking = false\n}\n\nembeddedServer(Netty, port = 8080) {\n    val sessionManager = SessionManager()\n    routing {\n        webSocket("/chat/{roomId}") {\n            val roomId = call.parameters["roomId"] ?: "general"\n            val userId = call.request.queryParameters["userId"] ?: "anon"\n            sessionManager.addUserToRoom(roomId, userId, this)\n            try {\n                for (frame in incoming) {\n                    if (frame is Frame.Text) {\n                        val text = frame.readText()\n                        sessionManager.broadcastToRoom(roomId, "[$userId]: $text")\n                    }\n                }\n            } catch (e: Exception) {\n                log.error("Erreur WebSocket pour l'utilisateur $userId : ${e.localizedMessage}")\n            } finally {\n                sessionManager.removeUser(userId)\n                log.info("Utilisateur $userId déconnecté de la salle $roomId")\n            }\n        }\n    }\n}.start(wait = true)
\n\n

2. Mise à l'échelle et clustering WebSocket en Kotlin

\n

Un seul serveur ne peut pas gérer des dizaines de milliers de connexions simultanées. La solution est la mise à l'échelle horizontale. Cependant, une connexion WebSocket est

Blogs

Book Recommendations