【发布时间】:2009-11-10 00:54:54
【问题描述】:
我正在编写 http 会话管理器(基于 gen_server)。该服务器从内存存储中创建和删除会话。我需要在超时时删除过期的会话。我有两个解决方案:
- 创建一个计时器以从管理器中删除过期会话
- 为每个会话创建计时器
第一个解决方案在未处理所有会话时锁定服务器(锁定问题)。第二种解决方案需要处理每个会话(内存问题)。
问题是哪种解决方案是正确的?
谢谢!
【问题讨论】:
标签: erlang
我正在编写 http 会话管理器(基于 gen_server)。该服务器从内存存储中创建和删除会话。我需要在超时时删除过期的会话。我有两个解决方案:
第一个解决方案在未处理所有会话时锁定服务器(锁定问题)。第二种解决方案需要处理每个会话(内存问题)。
问题是哪种解决方案是正确的?
谢谢!
【问题讨论】:
标签: erlang
使用timer:send_after、timer:exit_after 或timer:kill_after。 timer 模块将 ets 用于存储计时器,而整个 VM 只有一个 gen_server。将计时器引用存储在每个会话记录中,以便计时器重新启动等。这是一个简单而干净的解决方案。
【讨论】:
低频事件应由低频进程 IMO 处理。您不希望在没有“产生”价值的事情上“花费”太多资源。
“清理”活动似乎不需要“锁定”服务器。也许您需要在这一点上进行扩展。
为什么需要在解决方案 #1 中“锁定”某些内容?您在这里有什么顾虑?请详细说明您的疑虑,以便我提供更多建议。
【讨论】:
这就是我在我的宠物“网络框架”中处理会话的方式。
工作进程直接查找现有会话并在 ets 表中创建新会话(无需任何服务器干预)。如果会话已死,工作进程也会在成功查找后检查。如果是这样,它会创建一个新会话,并删除旧会话。由于ets表不需要排序,可以开启写并发。
“会话服务器”的角色是拥有会话表,并时不时地产生一个清理进程。这是一个低优先级进程,它通过 ets:next() 调用遍历 ets 表,并删除过期的会话。
请注意,不涉及计时器。
【讨论】:
只要您没有大量的会话,任何建议的解决方案都不会出错。我的意思是你应该进行基准测试。
定时器模块被实现为一个有序的 ets 表,其中 ets:first 可以有效地找到第一个应该过期的定时器并休眠直到发生。所以通过定时器模块添加几千个定时器是没有问题的。每个会话一个。
如果您有很多会话,那么故障安全设计的问题可能是一个更大的问题。您需要分发您的会话数据库,以便请求可以负载平衡,并且您不会受到任何一台 Web 服务器机器宕机的影响。
这就是我觉得没有功能要求的人可以做到的具体程度。
【讨论】: