Erlang应用系统内部状态监控

来源:互联网 发布:人类男捏脸具体数据 编辑:程序博客网 时间:2024/05/29 06:49
开发一个基于Erlang/OTP的应用系统,实际上是构建了一个由几十万甚至上百万的erlang进程构成的一个actor系统。
系统的内部健康状态完全可以由内部的进程状态来体现。
一般关心的进程状态有:内存占用、消息队列大小、执行归约数reduction等等。

attach到一个启动的erlang节点的命令:
erl -sname node_1 -remsh node_2@other_host

这样就直接接入了node_2节点的内部了,想看啥就看啥。


etop工具:
    etop类似linux的top工具,可以看到系统内部的一些状态情况。etop是扫描erlang系统内部所有进程的状态。
详见:http://www.erlang.org/doc/man/etop.html#help-0
简单示例:
etop:start([{output,text}]).


图中可以看到按照归约数排序的进程状态情况。也可以现在其他排序:

spawn(fun() -> etop:start([{output, text}, {interval, 2}, {lines, 30}, {sort, reductions}]) end).

 

spawn(fun() -> etop:start([{output, text}, {interval, 2}, {lines, 30}, {sort, memory }]) end).


spawn(fun() -> etop:start([{output, text}, {interval, 2}, {lines, 30}, {sort, msg_q  }]) end). 


Sort: Value: runtime | reductions | memory | msg_q 


一般根据消息队列、进程归约数、内存占用等排序情况就可以找到资源消耗较大的进程,然后重点关注。


需要指出的是,etop是一个单进程的扫描,即产生一个任务进程,其扫描所有的系统中的进程,然后进行排序。

如果系统中有几十万,甚至上百万的进程,则这样的etop扫描进程会直接拖挂整体系统。

因为erlang是公平调度系统,如果一个进程的任务太重会强占其他进程的归约数,导致其他进程被连累,形成恶性循环。


因此需要将etop改造成多进程的方式来扫描整体系统,代码如下:

sort(List) ->

  SubList = lists:sublist(List, 20000),

  case length(SubList) > 0 of

    false ->

      exit(normal);

    true ->

      spawn(fun() ->

        Sort = fun({_A, Sa}, {_B, Sb}) ->

          Sa > Sb

        end,

        R = lists:sort(Sort, SubList),

        io:format("\n~p,sort:~p\n", [self(), lists:sublist(R, 4)]),

        exit(normal)

      end)

  end,

  case length(List) > 20000 of

    true ->

      sort(lists:nthtail(20001, List));

    false ->

      ok

  end.


sort_memory() ->

  Pids = [{P, Size} || P <- erlang:processes(), {memory, Size} <- [erlang:process_info(P, memory)]],

  sort(Pids),

  io:format("pid:~p", [self()]).


sort_reduction() ->

  Pids = [{P, Size} || P <- erlang:processes(), {reductions, Size} <- [erlang:process_info(P, reductions)]],

  sort(Pids),

  io:format("pid:~p", [self()]).


sort_msg_queue() ->

  Pids = [{P, Size} || P <- erlang:processes(), {message_queue_len, Size} <- [erlang:process_info(P, message_queue_len)]],

  sort(Pids),

  io:format("pid:~p", [self()]).


0 0
原创粉丝点击