Erlang 为什么啤酒要这样设计?

Erlang 为什么啤酒要这样设计?,erlang,otp,Erlang,Otp,我用啤酒时遇到了问题。 在lager源代码中,是lager_backend_throttle.erl文件 handle_event({log, _Message},State) -> {message_queue_len, Len} = erlang:process_info(self(), message_queue_len), case {Len > State#state.hwm, State#state.async} of {true, tru

我用啤酒时遇到了问题。 在lager源代码中,是lager_backend_throttle.erl文件

handle_event({log, _Message},State) ->
    {message_queue_len, Len} = erlang:process_info(self(), message_queue_len),
    case {Len > State#state.hwm, State#state.async} of
        {true, true} ->
            %% need to flip to sync mode
            lager_config:set(async, false),
            {ok, State#state{async=false}};
        {false, false} ->
            %% need to flip to async mode
            lager_config:set(async, true),
            {ok, State#state{async=true}};
        _ ->
            %% nothing needs to change
            {ok, State}
    end;
当消息队列长度超过阈值时,它将切换到同步模式

当消息队列长度小于阈值时,它将切换到异步模式

我认为当有太多的消息时,它应该将模式更改为async以更快地处理消息。为什么啤酒要这样设计


我猜原因是消息队列中存在长度限制,如果消息太多,进程可能会崩溃。因此,通过改变发送模式来降低发送消息的速度?

我在github上找到了答案

在lager 2.0之前,lager核心的gen_事件完全以同步模式运行。异步模式速度更快,但没有防止消息队列过载的保护。在lager 2.0中,gen_事件采用混合方法。它轮询自己的邮箱大小,并根据邮箱大小在同步和异步之间切换消息

{async_阈值,20}, {异步阈值窗口,5} 这将使用异步消息传递,直到邮箱超过20条消息,此时将使用同步消息传递,并在大小减小到20-5=15时切换回异步

如果希望禁用此行为,只需将其设置为“未定义”。它默认为较低的数字,以防止邮箱快速增长超过限制并导致问题。一般来说,淡啤酒处理信息的速度应该与收到信息的速度一样快,因此落后20条应该是相对特殊的

如果要限制每秒允许从error_logger发送的消息数(如果要在大量相关进程崩溃时经受大量消息的冲击,这是一个好主意),可以设置一个限制:

{错误_logger_hwm,50}
最好将这个数字保持在较小的范围内。

只需注意一点。我不相信消息队列(除了系统内存)有限制。@mpm可能,正如他们所说。以便在消息传入时以最快的速度处理消息。所以,如果消息太多,当用户调用lager:notice()时,打印此日志需要很长时间。这不是用户友好的体验。mpm关于消息队列受系统内存限制的说法是正确的。这是监视邮箱的主要原因:如果发送处理消息的速度快于邮箱的处理速度,则邮箱将被填满,Erlang VM将耗尽内存。这将终止整个VM,而不仅仅是您的进程,因此这是一个灾难性的错误。