如果我把你的问题弄错了,我深表歉意。
我可以提出一些建议来指导您朝着正确的方向前进(或者我认为是正确的方向:)
1(相当次要,但仍然很重要)我建议从该工作程序中获取 inets 启动代码并将其放入应用程序状态代码(appname_app.erl)中。据我所知,您正在使用钢筋模板,因此您应该拥有这些模板。
2 现在,到关键部分。为了充分利用 OTP 的监督者模型,假设您要生成大量的爬虫,使用simple_one_for_one监督者而不是one_for_one会很有意义(阅读http://www.erlang. org/doc/man/supervisor.html以获取更多详细信息,但基本部分是: simple_one_for_one - 简化的 one_for_one 主管,其中所有子进程都是动态添加的相同进程类型的实例,即运行相同的代码。)。因此,您实际上将指定一种“模板”,而不是只启动一个进程进行监督——关于如何启动正在执行实际工作的工作进程。这种类型的每个工人都开始使用主管:start_child/2 — http://erldocs.com/R14B01/stdlib/supervisor.html?i=1&search=start_chi#start_child/2。在您明确启动它们之前,这些工人都不会启动。
2.1 根据爬虫的性质,您可能需要评估您的工作人员需要什么样的重启策略。现在,在您的模板中,您已将其设置为永久(但是您有不同类型的受监督孩子)。以下是您的选择:
Restart defines when a terminated child process should be restarted. A permanent child process should always be restarted,
a temporary child process should never be restarted and a transient child process should be restarted only if it terminates
abnormally, i.e. with another exit reason than normal.
所以,你可能想要这样的东西:
-behaviour(supervisor).
-define(CHILD(I, Type, Restart), {I, {I, start_link, []}, Restart, 5000, Type, [I]}).
init(_Args) ->
Children = [
?CHILD(crawler, worker, transient)
],
RestartStrategy = {simple_one_for_one, 0, 1},
{ok, {RestartStrategy, Children}}.
我冒昧地建议这些孩子暂时重新启动,因为这对这类工人有意义(如果他们未能完成工作则重新启动,如果他们正常完成则不要重新启动)
2.2 一旦您处理完上述事项,您的主管将处理任意数量的动态添加的工作进程;它将监视并重新启动(如有必要)它们中的每一个,这大大提高了您的系统稳定性和可管理性。
3 现在,一个工作进程。我会假设每个爬虫都有一些特定的状态,它可能在任何给定的时刻处于。出于这个原因,我建议使用 gen_fsm(有限状态机,有关它们的更多信息,请访问http://learnyousomeerlang.com/finite-state-machines)。这样,您动态添加到主管的每个 gen_fsm 实例都应该在init/1中向自身发送一个事件(使用http://erldocs.com/R14B01/stdlib/gen_fsm.html?i=0&search=send_even#send_event/2)。
仅此而已:
init([Arg1]) ->
gen_fsm:send_event(self(), start),
{ok, initialized, #state{ arg1 = Arg }}.
initialized(start, State) ->
%% do your work
%% and then either switch to next state {next_state, ...
%% or stop the thing: {stop, ...
请注意,您的工作可以包含在此 gen_fsm 进程中,也可以考虑为其生成一个单独的进程,具体取决于您的特定需求。
如果认为有必要,您可能希望为爬网的不同阶段设置多个状态名称。
无论哪种方式,希望这将有助于以某种 OTP 方式设计您的应用程序。如果您有任何问题,请告诉我,如有必要,我很乐意补充。