我有一个以潜在高速率生成点的数据源,并且我想对每个点执行可能耗时的操作;但我也希望系统在过载时通过删除多余的数据点来优雅地降级。
据我所知,使用 gen_event 永远不会跳过事件。从概念上讲,我希望 gen_event 做的是在再次运行处理程序之前删除除最新待处理事件之外的所有事件。
有没有办法用标准 OTP 来做到这一点?或者我有充分的理由不应该那样处理事情吗?
到目前为止,我最好的方法是使用 gen_server 并依靠超时来触发昂贵的事件:
-behaviour(gen_server).
init() ->
{ok, Pid} = gen_event:start_link(),
{ok, {Pid, none}}.
handle_call({add, H, A},_From,{Pid,Data}) ->
{reply, gen_event:add_handler(Pid,H,A), {Pid,Data}}.
handle_cast(Data,{Pid,_OldData}) ->
{noreply, {Pid,Data,0}}. % set timeout to 0
handle_info(timeout, {Pid,Data}) ->
gen_event:sync_notify(Pid,Data),
{noreply, {Pid,Data}}.
Run Code Online (Sandbox Code Playgroud)
这种做法正确吗?(特别是关于监督?)
小智 0
有没有办法用标准 OTP 来做到这一点?
不。
我有充分的理由不应该那样处理事情吗?
不,提前超时可以提高整个系统的性能。阅读此处了解如何操作。
这种做法正确吗?(特别是关于监督?)
不知道,您还没有提供监管代码。
作为第一个问题的一些额外信息:
如果您可以使用 OTP 之外的第 3 方库,则有一些库可以添加抢占式超时,这正是您所描述的。
有两个我比较熟悉的,第一个是dispcount,第二个是chick(我是chick的作者,我会尽量不在这里给这个项目做广告)。
Dispcount 对于只有有限数量的可同时运行且无需排队的作业的单一资源非常有效。您可以在这里阅读相关内容(警告有很多非常有趣的信息!)。
Dispcount 对我不起作用,因为我必须生成 4000 多个进程池来处理应用程序内不同队列的数量。我写小鸡是因为我需要一种方法来动态增加和减少队列长度,以及能够对请求进行排队并拒绝其他请求,而不必生成 4000 多个进程池。
如果我是你,我会首先尝试discount(因为大多数解决方案不需要chick),然后如果你需要一些更动态的东西,那么可以响应一定数量的请求的池尝试chick。