Process Erlang监视多个进程

Process Erlang监视多个进程,process,erlang,monitor,Process,Erlang,Monitor,我需要监视一组工作进程。目前我可以通过一个监视器监视一个进程。如何将其扩展到监视N个工作进程。我也需要生成N个监视器吗?如果是这样,那么如果其中一个生成的监视器出现故障/崩溃会发生什么情况?不要生成监视器,然后再使用监视器,这在过去会导致生产问题,请改用 您可以从您的主管处启动和监视多个进程,如果您查看上的文档,您会注意到,每次监视的进程死亡时,它都会发送如下消息: {'DOWN', MonitorRef, Type, Object, Info} 监控刚刚死亡的流程的主管流程 然后您可以决定要

我需要监视一组工作进程。目前我可以通过一个监视器监视一个进程。如何将其扩展到监视N个工作进程。我也需要生成N个监视器吗?如果是这样,那么如果其中一个生成的监视器出现故障/崩溃会发生什么情况?

不要生成监视器,然后再使用监视器,这在过去会导致生产问题,请改用

您可以从您的主管处启动和监视多个进程,如果您查看上的文档,您会注意到,每次监视的进程死亡时,它都会发送如下消息:

{'DOWN', MonitorRef, Type, Object, Info}
监控刚刚死亡的流程的主管流程

然后您可以决定要做什么,monitoref是您开始监视进程时得到的引用,Object将具有已终止进程的Pid,如果您为其分配了名称,则为其注册的名称

使用monitor创建一些示例代码是一个很好的练习,但是尝试使用OTP库和OTP管理器

我也需要生成N个监视器吗

否:

如果是这样的话,那么如果其中一个生成的监视器出现故障/崩溃,会发生什么情况

Erlang在不同的国家拥有多个服务器场,并且Erlang已经收购了多个冗余电网,因此elrang将在一个永远不会出现故障的容错分布式系统中重新启动所有设备。都是内置的。你不必担心任何事情。:)

事实上…在任何你能想象到某个故障的地方,都必须对其进行备份,例如,通过另一台计算机上的另一个监视进程进行备份。

不要生成然后监视--我已经完成了,监视进程仍然会收到“退出”消息--这与
link()
不同。出于历史原因,存在“生成监视器”,为了避免在进程在被监视之前死亡时出现错误,这不是经常发生的,事实上,如果你监视一个死进程,你会收到一条消息,但是当你自己学习创建管理器时,一个好的做法是使用spawn_monitor而不是spawn,然后使用monitor来避免进程在被监视之前死亡时出现错误,--据我所知,这没有什么区别。我理解为什么添加了
spawn\u link()
,但是
monitor()
似乎没有遇到同样的问题。
-module(mo).
-compile(export_all).

worker(Id) ->
    timer:sleep(1000 * rand:uniform(5)),
    io:format("Worker~w: I'm still alive~n", [Id]),
    worker(Id).

create_workers(N) ->
    Workers = [  % { {Pid, Ref}, Id }
        { spawn_monitor(?MODULE, worker, [Id]), Id }
        || Id <- lists:seq(1, N)
    ],
    monitor_workers(Workers).

monitor_workers(Workers) ->
    receive
        {'DOWN', Ref, process, Pid, Why} ->
            Worker = {Pid, Ref},
            case is_my_worker(Worker, Workers) of
                true  ->  
                    NewWorkers = replace_worker(Worker, Workers, Why),
                    io:format("Old Workers:~n~p~n", [Workers]),
                    io:format("New Workers:~n~p~n", [NewWorkers]),
                    monitor_workers(NewWorkers);
                false -> 
                    monitor_workers(Workers)
            end;
        _Other -> 
            monitor_workers(Workers)
    end.

is_my_worker(Worker, Workers) ->
    lists:keymember(Worker, 1, Workers).

replace_worker(Worker, Workers, Why) ->
    {{Pid, _}, Id} = lists:keyfind(Worker, 1, Workers),
    io:format("Worker~w (~w) went down: ~s~n", [Id, Pid, Why]),
    NewWorkers = lists:keydelete(Worker, 1, Workers),
    NewWorker = spawn_monitor(?MODULE, worker, [Id]),
    [{NewWorker, Id}|NewWorkers].

start() ->
    observer:start(),  %%In the Processes tab, you can right click on a worker and kill it.
    create_workers(4).
$ ./run
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V8.2  (abort with ^G)


1> Worker3: I'm still alive
Worker1: I'm still alive
Worker2: I'm still alive
Worker4: I'm still alive
Worker3: I'm still alive
Worker1: I'm still alive
Worker4: I'm still alive
Worker2: I'm still alive
Worker3: I'm still alive
Worker1: I'm still alive
Worker4: I'm still alive
Worker3 (<0.87.0>) went down: killed
Old Workers:
[{{<0.85.0>,#Ref<0.0.4.292>},1},
 {{<0.86.0>,#Ref<0.0.4.293>},2},
 {{<0.87.0>,#Ref<0.0.4.294>},3},
 {{<0.88.0>,#Ref<0.0.4.295>},4}]
New Workers:
[{{<0.2386.0>,#Ref<0.0.1.416>},3},
 {{<0.85.0>,#Ref<0.0.4.292>},1},
 {{<0.86.0>,#Ref<0.0.4.293>},2},
 {{<0.88.0>,#Ref<0.0.4.295>},4}]
Worker2: I'm still alive
Worker1: I'm still alive
Worker2: I'm still alive
Worker1: I'm still alive
Worker1: I'm still alive
Worker4: I'm still alive
Worker3: I'm still alive
Worker2: I'm still alive
Worker1: I'm still alive
Worker3: I'm still alive
Worker4: I'm still alive
Worker1: I'm still alive
Worker4 (<0.88.0>) went down: killed
Old Workers:
[{{<0.2386.0>,#Ref<0.0.1.416>},3},
 {{<0.85.0>,#Ref<0.0.4.292>},1},
 {{<0.86.0>,#Ref<0.0.4.293>},2},
 {{<0.88.0>,#Ref<0.0.4.295>},4}]
New Workers:
[{{<0.5322.0>,#Ref<0.0.1.9248>},4},
 {{<0.2386.0>,#Ref<0.0.1.416>},3},
 {{<0.85.0>,#Ref<0.0.4.292>},1},
 {{<0.86.0>,#Ref<0.0.4.293>},2}]
Worker3: I'm still alive
Worker2: I'm still alive
Worker4: I'm still alive
Worker1: I'm still alive
Worker3: I'm still alive
Worker3: I'm still alive
Worker2: I'm still alive
Worker1 (<0.85.0>) went down: killed
Old Workers:
[{{<0.5322.0>,#Ref<0.0.1.9248>},4},
 {{<0.2386.0>,#Ref<0.0.1.416>},3},
 {{<0.85.0>,#Ref<0.0.4.292>},1},
 {{<0.86.0>,#Ref<0.0.4.293>},2}]
New Workers:
[{{<0.5710.0>,#Ref<0.0.1.10430>},1},
 {{<0.5322.0>,#Ref<0.0.1.9248>},4},
 {{<0.2386.0>,#Ref<0.0.1.416>},3},
 {{<0.86.0>,#Ref<0.0.4.293>},2}]
Worker2: I'm still alive
Worker3: I'm still alive
Worker4: I'm still alive
Worker3: I'm still alive
-module(mo).
-compile(export_all).

worker(Id) ->
    timer:sleep(1000 * rand:uniform(5)),
    io:format("Worker~w: I'm still alive~n", [Id]),
    worker(Id).

create_workers(N) ->
    Workers = [  % { {Pid, Ref}, Id }
        { spawn_monitor(?MODULE, worker, [Id]), Id }
        || Id <- lists:seq(1,N)
    ],
    monitor_workers(Workers).

monitor_workers(Workers) ->
    receive
        {'DOWN', Ref, process, Pid, Why} ->
            CrashedWorker = {Pid, Ref},
            NewWorkers = replace(CrashedWorker, Workers, Why),
            io:format("Old Workers:~n~p~n", [Workers]),
            io:format("New Workers:~n~p~n", [NewWorkers]),
            monitor_workers(NewWorkers);
        _Other -> 
            monitor_workers(Workers)
    end.

replace(CrashedWorker, Workers, Why) ->
    lists:map(fun(PidRefId) ->
                      { {Pid,_Ref}=Worker, Id} = PidRefId,
                      case Worker =:= CrashedWorker of
                          true ->  %replace worker
                              io:format("Worker~w (~w) went down: ~s~n", 
                                        [Id, Pid, Why]),
                              {spawn_monitor(?MODULE, worker, [Id]), Id}; %=> { {Pid,Ref}, Id }
                          false ->  %leave worker alone
                              PidRefId  
                      end
              end,
              Workers).

start() ->
    observer:start(),  %%In the Processes tab, you can right click on a worker and kill it.
    create_workers(4).