我打电话给菲尼克斯航线,其工作往往需要10秒以上。这太长了,菲尼克斯超时了。
这个问题可以通过websockets轻松解决,但我想知道如何使用简单的REST。
什么是凤凰城流程模型?是否所有请求都发送到工作池,只是在游泳池中阻塞很长时间是不明智的?
答案 0 :(得分:4)
我想知道它是如何使用简单的REST
完成的
您要么提高代码效率,要么增加网络服务器的超时时间,要么两者兼而有之。
什么是Phoenix流程模型?是否所有请求都发送到工作池
不,请求不会进入工作池。
对于Web服务器,Phoenix目前正在使用cowboy。因此,当您点击Phoenix Endpoint时,它实际上正在触及底层牛仔实现,这将为您的请求生成一个新的Erlang进程。然后由Erlang调度程序实际为您的进程提供CPU时间。
答案 1 :(得分:1)
还有其他一些你可以尝试的东西:启动一个过程来完成繁重的工作并立即返回给客户。分配名称或以其他方式使此任务可被发现。然后经常从客户端轮询以检查该过程是否完成。一旦完成并且你得到结果,你可以杀死它。
轮询是一种解决方法,只有当你真的不能使用套接字时,套接字推送会更有效率,否则
编辑: 好的,这是一个概念证明,它应该指向正确的方向。
首先定义一个模块来封装这种行为
+-----------+-------------+-------------+-------------+
| NAME | MONDAY | TUESDAY | WEDNESDAY |
+-----------+-------------+-------------+-------------+
| John | 8:30 - 17:00| 8:30 - 17:00| 8:30 - 17:00|
+-----------+-------------+-------------+-------------+
| Peter | 8:00 - 16:30| 8:00 - 16:30| 8:00 - 16:30|
+-----------+-------------+-------------+-------------+
| Craig | 9:00 - 17:30| 9:00 - 17:30| 9:00 - 17:30|
+-----------+-------------+-------------+-------------+
| TOTAL | 8:30 | 8:30 | 8:30 |
+-----------+-------------+-------------+-------------+
然后在你的控制器中定义2个动作,触发任务的初始请求和你可以检查完成的轮询终点
defmodule LongRunningTask do
def start(params) do
spawn(fn ->
me = self()
spawn(fn -> do_long_running_task(me, params) end)
wait()
end)
|> inspect()
end
def get_result("#PID" <> ref) do
pid = ref
|> :erlang.binary_to_list
|> :erlang.list_to_pid
send(pid, {:is_it_done_yet?, self()})
receive do
{:answer, result} -> result
:still_not_done -> :still_not_done
after
1000 -> :no_one_here
end
end
defp wait(state \\ nil) do
receive do
{:result, result} -> wait(result)
{:is_it_done_yet?, from} ->
case state do
nil ->
send(from, :still_not_done)
wait(state)
result ->
send(from, {:answer, result})
end
end
end
defp do_long_running_task(pid, _params) do
Process.sleep(10_000)
send(pid, {:result, "the answer"})
end
end
PS:Elixir很有趣:)