java之session--获取最近浏览商品(获取cookie值)算法思想及代码

记录浏览历史算法

记录上次浏览商品信息

通过id获取相关信息(通过传入的id获取cookie中的值)

分析:

         当前cookie值            传入的id             最后的cookie              描述                                   算法

 cookies==null||histPro==null                 1                                    1                           第一次访问                                直接接收将传入的id

                        1                                 2                                    2,1                        小于3个且没有重复id                  将传入id放在最前面

                        2,1                             1                                     1,2                       小于3个且重复                           去重,将传入id放在最前面

                        1,2                             3                                   3,1,2                       等于3个不重复                           将传入id放在最前面

                       3,1,2                           4                                  4,3,1                        等于3个不重复                           去掉最后一个,将传入id放在最前面


注:histPro表示要获取的cookie的值,规定最多显示最近3条记录

代码:

private String createValue(HttpServletRequest request,String id) {
    Cookie[] cookies=request.getCookies();
    String histPro=null;
    if(cookies!=null){
        for(Cookie cookie:cookies){
            if(cookie.getName().equals("histPro")){
                histPro=cookie.getValue();
                break;
            }
        }
    }
    if(cookies==null||histPro==null){
        return id;
    }
    String[] ids=histPro.split(",");
    Collection colls= Arrays.asList(ids);
    //LinkedList方便操作集合,Collection-->LinkedList
    LinkedList list=new LinkedList(colls);
    //1.不超过3个
    if(list.size()<3){
        //1.id重复
        if(list.contains(id)){
            //去重,把传入的id放最前面
            list.remove(id);
            list.addFirst(id);
        }
        else {
            list.addFirst(id);
        }
    }
    else {
        //等于3个
        //id重
        if (list.contains(id)){
            list.remove(id);
            list.addFirst(id);
        }
        else {
            list.removeLast();//去掉最后一个
            list.addFirst(id);
        }
    }

    //LinkedList --->String
    StringBuffer sb=new StringBuffer();
    for(Object obj:list){
        sb.append(obj+",");
    }
    //去掉最后的逗号
    String result=sb.toString();
    result=result.substring(0,result.length()-1);
    return result;
}

<think>首先,用户的问题是关于WebSocket Session在序列化存储过程中可能存在的问题,并寻找相应的解决方案。我需要基于系统级指令和用户可见层的要求来构建回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考站内引用: - [^1]: Session无法序列化存储到Redis,只能本地存储,集群中需要Session共享。 - [^2]: Websocket Session不能直接序列化存储,跨节点可能不通。 - [^3]: Session的序列化和反序列化,以及活化和钝化,用于处理内存问题。 - [^4]: Websocket session不支持序列化,无法存储至Redis。 用户的问题:WebSocket Session序列化存储的问题与解决方法。 我的回答需要结构清晰: 1. 解释问题:WebSocket Session序列化存储时的问题。 2. 讨论原因:为什么存在这些问题。 3. 提供解决方案:如何解决这些问题。 4. 生成相关问题。 在回答中,我需要自然地引用参考内容。引用标识如[^1]。 步骤: - 开头简要概述问题。 - 分步解释问题、原因和解决方案。 - 使用中文。 - 结束时生成相关问题。 内容大纲: 1. **问题描述**:WebSocket Session在序列化存储时遇到的问题。 - 例如,session无法序列化存储到Redis等中间件,导致集群中session共享困难。 2. **原因分析**:为什么WebSocket Session不支持序列化。 - 可能涉及session状态的特殊性,如包含连接信息等。 3. **解决方案**: - 使用本地内存存储,但集群中需要共享机制。 - 活化和钝化技术(session钝化到硬盘,活化时加载)。 - 其他方法,如使用外部存储或消息队列。 4. **生成相关问题**:在最后添加相关问题。 确保引用: - 当提到session无法序列化时,引用[^1]或[^4]。 - 当讨论活化和钝化时,引用[^3]。 最终回答结构: - 引言:简要回答。 - 详细部分:分点解释。 - 代码或示例:如果有相关代码,但这里可能不需要,因为用户问题不涉及代码- 相关问题。</think>### WebSocket Session序列化存储的问题与解决方法 在分布式系统中,WebSocket Session的序列化存储是实现集群共享的关键挑战。WebSocket Session代表客户端与服务器的持久连接状态,包含连接句柄、用户信息等动态数据。序列化是将对象转换为可存储格式(如字节流)的过程,但WebSocket Session本身不支持标准序列化机制,这会导致一系列问题。以下我将逐步解释问题、分析原因,并提供可行的解决方案,确保回答真实可靠,基于实际技术实践。 #### 1. **问题描述:序列化存储的主要问题** - **无法直接序列化存储**:WebSocket Session对象通常包含不可序列化的元素(如网络连接句柄、线程上下文),尝试将其存储到Redis等中间件时,会抛出序列化异常。例如,使用Java的`java.io.Serializable`接口时,Session对象无法被正确转换为字节流,导致存储失败[^4]。 - **集群共享困难**:在分布式环境中,用户请求可能被路由到不同节点。如果Session存储在本地内存(如节点A),当用户后续请求被路由到节点B时,节点B无法访问原始Session,导致消息推送失败或连接中断[^2]。引用[^1]指出:“由于session无法实现序列化,不能存储到redis这些中间存储里面,因此这里我们只能把session存储在本地的内存中。” - **内存与性能瓶颈**:在高并发场景下(如电商抢购),大量Session驻留内存可能引发OOM(内存溢出)错误。例如,淘宝活动中,几十万用户Session若不及时钝化,会耗尽服务器资源[^3]。 #### 2. **原因分析:为什么WebSocket Session不支持序列化** - **动态连接状态**:WebSocket Session依赖于底层TCP连接,包含实时状态(如socket句柄),这些状态是瞬时的,无法被冻结为持久化格式。数学上,这类似于一个动态系统:设$S(t)$表示Session在时间$t$的状态,其变化率$\frac{dS}{dt}$依赖于网络I/O,导致$S(t)$无法被完整序列化为静态数据。 - **框架限制**:大多数WebSocket实现(如Java的`javax.websocket.Session`)未实现序列化接口,因为序列化会破坏连接活性。引用[^4]强调:“websocket session不支持序列化,无法存储至redis。” - **跨节点兼容性问题**:即使强制序列化,反序列化后的Session在新节点上可能无效,因为网络连接ID与原始节点绑定。这类似于在分布式系统中传递一个无效引用。 #### 3. **解决方案:针对序列化问题的实用方法** 为解决上述问题,可采用以下策略,核心思想是避免直接序列化Session对象,而是通过间接方式管理状态。 - **方案1: Session共享机制(推荐用于集群)** - **原理**:不存储Session对象本身,而是将会话数据(如用户ID、连接状态)提取为可序列化格式(如JSON),存储到外部存储(如Redis)。然后,通过消息中间件(如Kafka)广播事件,确保所有节点同步。 - **实施步骤**: 1. 当WebSocket连接建立时,提取关键数据(如`userId`、`sessionId`)。 2. 将这些数据序列化为字符串,存储到Redis中,使用键如`websocket:session:{userId}`。 3. 节点间通过发布-订阅模式同步消息:节点A接收到消息后,发布事件到消息队列;节点B订阅事件,并根据Redis中的数据重建上下文。 - **优点**:避免直接处理Session对象,支持高可用。引用[^2]提到:“Websocket Session共享解决...既然Websocket Session不能直接序列化,可以通过外部存储同步状态。” - **示例代码(伪代码)**: ```java // 存储到Redis String sessionData = serializeToJson(userId, status); // 序列化为JSON redis.set("session:" + userId, sessionData); // 节点间消息同步 kafka.publish("session-update", new Message(userId, "data")); ``` - **方案2: Session活化和钝化(适用于内存优化)** - **原理**:将不活跃的Session“钝化”到磁盘(序列化为文件),当需要时“活化”加载回内存。这类似于操作系统的页面置换算法- **实施步骤**: 1. 定义Session钝化:当Session闲置时(如超时30分钟),将其状态保存为文件(如使用Java的`ObjectOutputStream`)。 2. 活化过程:用户请求到来时,从文件反序列化状态,并重新绑定到WebSocket连接。 3. 结合定时任务:使用Quartz等工具管理钝化周期。 - **优点**:减少内存占用,适合突发流量场景。引用[^3]解释:“Session的活化和钝化...让其在闲置的时候离开内存,将信息保存至硬盘,等要用的时候,就重新加载进内存。” - **公式描述**:设内存使用量$M$与活跃Session数$N$成正比,即$M = k \cdot N$。通过钝化,可将$N$控制在阈以下,避免$M$溢出。 - **方案3: 粘性会话(Sticky Session)结合负载均衡** - **原理**:在负载均衡层(如Nginx)配置基于用户IP或Cookie的粘性路由,确保同一用户请求始终路由到同一节点。这样,Session可安全存储在本地内存,无需序列化。 - **实施步骤**: 1. 配置负载均衡器为“sticky session”模式。 2. 每个节点维护自己的Session缓存。 3. 节点失效时,通过备份机制恢复。 - **优点**:简单易行,但牺牲了集群弹性。适用于小型系统。 - **限制**:如果节点宕机,Session会丢失,需配合心跳检测。 **总结解决方案**:优先采用Session共享机制(方案1)以实现高可用;对于内存敏感场景,结合活化和钝化(方案2)。这些方法已在电商、即时通讯系统中验证,能有效规避序列化问题。 ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值