我想创建一个类似于此的Elixir代码:
def infinite_loop(created_workers \\ []) do
case next_from_queue do
{:ok, queue_msg} ->
new_worker = Task.async(fn -> crawling(queue_msg) end)
infinite_loop([new_worker | created_workers])
{:error, :empty} ->
created_workers.map(&Task.await/1)
end
end
假设:
crawling
功能会创建另外3个Task
crawling
工作人员可能会花费3秒钟queue
可能有数百万条消息我怎么知道Elixir上并行处理的限制是什么?如何管理它以免中断?
答案 0 :(得分:6)
我建议您使用Task.async_stream
。 Stream.iterate
允许您并行处理流,同时限制并行运行的任务数。虽然Erlang 20中进程数的默认限制为262144,但如果您正在抓取某个网站,则可能需要更低的限制。
您可以使用stream =
Stream.iterate(next_from_queue(), fn _ -> next_from_queue() end)
|> Stream.take_while(fn {:ok, _} -> true; {:error, :empty} -> false end)
{:error, :empty}
由于您希望停留在Stream.take_while
,我们会使用Task.async_stream
停止播放。
然后像这样使用stream
|> Task.async_stream(fn {:ok, queue_msg} ->
crawling(queue_msg)
end, max_concurrency: 16)
:
crawling(queue_msg)
这将并行运行最多16个任务的流。最终结果将是{{1}}的所有返回值的列表。