阻止/长期运行凤凰城

时间:2017-03-08 01:18:08

标签: elixir phoenix-framework

我打电话给菲尼克斯航线,其工作往往需要10秒以上。这太长了,菲尼克斯超时了。

这个问题可以通过websockets轻松解决,但我想知道如何使用简单的REST。

什么是凤凰城流程模型?是否所有请求都发送到工作池,只是在游泳池中阻塞很长时间是不明智的?

2 个答案:

答案 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很有趣:)