任务:有一个使用 Helidon SE4 框架实现的服务器。与服务器的通信是使用WebSocket协议进行的。对于每个新连接,我需要保存用户 ID。当连接关闭时,您需要删除这些数据。
问题:在 Helidon SE4 中,我没有找到任何与 Jakarta WebSockets 中类似的机制。 WsSession 没有类似 的方法Session.getUserProperties(),并且实现类WsListener会被所有已建立的连接重用。
我如何尝试解决这个问题:但是对于每个 WebSocket 连接,都提供了自己独特的虚拟流。
- 我尝试用它
ThreadLocal来存储用户数据。但这会导致内存泄漏,因为......客户端可以在不通知服务器的情况下关闭连接 -> 不会从正确的线程调用任何 WsListener 方法 -> 不可能ThreaLocal.remove()从正确的线程调用。 - 我也尝试使用
ConcurrentHashMap.然而,这导致了性能问题,因为......所有负责连接的线程都被迫不断地相互等待。
最有可能的是——不可能。虽然WebSocket是有状态协议,但它也可以用作无状态协议。最有可能的是,当每个传入消息都有一个可以唯一标识客户端的特定令牌时,该框架的开发人员希望鼓励这种使用。显然没有条件就没有办法
ConcurrentHashMap。要解决Helidon SE4中的问题,您可以使用 的方法,将其与防止内存泄漏的
ConcurrentHashMap使用结合起来。WeakReference这将允许您将用户数据与连接相关联,并确保在连接关闭或没有对该连接的引用时自动删除该数据。
下面是如何实现这一想法的示例:
使用以下命令创建地图来存储数据
WeakReference:使用卡获取用户数据:
在此示例中,打开连接时,将用户
onOpen添加ID到地图,将其与会话关联WsSession。连接关闭时,onClose从地图中删除数据。使用它
WeakReference有助于防止内存泄漏,因为如果不再引用会话,数据将被自动删除。这种方法避免了与使用相关的性能问题
ConcurrentHashMap,因为地图上的添加和删除操作仅在连接打开和关闭时发生,而不是在每次访问时发生。在这种情况下,让我们看看一种更可靠的方式来存储用户数据
ConcurrentHashMap并确保在连接关闭时删除数据。在此示例中,我们使用
WsSessionas 中的键ConcurrentHashMap,假设每个实例WsSession对于每个连接都是唯一的(假设对于 WebSocket 连接通常如此)。下面是一些解决您描述的问题的示例代码:
此示例
onOpen在打开连接时将用户 ID 添加到地图,并将其与 session 相关联WsSession。连接关闭时,onClose从地图中删除数据。同样,如果连接错误,onError它也会删除数据。这种方法可以确保在连接关闭或发生错误时立即清除用户数据,从而防止内存泄漏。使用
ConcurrentHashMap可确保处理数据时的线程安全和高性能。如果您需要确保
WsSession每个连接都是唯一的,您还可以运行测试或参考 Helidon 文档或社区进行确认。在大多数 WebSocket 连接实现中,每个新连接的每个会话实例都是唯一的。那些你缺少的功能我们计划添加到框架中。目前,WebSocket 服务器处于原型状态。用人的话来说,这只是一个未完成的框架。目前尚不清楚它是否会完成。也许在您的情况下,最好的解决方案是迁移到另一个框架。