用redis管理nitrogen中的session

2 篇文章 0 订阅
2 篇文章 0 订阅

nitrogen使用中session问题

nitrogen中的session在集群情况下会找不到,经常会出现重新登录情况,试图修改成为mnesia管理session,在节点超过一定数量时mnesia同步机制会出现同步慢的问题,为此决定再次修改为redis来管理session。

 

修改为redis管理session

 

1 在nitrogen中调用wf:session/2设置session时调用了session_handler:set_value/2,回调behaviour (session_handler),wf_handler:call/3,这里实现了一个简单的session_handler,只要实现自己的session_handler行为,就可以了,在wf:context中会配置具体调用哪些handler,只要修改make_handler(session_handler, simple_session_handler), %simple_session_handler), 为自己的实现即可。
2 我实现的redis_session_handler
Erlang代码   收藏代码
  1. % Copyright (c) 2008-2010 Rusty Klophaus  
  2. % See MIT-LICENSE for licensing information.  
  3.   
  4. % This is a "simple as possible" session handler. Unfortunately,  
  5. % due to time constraints, had to leave out some great code  
  6. % contributed by Dave Peticolas that fit Nitrogen sessions  
  7. % into a gen_server. My code below is far inferior.   
  8. % Someone please make it better! - Rusty  
  9.   
  10. -module (redis_session_handler).  
  11. -include_lib ("wf.hrl").  
  12. -behaviour (session_handler).  
  13. -export ([  
  14.     init/2,   
  15.     finish/2,  
  16.     get_value/4,   
  17.     set_value/4,   
  18.     clear_all/2  
  19. ]).  
  20. -record (state, {unique}).  
  21.   
  22. init(_Config, _State) ->   
  23.     Cookie = wf:cookie(get_cookie_name()),  
  24.     State = case wf:depickle(Cookie) of  
  25.         undefined -> new_state();  
  26.         Other -> Other  
  27.     end,  
  28.     {ok, State}.  
  29.   
  30. finish(_Config, State) ->   
  31.     % Drop the session cookie...  
  32.     Timeout = wf:config_default(session_timeout, 20),  
  33.     ok = wf:cookie(get_cookie_name(), wf:pickle(State), "/", Timeout),  
  34.     {ok, []}.  
  35.   
  36. get_value(Key, DefaultValue, _Config, State) ->   
  37.     %Host = wf:config_default(erldis_host, "127.0.0.1"),  
  38.     %Port = wf:config_default(erldis_port, 6379),  
  39.     %{ok, Client} = erldis:connect(Host, Port),  
  40.     %io:format("~p",[?LINE]),  
  41.     %io:format("get_value, Key = ~p~n",[Key]),  
  42.     Client = erldis_sup:client(),  
  43.     Value = case erldis:hget(Client, State#state.unique, Key) of  
  44.     nil ->  
  45.         DefaultValue;  
  46.     Any ->  
  47.         binary_to_term(Any)  
  48.     end,  
  49.     %io:format("get_value, Key = ~p, Value = ~p~n",[Key, Value]),  
  50.     Timeout = wf:config_default(session_timeout, 20),  
  51.     erldis:expire(Client, State#state.unique, Timeout*60),  
  52.     {ok, Value, State}.  
  53.   
  54. set_value(Key, Value, _Config, State) ->   
  55.     %io:format("set_value, Key = ~p, Value = ~p~n",[Key, Value]),  
  56.     Client = erldis_sup:client(),  
  57.   
  58.     OldValue = case erldis:hget(Client, State#state.unique, Key) of  
  59.     nil ->  
  60.         undefined;  
  61.     Any ->  
  62.         binary_to_term(Any)  
  63.     end,  
  64.     %io:format("~p",[?LINE]),  
  65.     %io:format("OldValue = ~n~p~n",[OldValue]),  
  66.     erldis:hset(Client, State#state.unique, Key, term_to_binary(Value)),  
  67.     Timeout = wf:config_default(session_timeout, 20),  
  68.     erldis:expire(Client, State#state.unique, Timeout*60),  
  69.     {ok, OldValue, State}.  
  70.   
  71. clear_all(_Config, State) ->   
  72.     Client = erldis_sup:client(),  
  73.     case erldis:del(Client, State#state.unique) of  
  74.     nil ->  
  75.         undefined;  
  76.     Any ->  
  77.         %io:format("~p",[?LINE]),  
  78.         %io:format("~n~p~n",[Any]),  
  79.         Any  
  80.     end,  
  81.     {ok, State}.  
  82.   
  83. %%% PRIVATE FUNCTIONS  
  84.   
  85. get_cookie_name() ->  
  86.     wf:config_default(cookie_name, "lxbssn").  
  87.   
  88. new_state() ->  
  89.     Unique = erlang:md5(term_to_binary({now(), erlang:make_ref()})),  
  90.     #state { unique=Unique }.  

 

 3  在上面代码中我使用了erldis作为redis的erlang客户端,经测试未发现问题,很稳定。

 

4 问题: 以上代码实现中查阅过redis手册,想找到类似 setex直接设置过期时间的命令,但没有找到,用hash 实现是为了节省内存与方便管理,如有更好解决方案大家回复交流。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot 使用 Redis 存储 WebSocketSession,可以通过 RedisTemplate 来实现。以下是一个示例代码: 首先,确保已经在 Spring Boot 项目配置好了 RedisTemplate,可以通过在配置类或配置文件添加相应的配置来实现。 然后,在你的 WebSocket 处理器,注入 RedisTemplate,并使用它来存储和获取 WebSocketSession。示例代码如下: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import java.util.concurrent.TimeUnit; @Component public class MyWebSocketHandler extends TextWebSocketHandler { private final RedisTemplate<String, Object> redisTemplate; @Autowired public MyWebSocketHandler(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { String sessionId = session.getId(); // 存储 WebSocketSessionRedis,key 为 sessionId,value 为 WebSocketSession redisTemplate.opsForValue().set(sessionId, session); // 设置过期时间,例如设置为 1 小时 redisTemplate.expire(sessionId, 1, TimeUnit.HOURS); // 处理逻辑 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { String sessionId = session.getId(); // 从 Redis 移除对应的 WebSocketSession redisTemplate.delete(sessionId); // 处理逻辑 } // 其他 WebSocket 处理方法... } ``` 在上述代码,我们注入了一个 RedisTemplate<String, Object> 对象,用于操作 Redis。在 `afterConnectionEstablished` 方法,我们将 WebSocketSession 存储到 Redis ,使用 WebSocketSession 的 `getId()` 方法作为 Redis 的 key,将 WebSocketSession 对象作为 value。 在 `afterConnectionClosed` 方法,我们从 Redis 移除已关闭的 WebSocketSession。 通过这种方式,你可以在不同的服务器或应用实例之间共享 WebSocketSession,并实现分布式的 WebSocket 会话管理。请确保在使用 Redis 存储 WebSocketSession 时,对于存储和删除操作都进行适当的异常处理和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值