如果我误解了你的问题,我很抱歉。
以下是一些建议,可以指导你朝正确的方向前进(或者我认为是正确的方向 :))
1(相对不重要,但仍然重要)我建议将inets启动代码从worker中移出,并将其放入应用程序启动代码(appname_app.erl)中。据我所知,您正在使用rebar模板,因此您应该有这些。
2 现在,进入基本部分。为了充分利用OTP的supervisor模型,假设您想要生成大量的爬虫,则使用simple_one_for_one监督者而不是one_for_one会更有意义(阅读http://www.erlang.org/doc/man/supervisor.html以获取更多详细信息,但基本部分是:simple_one_for_one-简化的one_for_one监督者,其中所有子进程都是同一进程类型的动态添加实例,即运行相同的代码)。因此,您将实际上指定一个“模板”-关于如何启动正在执行真正工作的工作进程。每个这种类型的worker都使用supervisor:start_child/2启动-http://erldocs.com/R14B01/stdlib/supervisor.html?i=1&search=start_chi#start_child/2。在您明确启动它们之前,这些worker都不会启动。
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) ->
请注意,完成工作可以在此gen_fsm进程内部完成,也可以考虑为其生成一个单独的进程,具体取决于您的特定需求。
如果需要,您可能希望为不同阶段的爬行设置多个状态名称。
无论哪种方式,希望这将有助于以某种OTP方式设计您的应用程序。如果您有任何问题,请告诉我,我很乐意添加一些内容。