Genserver Phoenix 问题

Posted

技术标签:

【中文标题】Genserver Phoenix 问题【英文标题】:Genserver Phoenix Issue 【发布时间】:2021-07-26 06:37:06 【问题描述】:

我从一个端点获取数据作为一个列表,假设它们是唯一的 id 我尝试为它们中的每一个启动一个 GenServer 进程,但这些进程在它们启动后立即终止,但错误不清楚,我似乎无法找到正在杀死进程的原因,这是我下面的示例代码和尝试调试的错误。注意(“但是,我可以使用单个事务启动进程”,当我使用 id 调用 Enum.each() 并尝试在命令行中启动 GenServer 时,它可以成功运行)。当列表来自端点时到底发生了什么,因为可以清楚地打印并且进程成功启动但它们也立即终止?。

def new(conn, %"hashes" => [_ | _] = hashes) do
    # Enum.each the list of hashes call hash fn on each hash
    # needs more debugging the function is glitching "some processes failing"
    hashes
    |>Enum.each(fn hash ->  call_hash(conn,hash) end)  #research more queing calls?
  end


  defp call_hash(conn,hash) do
    with :ok, _ <- GenServer.start_link(TransactionSubscriptionHandler, %hash: 
  String.to_atom(hash), name: String.to_atom(hash))
        #  :ok, %status: 200 <- BlockNative.subscribe_transaction(hash)
         do
         json(conn,%status: "Ok")
        else
     _ -> conn |> put_status(400) |> json(%status: "Failed")
  end

  end

输入

"hashes": [
        "0x04b08ab13d51613975cd5035cebb52d5f574137c42902a5b1147f953f1895c6a",
        "0x2285dfeafe2eae5846fe66bd9631f2d258c1d5b32702649153c9073a3a4ec8ad"
    ]

命令行输出

[info] POST /api/transaction
[debug] Processing with VhsWeb.TransactionController.new/2
  Parameters: %"hashes" => ["0x04b08ab13d51613975cd5035cebb52d5f574137c42902a5b1147f953f1895c6a", "0x2285dfeafe2eae5846fe66bd9631f2d258c1d5b32702649153c9073a3a4ec8ad"]
  Pipelines: [:api]
:ok, #PID<0.597.0>
[info] Sent 200 in 2ms
:ok, #PID<0.598.0>
[info] Sent 200 in 2ms
[error] Ranch listener VhsWeb.Endpoint.HTTP had connection process started with :cowboy_clear:start_link/4 at #PID<0.594.0> exit with reason: :function_clause, [:cowboy_http, :commands, [:state, #PID<0.471.0>, VhsWeb.Endpoint.HTTP, #Port<0.22>, :ranch_tcp, :undefined, %env: %dispatch: [:_, [], [:_, [], Phoenix.Endpoint.Cowboy2Handler, VhsWeb.Endpoint, []]], stream_handlers: [:cowboy_telemetry_h, :cowboy_stream_h], "", %, 127, 0, 0, 1, 34624, 127, 0, 0, 1, 4000, :undefined, #Reference<0.3145460136.2965635073.81437>, 2, :ps_request_line, 0, :infinity, 1, :done, 100, [:stream, 1, :cowboy_telemetry_h, :state, :cowboy_stream_h, :state, :undefined, VhsWeb.Endpoint.HTTP, #PID<0.595.0>, :undefined, :undefined, :undefined, :undefined, 0, :fin, "", 180, :undefined, ..., #Function<0.122385210/1 in :cowboy_telemetry_h."-fun.metrics_callback/1-">, :undefined, %body_length: 180, cert: :undefined, has_body: true, headers: %"accept" => "*/*", "accept-encoding" => "gzip, deflate, br", "connection" => "keep-alive", "content-length" => "180", "content-type" => "application/json", "host" => "localhost:4000", "postman-token" => "ad48096e-c775-4f82-a860-a4d4b4286c9c", "user-agent" => "PostmanRuntime/7.26.8", host: "localhost", method: "POST", path: "/api/transaction", peer: 127, 0, 0, ..., 34624, pid: #PID<0.594.0>, port: 4000, qs: "", ref: VhsWeb.Endpoint.HTTP, ..., "200 OK", %"cache-control" => "max-age=0, private, must-revalidate", "content-length" => "15", "content-type" => "application/json; charset=utf-8", "date" => "Mon, 03 May 2021 20:41:43 GMT", "server" => "Cowboy", "x-request-id" => "FnupLbYol1vbVZsAAABE", VhsWeb.Endpoint.HTTP, -576460686234141769, :undefined, -576460686234115433, -576460686234115433, -576460686203746015, -576460686203746015, %#PID<0.595.0> => %spawn: -576460686234129902, [], 180, ..., "POST", :"HTTP/1.1", :undefined, :undefined, 0, []], [:child, #PID<0.595.0>, 1, 5000, :undefined], 1, [:response, "200 OK", %"cache-control" => "max-age=0, private, must-revalidate", "content-length" => "15", "content-type" => "application/json; charset=utf-8", "date" => "Mon, 03 May 2021 20:41:43 GMT", "server" => "Cowboy", "x-request-id" => "FnupLbYol1vbVZsAAABE", ["\"", [[] | "status"], "\":", [34, [[] | "Ok"], 34], 125]]], [file: '/home/edwin/dev/phoenix-projects/vhs/deps/cowboy/src/cowboy_http.erl', line: 922], :cowboy_http, :loop, 1, [file: '/home/edwin/dev/phoenix-projects/vhs/deps/cowboy/src/cowboy_http.erl', line: 231], :proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]]

【问题讨论】:

那个牛仔错误很难阅读,但看起来它遇到了未定义的东西。看起来它试图让一个单独的 Web 服务器进程处理列表中的每个项目,这可能会使事情失败,因为我认为 Phoenix 主进程接收传入的消息。您的意图不是启动多个网络服务器,对吧? 是的,我想启动多个 GenServer 进程 【参考方案1】:

许多进程与该问题无关。这是会引发相同错误的简化代码。

def new(conn, _),
  do: ["1", "2"] |> Enum.each(&call_hash(conn, &1))

defp call_hash(conn, _) do
  json(conn, %status: "Ok")
end

也就是说,您正尝试向单个 POST 请求发送许多响应,这显然失败了,因为在发送第一个响应后conn 被终止。

【讨论】:

我如何构造 call_hash 以在第一次调用后返回更新后的 conn,如果发生错误,返回响应但不杀死我的进程 hashes 上使用Enum.reduce_while/3,如果进程尚未启动并且仅在调用json/2 或以任何其他方式返回响应后终止。基本上,json/2 应该从new/2 调用所有对hash_call/2 的调用之后。

以上是关于Genserver Phoenix 问题的主要内容,如果未能解决你的问题,请参考以下文章

Phoenix实践 —— Phoenix SQL常用基本语法总结小记

flink与hbase交互

开源大数据处理系统/工具大全

玩家 1 邀请玩家 2 与凤凰频道玩游戏

每次测试后停止 GenServer

我可以从远程节点调用 GenServer 客户端函数吗?