引言:为什么 Kotlin 上的 WebSocket 是实时系统的专业选择
现代 Web 应用需要对用户操作做出即时响应:聊天、在线游戏、股票行情、监控系统。基于请求-响应的 HTTP 协议对此类任务效率低下。正是在这里,WebSocket 登场了——一种在客户端和服务器之间提供持久双向连接的协议。
Kotlin 语言凭借其强大的协程(coroutines)系统和 Ktor 框架,为构建可扩展且容错的实时应用提供了理想环境。在本文中,我们将深入探讨 Kotlin 上 WebSocket 的高级技术:从应用架构到性能微调。您将学习如何超越简单的 echo 服务器,构建工业级解决方案。
Kotlin WebSocket 应用架构:从简单到复杂
基础:Ktor Server 和 WebSockets 插件
我们从基本配置开始。Ktor 框架是在 Kotlin 上创建异步服务器的事实标准。要使用 WebSocket,需要添加插件:
// build.gradle.kts
implementation("io.ktor:ktor-server-websockets:$ktor_version")
implementation("io.ktor:ktor-server-netty:$ktor_version")
支持 WebSocket 的服务器基本初始化如下所示:
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import io.ktor.server.routing.*
fun main() {
embeddedServer(Netty, port = 8080) {
install(WebSockets) {
pingPeriod = 15.seconds // Keep-alive 心跳
timeout = 15.seconds // 响应超时
maxFrameSize = Long.MAX_VALUE // 最大帧大小
}
routing {
webSocket("/chat") {
// 连接处理逻辑
send("欢迎加入聊天!")
for (frame in incoming) {
if (frame is Frame.Text) {
val text = frame.readText()
// 消息处理
}
}
}
}
}.start(wait = true)
}
请注意 pingPeriod 和 timeout 参数。在生产环境中,需要根据网络条件配置这些参数,以避免在临时延迟时断开连接。
会话管理:不仅仅是 socket 列表
在高级层面,仅仅存储 DefaultWebSocketServerSession 列表是不够的。需要管理会话,按房间/频道分组,并正确处理断开连接。
class ChatRoom(private val name: String) {
private val sessions = mutableSetOf<WebSocketSession>()
@Synchronized
fun add(session: WebSocketSession) {
sessions.add(session)
broadcast("${session.call.request.local.remoteHost} 加入了 $name")
}
@Synchronized
fun remove(session: WebSocketSession) {
sessions.remove(session)
broadcast("${session.call.request.local.remoteHost} 离开了 $name")
}
@Synchronized
fun broadcast(message: String) {
sessions.forEach { session ->
GlobalScope.launch {
try {
session.send(Frame.Text(message))
} catch (e: Exception) {
// 记录日志并移除有问题的连接
remove(session)
}
}
}
}
}
重要提示: 使用 @Synchronized 可以防止并发访问 mutableSetOf 时的竞态条件。在高负载系统中,应该