我正在运行一个查询,并使用Postgrex将结果加载到Stream中,如下所示:
{:ok, host_pid} = Postgrex.start_link(hostname: "somewhere.hostname.io", username: "myuser", password: "mypass", database: "mydb")
Postgrex.transaction(host_pid, fn(conn) ->
# do query that takes 5 seconds
# with timeout set to be really big
query = Postgrex.prepare!(conn, "", "SELECT pg_sleep(5)", timeout: 50_000)
stream = Postgrex.stream(conn, query)
result_to_iodata = fn(%Postgrex.Result{rows: rows}) -> format_query_result(rows) end
Enum.into(stream, File.stream!("eg"), result_to_iodata)
end)
但是出现以下错误:
localhost$ mix run lib/MyPostgrexScript.exs
** (DBConnection.ConnectionError) connection not available and request was dropped
from queue after 2950ms. You can configure how long requests wait in the queue
using :queue_target and :queue_interval. See DBConnection.start_link/2 for more information
(db_connection) lib/db_connection.ex:836: DBConnection.transaction/3
lib/MyPostgrexScript.exs:3: MyPostgrexModule.sleep/0
(elixir) lib/code.ex:767: Code.require_file/2
(mix) lib/mix/tasks/run.ex:147: Mix.Tasks.Run.run/5
由于我要执行繁琐的查询,因此运行肯定需要2950毫秒以上的时间,所以我想知道如何配置Postgrex以使查询花费更多时间。我在https://hexdocs.pm/postgrex/Postgrex.html#transaction/3读到有关:timeout
选项的信息,但不确定如何包含它,或者我是否在寻找它。
非常感谢任何指导,谢谢!
答案 0 :(得分:0)
我在以下位置了解了:timeout选项 https://hexdocs.pm/postgrex/Postgrex.html#transaction/3,但我不是 一定要包含它,
赞(参见最后一行):
Postgrex.transaction(
host_pid,
fn(conn) ->
# do query that takes 5 seconds
# with timeout set to be really big
query = Postgrex.prepare!(conn, "", "SELECT pg_sleep(5)", timeout: 50_000)
stream = Postgrex.stream(conn, query)
result_to_iodata = fn(%Postgrex.Result{rows: rows}) ->
format_query_result(rows)
end
Enum.into(stream, File.stream!("eg"), result_to_iodata)
end,
timeout: 30_000 #30 seconds
)
每当Elixir文档定义这样的函数时:
func_name(arg1, ...argN, opts \\ [] )
opts
是一个关键字列表,例如:
[{:a, 1}, {:b, 2}]
但是,如果关键字列表是函数调用中的最后一个参数,则可以这样编写关键字列表:
func(arg1, arg2, a: 1, b: 2)
和函数定义将接收三个参数
arg1, arg2, [{:a, 1}, {:b, 2}]
无论如何,:timeout的默认值为:
:timeout - Transaction timeout (default: 15000);
错误提示:
连接不可用,并且请求从队列中删除后 2950ms
因为2950 < 15000
似乎不是:timeout值是错误的根源。
错误消息继续:
连接不可用。 您可以使用以下命令配置请求在队列中等待的时间: :queue_target和:queue_interval。请参阅DBConnection.start_link / 2以了解 更多信息
This说明了如何配置这些超时:
在
config/<env>.exs
(其中<env>
是开发,测试或生产)中:config :my_app, MyApp.Repo, adapter: Ecto.Adapters.Postgres, pool_size: 10, migration_timestamps: [type: :utc_datetime_usec], migration_lock: nil, queue_target: 5000
由于错误数量增加,我们最近要做的是 生产。
Also,
处理请求是通过队列完成的。当DBConnection是 开始时,有两个相关的选项可控制队列:
:queue_target in milliseconds, defaults to 50ms :queue_interval in milliseconds, defaults to 1000ms
我们的目标是最多等待:queue_target建立连接。我摔倒 :queue_interval期间签出的连接所花费的时间超过 :queue_target,然后我们将:queue_target加倍。如果退房 连接所需的时间比新目标要长,然后我们开始删除 消息。
例如,默认情况下,我们的目标是50ms。如果所有连接 结帐时间超过50毫秒,整整一秒,我们将 定位到100毫秒,如果结账时间到了,我们就开始丢弃消息 超过新的限制。
这可以让我们更好地计划超载,因为我们可以拒绝请求 在将它们发送到数据库之前,否则会增加 数据库的负担,使过载变得更糟。
但是,如果您还没有碰到这些默认值,那么我想知道为什么您会看到
错误消息中的2950ms
,而不是接近50ms或1000ms的时间。