我正在编写一个基于gen_server的http会话管理器。该服务器创建并从内存存储中删除会话。我需要在超时时删除过期的会话。我有两个解决方案:
- 创建一个计时器来从管理器中删除过期的会话
- 为每个会话创建一个计时器
第一个解决方案在所有会话未处理完之前锁定服务器(锁问题)。第二个解决方案对于每个会话都需要一个进程(内存问题)。
问题是哪种解决方案是正确的?
谢谢!
我正在编写一个基于gen_server的http会话管理器。该服务器创建并从内存存储中删除会话。我需要在超时时删除过期的会话。我有两个解决方案:
第一个解决方案在所有会话未处理完之前锁定服务器(锁问题)。第二个解决方案对于每个会话都需要一个进程(内存问题)。
问题是哪种解决方案是正确的?
谢谢!
使用 timer:send_after
、timer:exit_after
或者 timer:kill_after
。 timer
模块使用 ets
存储定时器,整个 VM 中只有一个 gen_server
。在每个会话记录中存储定时器引用以便重新启动定时器等操作。这是一个简单而干净的解决方案。
我认为低频事件应该由低频进程处理。您不希望在不“生成”价值的事情上“花费”太多资源。
“清理”活动似乎不需要“锁定”服务器。也许您需要详细阐述这一点。
为什么您在解决方案#1中需要“锁定”某些内容?您在这里有哪些顾虑?请详细说明您的顾虑,以便我能提供更多建议。
这是我在我的“Web框架”中处理会话的方式。
工作进程直接查找现有会话并将新会话创建到ets表中(无需任何服务器干预)。此外,工作进程在成功查找后检查会话是否已过期。如果是,则创建一个新会话并删除旧会话。由于ets表不需要排序,因此可以启用写并发。
“会话服务器”的角色是拥有会话表,并定期生成清理进程。这是一个低优先级进程,通过ets:next()调用遍历ets表并删除过期会话。
请注意,没有涉及计时器。
只要你没有大量的会话,任何建议的解决方案都不会出错。我的意思是你应该进行基准测试。
定时器模块作为有序ETS表实现,可以有效地找到应该过期的第一个定时器并休眠直到发生。因此,通过定时器模块添加许多计时器没有问题。每个会话一个计时器。
如果您有很多会话,则具有故障安全设计的问题可能更大。您需要分发会话数据库以便可以负载平衡请求,并且您不容易受到任何一个Web服务器机器失效的影响。
这就是我在没有功能要求的情况下能够做出的具体建议。