【问题标题】:why lager design this way?为什么要这样设计?
【发布时间】:2014-08-14 20:12:59
【问题描述】:

我在使用啤酒时遇到了问题。 在 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;

当 message_queue_len 大于 Threshold 时,它会翻转到同步模式。

当message_queue_len小于Thershold时,会转为异步模式。

我认为当消息太多时,应该将模式更改为异步以更快地处理消息。为什么要以这种方式进行大型设计?

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

【问题讨论】:

    标签: erlang erlang-otp


    【解决方案1】:

    我在github上找到了答案。

    在 lager 2.0 之前,lager 核心的 gen_event 纯粹以同步模式运行。异步模式更快,但无法防止消息队列过载。在 lager 2.0 中,gen_event 采用混合方法。它轮询自己的邮箱大小,并根据邮箱大小在同步和异步之间切换消息传递。

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

    如果您希望禁用此行为,只需将其设置为“未定义”。它默认为一个较小的数字,以防止邮箱快速增长超过限制并导致问题。一般来说,lager 应该尽快处理消息,因此落后 20 应该是相对例外的。

    如果您想限制 error_logger 每秒允许的消息数量,如果您想在大量相关进程崩溃时抵御大量消息,这是一个好主意,您可以设置一个限制:

    {error_logger_hwm, 50} 最好保持这个数字很小。

    【讨论】:

    • 只有一个音符。我不相信消息队列有限制(系统内存除外)。
    • @mpm 也许,正如他们所说。为了尽快处理消息。所以如果消息太多,当用户调用 lager:notice() 时,需要很长时间打印此日志。这不是用户友好的体验。
    • mpm 关于消息队列受系统内存限制的说法是正确的。这是监视邮箱的主要原因:如果您发送进程消息的速度超过了它可以处理的速度,则邮箱会填满并且 Erlang VM 会耗尽内存。这会终止整个 VM,而不仅仅是您的进程,因此这是一个灾难性错误。
    猜你喜欢
    • 2012-04-23
    • 1970-01-01
    • 2022-11-13
    • 2012-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多