zoukankan      html  css  js  c++  java
  • [Erlang33]使用recon从网页查看Erlang运行状态

    0.需求分析

    Erlang最好的卖点之一就是提供了一个非常强大的shell来查看Node运行时的各种状态,可以进行各种各样的内部查看,在运行时调试和分析,热更新代码。
     
    但是总有一些在生产环境下要慎用的状态查看函数。比如:
    1.在进程数达到10w级以上的Node调用erlang:processes()来得到所有的进程Pid.然后算长度blabla...;
    2. 当某个进程的信箱被堵塞了上万个消息队列时调用erlang:process_info(Pid,messages)来查看所有的消息。
    为了避免在shell中进行这些危险的操作,就有了recon这个项目。它保证在生产环境下可以调用安全。
    项目地址github:recon,     文档可见:fred
     
    Erlang in anger食用更佳。
    然而在体会到一段时间的recon的强大之后,突然感觉为了查看状态每次检查时都要在shell中输入相同的命令集是一件非常枯燥的事情,于是就想要一个可以直接用网页直接查看状态的工具。并且加上图表显示。让分析问题变得更加快速,易懂。
    recon_web是一个可以通过web 查看Eralng节点各种状态的工具。
    它与observer的区别:
    recon_web observer
    web页面查看,不需求wx GUI 需要Erlang安装wx GUI application
    保证可以在生产环境中被安全调用 如果对于ets非常多或进程达到一定数量时会崩溃掉,不适合大多数在Node已出状况时使用

    1. 项目介绍

    项目地址github:recon_web.
    使用的框架:
    cowboy 1.0.1 websocket 用于server通信
    recon   用于查看Node状态
    jsx   用于json转换
    lager   日志记录
    socket.io.client  web端的websocket维护
    highcharts web端绘制图表
       
     
    上手也非常简单,make&&make shell然后打开127.0.0.1:8080就可以看到效果啦,还不快来试试~。其它命令详见Readme。
     

    2.recon_web 实现

    说明:
    2.1.为什么要分成system_info 和recon_info?
      system_info是指Node中基本不会变化的那些指标:
      
      因为他们基本不会变化,所以只会在连接建立时传一次就行了。
      recon_info是用recon得到的Memory, Scheduler, Port的情况,它们会一直变化,所以在每个Heartbeat都会更新一次给Client.
     
    2.2. 如果大量的(比如1000个)连接上来查看。每个连接的心跳都会去用recon得到新的Node信息,会不会造成CPU在这上面消耗过多?
      这就是recon_server的职责,它是一个独立的gen_server,存着上次使用recon计算出的Node信息和计算时间:
      {ReconInfo, LastUpdateTime}.每个连接上来的点都会向recon_server请求ReconInfo,如果Now - LastUpdateTime >
      规则的时间就会重新计算一份ReconInfo存起来。所以大量的连接在同时请求ReconInfo,recon_server也只会计算一次。
     
    2.3.为什么不直接使用handler 同步call recon_server得到recon_info,然后回传给Client?
      现在实现是:
      2.3.1 handler 同步call session_gen_server ;
      2.3.2 session_gen_server再异步info recon_server;
      2.3.3 recon_server再异步info recon_info 给session_gen_server,
      2.3.4 session_gen_server得到recon_info后异步info handler有新的消息在我这,你快来取;
      2.3.5 handller得知3.4后,再同步call session_gen_server拿到recon_info,然后encode 通过websocket发给Client.
     
      这种方式就是多了session_gen_server这个中间缓冲层。
      好处是:可以把要传给client的多条消息都缓冲在这里,然后一次性发给Client。
      当然对于现在只有recon_info这一种消息来说,没有什么优势。可是考虑到扩展性(那些不需要及时发给Client的消息),加个缓冲层明显是好得多。 
     

    3. recon_web中各种图表说明 

    1> recon_web_status:get_recon_info(node_stats_list).
    [{process_summary,[{process_count,86},
                       {run_queue,0},
                       {error_logger_queue_len,0},
                       {memory_total,20032952},
                       {memory_procs,6067544},
                       {memory_atoms,330312},
                       {memory_bin,467040},
                       {memory_ets,465936}]},
     {mem_summary,[{bytes_in,0},
                   {bytes_out,0},
                   {gc_count,2},
                   {gc_words_reclaimed,256},
                   {reductions,130454},
                   {scheduler_usage,[{1,0.9252873563218391},
                                     {2,0.147239263803681},
                                     {3,0.13218390804597702},
                                     {4,0.14285714285714285}]}]}]

    3.1. 根据 error_logger_queue_len process_count run_queue绘制以下表:

    3.2. 根据上面的memory_total,memory_procs,memory_atoms,memory_bin,memory_ets绘制:

    3. 3.根据scheduler_usage绘制:

    3.4 根据bytes_in,bytes_out绘制:

    2> recon_web_status:get_recon_info(proc_count).
    [{proc_count,[{memory,[{<<"application_controller">>,602096},
                           {<<"0.26.0">>,372368},
                           {<<"recon_server">>,372328},
                           {<<"code_server">>,284656},
                           {<<"kernel_sup">>,197384},
                           {<<"0.159.0">>,88632},
                           {<<"erl_prim_loader">>,88552},
                           {<<"error_logger">>,75904},
                           {<<"init">>,67896},
                           {<<"0.45.0">>,55064}]},
                  {bin_memory,[{<<"kernel_sup">>,396661},
                               {<<"erl_prim_loader">>,27958},
                               {<<"0.26.0">>,7408},
                               {<<"0.159.0">>,5527},
                               {<<"0.45.0">>,1264},
                               {<<"application_controller">>,947},
                               {<<"user">>,852},
                               {<<"recon_server">>,454},
                               {<<"lager_event">>,278},
                               {<<"cowboy_clock">>,203}]},
                  {reductions,[{<<"recon_server">>,43125661},
                               {<<"erl_prim_loader">>,1328265},
                               {<<"0.159.0">>,243664},
                               {<<"code_server">>,196114},
                               {<<"application_controller">>,56899},
                               {<<"timer_server">>,53145},
                               {<<"kernel_sup">>,48774},
                               {<<"cowboy_clock">>,30740},
                               {<<"file_server_2">>,24547},
                               {<<"init">>,17949}]},
                  {total_heap_size,[{<<"application_controller">>,75112},
                                    {<<"recon_server">>,46421},
                                    {<<"0.26.0">>,46421},
                                    {<<"code_server">>,35462},
                                    {<<"kernel_sup">>,24503},
                                    {<<"0.159.0">>,10958},
                                    {<<"erl_prim_loader">>,10957},
                                    {<<"error_logger">>,9358},
                                    {<<"init">>,8370},
                                    {<<"0.45.0">>,6771}]}]}]

    3.5根据上面的memory, bin_memory,reductions, total_heap_size绘制:

    3> recon_web_status:get_recon_info(port).
    [{port_summary,[{<<"efile">>,5},
                    {<<"tcp_inet">>,2},
                    {<<"2/2">>,1},
                    {<<"tty_sl -c -e">>,1}]}]

    3.6.根据 port_summary绘制:

    4> recon_web_status:get_recon_info(inet_count).
    [{inet_count,[{sent_oct,[]},
                  {recv_oct,[{<<"Port0.4012">>,1205},{<<"Port0.3695">>,0}]},
                  {sent_cnt,[]},
                  {recv_cnt,[{<<"Port0.4012">>,72},{<<"Port0.3695">>,0}]}]}]

    3. 7.根据sent_oct, recv_oct, sent_cnt, recv_cnt绘制:

    5>recon_web_status:get_recon_info(alloc_memory).
    [{used,20804344},
     {allocated,32247216},
     {unused,11269856},
     {allocated_types,[{binary_alloc,2786160},
                       {driver_alloc,164720},
                       {eheap_alloc,6763376},
                       {ets_alloc,1475440},
                       {fix_alloc,426864},
                       {ll_alloc,19923784},
                       {sl_alloc,164720},
                       {std_alloc,934768},
                       {temp_alloc,655960}]},
     {allocated_instances,[{0,9094640},
                           {1,6305264},
                           {2,1246704},
                           {3,15664624},
                           {4,984560}]}]

    3.8根据alloc_memory绘制:

    6> recon_web_status:get_recon_info(cache_hit_rates).
    [{cache_hit_rates,[{<<"instance1">>,[602,1113]},
                       {<<"instance3">>,[148,213]},
                       {<<"instance0">>,"OV"},
                       {<<"instance2">>,[7,13]},
                       {<<"instance4">>,[0,0]}]}]

    3.9 根据cache_hit_rates绘制:

    4. 参考文档

    cowboy 建立websocket:http://ninenines.eu/docs/en/cowboy/HEAD/guide/ws_handlers/

    highcharts: http://www.highcharts.com/

     ---------------------------------------------------------------------------------------------------------------------

    inside the beam scheduler 

  • 相关阅读:
    Effective Java 19 Use interfaces only to define types
    Effective Java 18 Prefer interfaces to abstract classes
    Effective Java 17 Design and document for inheritance or else prohibit it
    Effective Java 16 Favor composition over inheritance
    Effective Java 15 Minimize mutability
    Effective Java 14 In public classes, use accessor methods, not public fields
    Effective Java 13 Minimize the accessibility of classes and members
    Effective Java 12 Consider implementing Comparable
    sencha touch SortableList 的使用
    sencha touch dataview 中添加 button 等复杂布局并添加监听事件
  • 原文地址:https://www.cnblogs.com/zhongwencool/p/recon_web.html
Copyright © 2011-2022 走看看