【发布时间】:2019-12-16 23:34:13
【问题描述】:
我目前正在努力解决这个错误,因为我的服务器提供的日志和信息不多。我有一个名为 /stop 的端点(下面提供的代码示例),在返回 :ok 之前我执行了很多代码。所有这些代码都包含在多个函数中,并通过多个文件和服务进行。
离这些函数的结尾不远,我正在写入数据库。我有 3 种不同的插入物。但是几天后,我遇到了这个错误:Postgrex.Protocol (#PID<0.375.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.543.0> exited 随机出现在这 3 个插入中的一个中。 (它可能是第一个,它可能在第二个的中间,或最后一个。有时(很少)它甚至不会失败)。我唯一能够将其隔离为“触发器”的是当插入的数据稍大时。它以前一直有效,当我尝试通过 iex 直接插入相同的数据时,它也很有效。
在 Postgres 方面,我只有这个日志:LOG: unexpected EOF on client connection with an open transaction。
控制器代码如下所示:
def stop(conn, params) do
case @influx_caller.end_connexion_performable?(params) do
true ->
handle_end_of_connexion(params)
conn |> send_resp(:ok, [])
false ->
if @influx_caller.connexion_data_from(params["connexion_key"]) == %{} do
update_connexion_with(:influx_empty, params, true)
end
conn |> send_resp(:forbidden, [])
end
end
end
end
失败发生在由handle_end_of_connexion 函数调用的文件之一中的快乐路径(案例的真正选项)中。例如在这个查询中:
Ecto.Changeset.change(connexion, %{
closed_at: Calculation.get_close_time(events),
})
|> Ecto.Changeset.put_assoc(:infos, MyApp.InfosGenerator.perform(obj, obj_type, twi, twl, events))
|> MyApp.Repo.update
可以从我的应用程序中的另一个控制器(类似于管理面板)调用具有完全相同数据的完全相同的文件,并且它工作得很好。所以我认为我的问题来自 /stop 端点。
到目前为止我测试过的东西:
检查我的 OTP 版本。当时是 21.3,我发现很多报告都在谈论来自它的类似错误,所以我将其更新为 22.1.7
激活
show_sensitive_data_on_connection_error希望它会添加一些日志进行调查,但没有运气。将 phoenix、plug_cowboy、postgrex 和 ecto 更新到最新版本。
在我的 Mix.Config 中添加
http: [protocol_options: [idle_timeout: :infinity]],,因为我还从牛仔 2.0 版本中了解到超时。
这些都不起作用。 (当然,我也尝试在任何地方记录东西,但在本地模式下一切正常)
任何帮助或至少是领导将不胜感激。提前致谢!
[编辑] 感谢观察者,我设法收集了这些附加信息:
当此错误发生时:Postgrex.Protocol (#PID<0.422.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.31212.0> exited,我在观察者中弹出这些行 =>
11:06:52:783159 (<0.31212.0>) out {lists,reverse,1}
11:06:52:783212 (<0.31212.0>) in {lists,reverse,1}
11:06:52:783218 (<0.31212.0>) << {inet_reply,#Port<0.71>,ok}
11:06:52:783234 (<0.31212.0>) out {prim_inet,send_recv_reply,2}
11:06:52:783243 (<0.31212.0>) in {prim_inet,send_recv_reply,2}
11:06:52:783247 (<0.31212.0>) out {prim_inet,recv0,3}
11:06:52:797698 (<0.31209.0>) in {cowboy_http,loop,1}
11:06:52:797725 (<0.31209.0>) << {tcp_closed,#Port<0.140>}
11:06:52:797750 (<0.31209.0>) getting_unlinked #Port<0.140>
11:06:52:797786 (<0.31209.0>) out {cowboy_children,terminate_loop,2}
11:06:52:797794 (<0.31212.0>) in {prim_inet,recv0,3}
11:06:52:797800 (<0.31212.0>) exit shutdown
11:06:52:797820 (<0.31212.0>) out_exited 0
11:06:52:797905 (<0.31209.0>) in {cowboy_children,terminate_loop,2}
11:06:52:797911 (<0.31209.0>) getting_unlinked <0.31212.0>
11:06:52:797915 (<0.31209.0>) << {'EXIT',<0.31212.0>,shutdown}
11:06:52:797943 (<0.31209.0>) exit {shutdown,{socket_error,closed,'The socket has been closed.'}}
11:06:52:797951 (<0.31209.0>) out_exited 0
进程在这里产生:
11:06:52:304313 (<0.31209.0>) spawn <0.31212.0> as proc_lib:init_p(<0.31209.0>,[<0.447.0>,<0.446.0>,'Elixir.Tracking.Endpoint',<0.414.0>,<0.413.0>],cowboy_stream_h,request_process,[#{body_length => 136,cert => undefined,has_body => true, [etc...]
我真的不明白这个过程是什么以及为什么关闭并且链接丢失了:/
【问题讨论】:
-
首先检查数据库的日志,我希望数据库会根据配置终止连接。
-
您使用的是什么版本的
ecto和postgrex? -
我从 db 中找到的唯一日志是:
unexpected EOF on client connection with an open transaction所以我猜 elixir 正在关闭进程,没有任何解释。我正在使用 ecto 3.1.7 和 postgrex 0.14.1。我们发现,如果我们为容器提供更多内存,错误就会更少,因此我们怀疑 Elixir 内存管理存在问题,但仍然不知道发生了什么。 -
你的池大小是多少?它是在配置中设置的。
:pool_size- hexdocs.pm/ecto/3.1.7/Ecto.Repo.html 试着摆弄它。它默认为 10,但如果你增加了,我建议降低它。 -
我的池大小为 10,数据库大小一切正常。这似乎与牛仔有关。我已经能够追踪被杀死的进程,它是当我的端点被调用时由牛仔产生的。它在有时间完成工作之前被杀死。
标签: elixir phoenix-framework ecto