我正在运行一个生产应用,它需要做大量的IO。每当系统被新的请求所淹没时(我做了大量的IO),我看到Erlang file_server在用消息备份。根据我们的容量,backupslowdown可以持续几个小时。
据我所知,很多 File
调用实际上是通过Erlang file_server进行的。这似乎是有限的吞吐量。此外,当消息队列被备份时,整个应用程序基本上被冻结(锁定),它根本无法处理新的IO请求。
所有的IO调用都在使用 File
模块。我已经指定了 [:raw]
选项的地方都允许它。我的理解是,传入 :raw
会绕过file_server。
这对我们来说是个很大的问题,我想其他人在某些时候也会遇到这个问题。我试着用Ruby重写了IO逻辑,结果吞吐量有了很大的提高(我没有确切的数字,但这是一个明显的差异)。
有谁知道我还可以看看做什么来提高性能吞吐量?
示例代码。
defmodule MyModule.Ingestion.Insertion.Folder do
use MyModule.Poller
alias MyModule.Helpers
def perform() do
Logger.info("#{__MODULE__} starting check")
for path <- paths() do
files = Helpers.Path.list_files(path, ".json")
Task.async_stream(
files,
fn file ->
result =
file
|> File.read!()
|> Jason.decode()
case result do
{:ok, data} ->
file_created_at = Helpers.File.created_time(file)
data = Map.put(data, :file_created_at, file_created_at)
filename = Path.basename(file, ".json")
:ok = MyModule.InsertWorker.enqueue(%{data: data, filename: filename})
destination =
Application.fetch_env!(:my_application, :backups) <> filename <> ".json"
File.copy!(file, destination)
File.rm!(file)
_err ->
nil
end
end,
timeout: 60_000,
max_concurrency: 10
)
|> Stream.run()
end
Logger.info("#{__MODULE__} check finished")
end
def paths() do
path = Application.fetch_env!(:my_application, :lob_path)
[
path <> "postcards/",
path <> "letters/"
]
end
end
考虑用以下方法调整虚拟机 async_threads