WebSocket em Kotlin: criação de aplicações real-time de nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que um WebSocket avançado em Kotlin?

\n

As aplicações web modernas exigem cada vez mais transmissão instantânea de dados: chats, notificações, jogos online, cotações financeiras e painéis de monitoramento. O protocolo WebSocket básico permite estabelecer uma conexão bidirecional permanente entre cliente e servidor, mas na prática, desenvolver uma aplicação real-time confiável e escalável em Kotlin exige muito mais do que simplesmente abrir um socket.

\n

Neste artigo, iremos além de um simples servidor echo. Abordaremos padrões arquiteturais para lidar com milhares de conexões, tratamento de erros usando corrotinas Kotlin, clusterização de servidores com brokers de mensagens e questões de segurança. O material é voltado para desenvolvedores já familiarizados com os fundamentos de Kotlin e Ktor.

\n\n

1. Arquitetura de um servidor WebSocket de alta carga em Ktor

\n

Para uma solução de produção, não basta apenas adicionar um handler webSocket. É necessário planejar o gerenciamento de sessões, o ciclo de vida da conexão e o isolamento dos handlers. Vamos analisar os elementos-chave.

\n\n

Gerenciamento de sessões e seu agrupamento

\n

Cada conexão WebSocket no Ktor é representada por um objeto DefaultWebSocketSession. Para enviar mensagens a um usuário específico ou a um grupo (por exemplo, "sala de chat"), é necessário armazenar as sessões ativas. Use ConcurrentHashMap para segurança em 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

Tratamento do ciclo de vida com corrotinas

\n

O Ktor usa corrotinas para processar cada conexão. É importante tratar corretamente as exceções e o fechamento do socket para evitar vazamentos de memória. Use try-catch dentro do bloco webSocket e chame removeUser no bloco 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("Erro WebSocket para o usuário $userId: ${e.localizedMessage}")\n            } finally {\n                sessionManager.removeUser(userId)\n                log.info("Usuário $userId desconectado da sala $roomId")\n            }\n        }\n    }\n}.start(wait = true)
\n\n

2. Escalabilidade e clusterização de WebSocket em Kotlin

\n

Um único servidor não conseguirá lidar com dezenas de milhares de conexões simultâneas. A solução é a escalabilidade horizontal. No entanto, a conexão WebSocket "p

Blogs

Book Recommendations