RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1586082
Accepted
Bakuard
Bakuard
Asked:2024-07-04 14:08:24 +0000 UTC2024-07-04 14:08:24 +0000 UTC 2024-07-04 14:08:24 +0000 UTC

如何在 Helidon SE4 中存储每个 WebSocket 连接的用户数据

  • 772

任务:有一个使用 Helidon SE4 框架实现的服务器。与服务器的通信是使用WebSocket协议进行的。对于每个新连接,我需要保存用户 ID。当连接关闭时,您需要删除这些数据。

问题:在 Helidon SE4 中,我没有找到任何与 Jakarta WebSockets 中类似的机制。 WsSession 没有类似 的方法Session.getUserProperties(),并且实现类WsListener会被所有已建立的连接重用。

我如何尝试解决这个问题:但是对于每个 WebSocket 连接,都提供了自己独特的虚拟流。

  1. 我尝试用它ThreadLocal来存储用户数据。但这会导致内存泄漏,因为......客户端可以在不通知服务器的情况下关闭连接 -> 不会从正确的线程调用任何 WsListener 方法 -> 不可能ThreaLocal.remove()从正确的线程调用。
  2. 我也尝试使用ConcurrentHashMap.然而,这导致了性能问题,因为......所有负责连接的线程都被迫不断地相互等待。
java
  • 4 4 个回答
  • 87 Views

4 个回答

  • Voted
  1. Sandro
    2024-07-04T19:17:32Z2024-07-04T19:17:32Z

    最有可能的是——不可能。虽然WebSocket是有状态协议,但它也可以用作无状态协议。最有可能的是,当每个传入消息都有一个可以唯一标识客户端的特定令牌时,该框架的开发人员希望鼓励这种使用。显然没有条件就没有办法ConcurrentHashMap。

    • 1
  2. PavelGalkin
    2024-07-10T17:23:17Z2024-07-10T17:23:17Z

    要解决Helidon SE4中的问题,您可以使用 的方法,将其与防止内存泄漏的ConcurrentHashMap使用结合起来。WeakReference

    这将允许您将用户数据与连接相关联,并确保在连接关闭或没有对该连接的引用时自动删除该数据。

    下面是如何实现这一想法的示例:

    1. 使用以下命令创建地图来存储数据WeakReference:

      import io.helidon.webserver.websocket.WsListener;
      import io.helidon.webserver.websocket.WsSession;
      
      import java.util.concurrent.ConcurrentHashMap;
      import java.lang.ref.WeakReference;
      
      public class WebSocketListener implements WsListener {
          private final ConcurrentHashMap<WsSession, WeakReference<String>> userSessionMap = new ConcurrentHashMap<>();
      
          @Override
          public void onOpen(WsSession session) {
              // Здесь вы можете добавить ID пользователя в карту при открытии соединения.
              String userId = "someUserId"; // Получите userId из ваших данных
              userSessionMap.put(session, new WeakReference<>(userId));
          }
      
          @Override
          public void onMessage(WsSession session, String message) {
              // Обработка сообщения
          }
      
          @Override
          public void onClose(WsSession session, int status, String reason) {
              // Удаление данных при закрытии соединения
              userSessionMap.remove(session);
          }
      
          @Override
          public void onError(WsSession session, Throwable throwable) {
              // Обработка ошибок
          }
      }
      
    2. 使用卡获取用户数据:

      public String getUserId(WsSession session) {
          WeakReference<String> ref = userSessionMap.get(session);
          return (ref != null) ? ref.get() : null;
      }
      

    在此示例中,打开连接时,将用户onOpen添加ID到地图,将其与会话关联WsSession。连接关闭时,onClose从地图中删除数据。

    使用它WeakReference有助于防止内存泄漏,因为如果不再引用会话,数据将被自动删除。

    这种方法避免了与使用相关的性能问题ConcurrentHashMap,因为地图上的添加和删除操作仅在连接打开和关闭时发生,而不是在每次访问时发生。

    • 1
  3. PavelGalkin
    2024-07-11T23:48:15Z2024-07-11T23:48:15Z

    在这种情况下,让我们看看一种更可靠的方式来存储用户数据ConcurrentHashMap并确保在连接关闭时删除数据。

    在此示例中,我们使用WsSessionas 中的键ConcurrentHashMap,假设每个实例WsSession对于每个连接都是唯一的(假设对于 WebSocket 连接通常如此)。

    下面是一些解决您描述的问题的示例代码:

    1. 创建一个地图来存储用户数据:
    import io.helidon.webserver.websocket.WsListener;
    import io.helidon.webserver.websocket.WsSession;
    
    import java.util.concurrent.ConcurrentHashMap;
    
    public class WebSocketListener implements WsListener {
        private final ConcurrentHashMap<WsSession, String> userSessionMap = new ConcurrentHashMap<>();
    
        @Override
        public void onOpen(WsSession session) {
            // Здесь вы можете добавить ID пользователя в карту при открытии соединения.
            String userId = "someUserId"; // Получите userId из ваших данных
            userSessionMap.put(session, userId);
        }
    
        @Override
        public void onMessage(WsSession session, String message) {
            // Обработка сообщения
        }
    
        @Override
        public void onClose(WsSession session, int status, String reason) {
            // Удаление данных при закрытии соединения
            userSessionMap.remove(session);
        }
    
        @Override
        public void onError(WsSession session, Throwable throwable) {
            // Удаление данных при ошибке
            userSessionMap.remove(session);
        }
    
        public String getUserId(WsSession session) {
            return userSessionMap.get(session);
        }
    }
    
    1. 使用卡获取用户数据:
    public String getUserId(WsSession session) {
        return userSessionMap.get(session);
    }
    

    此示例onOpen在打开连接时将用户 ID 添加到地图,并将其与 session 相关联WsSession。连接关闭时,onClose从地图中删除数据。同样,如果连接错误,onError它也会删除数据。

    这种方法可以确保在连接关闭或发生错误时立即清除用户数据,从而防止内存泄漏。使用ConcurrentHashMap可确保处理数据时的线程安全和高性能。

    如果您需要确保WsSession每个连接都是唯一的,您还可以运行测试或参考 Helidon 文档或社区进行确认。在大多数 WebSocket 连接实现中,每个新连接的每个会话实例都是唯一的。

    • 1
  4. Best Answer
    Sandro
    2024-07-13T11:23:28Z2024-07-13T11:23:28Z

    那些你缺少的功能我们计划添加到框架中。目前,WebSocket 服务器处于原型状态。用人的话来说,这只是一个未完成的框架。目前尚不清楚它是否会完成。也许在您的情况下,最好的解决方案是迁移到另一个框架。

    • 1

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5