在Redis中存储Web Socket会话

4

我有一个Web Socket服务器端点部署在Tomcat中,如下所示:

    @ServerEndpoint(value="/alerts/{username}/{sessionId}/{token}",
    decoders = AlertDTODecoder.class, 
    encoders = AlertDTOEncoder.class )
public class AlertWebSocketEndpoint {

    @OnOpen
    public void onOpen(Session session, 
            @PathParam("username") String username, 
            @PathParam("sessionId") String sessionId,
            @PathParam("token") String token) throws IOException {

        String origToken = TokenCacheServiceImpl.getInstance().getToken(username, sessionId);

        if ( origToken == null || !origToken.equals(token)) {           
            session.close();
        }else {    
            AlertSession.getInstance().addUserSession(username, session);
        }
    }

    @OnClose
    public void onClose(Session session, @PathParam("username") String username) throws Exception {    
        AlertSession.getInstance().removeUserSession(username, session);        
        session.close();
    }
}

AlertSession是一个单例类,我在其中维护会话缓存。
TokenCacheServiceImpl用于在REDIS中缓存与每个用户对应的令牌。
由于Session是非可序列化对象,因此无法将其存储在REDIS中,必须在本地内存中维护它。我希望避免这种情况,因为如果服务器重新启动或者我想进行负载均衡,我不想丢失数据。
如何实现这一点?

1
编写自己的序列化程序?Redis并不一定是持久性存储,因此您可能会丢失数据。 - No Refunds No Returns
假设Redis是持久化的。那么有没有办法存储Session对象? - Dinesh Shekhawat
最终,所有东西都可能会被损坏、丢失、盗窃、磁化、停用等。将“session”序列化,然后如果它不是过度庞大的话,将其存储为redis字符串。在redis中,字符串是具有长度前缀的二进制数组,不一定是a-zA-z0-9。写入时进行序列化,读取时进行反序列化。如果您正在使用.net,请参阅NetDataContractSerializer进行讨论。https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.netdatacontractserializer?view=netframework-4.7.2 我曾经在一个使用此方法缓存任何内容的系统上工作过。Java? - No Refunds No Returns
1个回答

3

如果你想要存储任意的非serializable对象,那么你需要做很多工作。

但是如果你知道你正在存储的对象类型,那么你可以编写自己的序列化程序。并没有规定数据必须是二进制的。你可以使用XML、JSON或者一些自定义的存储系统。

你能限制你的应用只存储某些类型的对象吗?例如,如果你只存储基本类型(以及它们的包装类型)和集合等,你可以用非常少的代码完成这个任务。否则,准备写更多的代码。

把你的会话对象的代码更改为Serializable可能会更容易,并且可以直接使用Java序列化来完成。

请注意,Java序列化的未来是不确定的。一个很旧的JEP曾经提出过删除序列化的建议,但是已被撤回。最近的安全问题促使一些人支持从未来的Java版本中删除序列化。第二篇文章特别提到,“删除序列化是一个长期目标,并且是Amber项目的一部分”,但是我没有看到Amber项目中涉及任何与序列化有关的内容。

此外,某些现有的Java规范(包括Java EE的部分,包括Servlet规范)几乎需要支持序列化,因此即使它已被弃用,我也不认为它会很快消失。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接