Elixir 中 Agent、GenServer 与 ETS 表的使用与对比
1. Agent 与 GenServer 的对比
在 Elixir 中,Agent 是管理状态的一种方式。不过,Agent 的状态可以通过传递给 Agent 函数的匿名函数以任意方式操作,这就使得状态容易意外被破坏。为避免此问题,建议将 Agent 封装在专用模块中,仅通过该模块的函数操作 Agent 进程。例如将 Todo.Server 转换成 Agent 时就是这样做的,新版本的 Todo.Server 仅需 29 行代码,比之前 GenServer 实现的 41 行代码更简短,看起来 Agent 是 GenServer 不错的替代方案。
然而,Agent 无法处理 GenServer 能处理的所有场景,并非总是适用。比如在当前系统中,待办事项缓存中的项目不会过期,这会导致随着用户操作不同的待办事项列表,内存消耗不断增加,最终可能使系统崩溃。为解决这个问题,需要引入待办事项服务器的过期机制,停止闲置一段时间的服务器。
一种实现方式是创建一个清理进程来终止闲置的待办事项服务器,但这种方式会使清理进程成为性能瓶颈,因为每个待办事项服务器每次使用时都要通知清理进程,可能导致该进程无法处理大量消息。更好的方法是让每个待办事项服务器自行决定何时终止,这可以通过 GenServer 实现,但 Agent 无法做到。
在 GenServer 中检测闲置期的一种简单方法是在回调函数返回的元组末尾添加一个整数元素,该整数表示闲置时间,超过这个时间后会向 GenServer 进程发送超时消息。例如:
超级会员免费看
订阅专栏 解锁全文
64

被折叠的 条评论
为什么被折叠?



