Elixir 我的任务进程似乎无限期地停滞
我正在用Elixir构建一个应用程序,它有一群工作人员(在任何给定时间可能有100-200人)。这些工作人员相互独立操作,他们不是“池”,他们所做的只是将作业从Redis队列中弹出,做一些工作,然后可能将更多作业弹出到队列中(请参见下面的代码) 这些工作人员只是受监督的任务,他们自己调用一个尾部递归函数,该函数要求执行一个作业,如果有,一切正常,如果没有,它将Elixir 我的任务进程似乎无限期地停滞,elixir,otp,erlang-supervisor,Elixir,Otp,Erlang Supervisor,我正在用Elixir构建一个应用程序,它有一群工作人员(在任何给定时间可能有100-200人)。这些工作人员相互独立操作,他们不是“池”,他们所做的只是将作业从Redis队列中弹出,做一些工作,然后可能将更多作业弹出到队列中(请参见下面的代码) 这些工作人员只是受监督的任务,他们自己调用一个尾部递归函数,该函数要求执行一个作业,如果有,一切正常,如果没有,它将:timer.sleep一秒钟,然后再次运行 问题是,这些工人在那里做了一段时间后(完全如预期的那样),他们会逐渐停止这样做 我在《观察家
:timer.sleep
一秒钟,然后再次运行
问题是,这些工人在那里做了一段时间后(完全如预期的那样),他们会逐渐停止这样做
我在《观察家》中看到了它们,我看到了一些有趣的事情:
- 出现错误时,工作人员将按照其
监督策略中的定义重新启动:一对一
- 已重新启动的工人可以通过其显著较高的PID来识别
- 无反应/停滞的工人具有最初分配的相同PID
- 如果我在Observer中手动杀死其中一个工人,它会重新启动并继续工作
观察者说这些暂停的进程正在做什么(“当前功能”列)?当观察者停止工作时,他们的MsgQ/Reds/内存值是否增加?@Dogbert当前函数是
gen:do_call/4
(现在我有一个运行状态,所有工作者都处于“停止”状态),所有工作者的函数相同。它们也都有0个红色,并且随着时间的推移似乎保持相同的内存值(要清楚的是,所有的工作进程都没有相同的内存值)。核心是什么?检查\u domain/1,Utils.insert/3
,和Store.Domains.pop/0
做什么?他们会打GenServer电话吗?所有这些调用都有超时值吗?Core.check\u domain/1
向HTTPoison库(hackney)发出一个HTTP请求,并有条件地向Whois库发出另一个HTTP请求(我知道没有GenServer)Utils.insert/1
使用EXTO向postgres中插入一行,并且Store.Domains.pop/0
通过自滚池机制使用Redix调用Redis(与我的工作人员的工作方式类似,只是随机将调用传递给10个Redix连接中的一个).我几乎排除了Store.Domains.pop/0,因为我有另一种类型的worker,它从不暂停,因为它也调用使用此Redix worker池的函数,并且以完全相同的方式工作,对返回(或未返回)的项进行压缩,只是一个不同的Redis集合。观察家说这些已经停止的进程正在做什么(“当前函数”列)?当观察者停止工作时,他们的MsgQ/Reds/内存值是否增加?@Dogbert当前函数是gen:do_call/4
(现在我有一个运行状态,所有工作者都处于“停止”状态),所有工作者的函数相同。它们也都有0个红色,并且随着时间的推移似乎保持相同的内存值(要清楚的是,所有的工作进程都没有相同的内存值)。核心是什么?检查\u domain/1,Utils.insert/3
,和Store.Domains.pop/0
做什么?他们会打GenServer电话吗?所有这些调用都有超时值吗?Core.check\u domain/1
向HTTPoison库(hackney)发出一个HTTP请求,并有条件地向Whois库发出另一个HTTP请求(我知道没有GenServer)Utils.insert/1
使用EXTO向postgres中插入一行,并且Store.Domains.pop/0
通过自滚池机制使用Redix调用Redis(与我的工作人员的工作方式类似,只是随机将调用传递给10个Redix连接中的一个).我几乎排除了Store.Domains.pop/0,因为我有另一种类型的worker,它从不暂停,因为它也调用使用此Redix worker池的函数,并且以完全相同的方式工作,在返回(或未返回)项上加上大小写,只是一个不同的Redis集。
defmodule Workers.DomainSupervisor do
def start_link do
import Supervisor.Spec, warn: false
children = 1..50 |> Enum.map(fn (i) -> worker(Task, [&Workers.Domain.worker/0], [id: {Workers.Domain, i}]) end)
opts = [strategy: :one_for_one, name: Workers.DomainSupervisor]
Supervisor.start_link(children, opts)
end
end
defmodule Workers.Domain do
def worker do
case Store.Domains.pop do
:empty ->
IO.puts "[Domain] none found, waiting..."
:timer.sleep(1000)
{crawl_id, domain} ->
IO.puts "[Domains] found a domain to check: #{domain}"
case Core.check_domain(domain) do
:error ->
Utils.insert(crawl_id, domain, false)
:registered ->
Utils.insert(crawl_id, domain, false)
:available ->
Utils.insert(crawl_id, domain, true)
end
end
worker()
end
end