我正在运行一个执行大量I/O的生产应用程序。每当系统被新请求淹没时(使用witch,我会执行大量IO),我就会看到Erlang file_server正在用消息进行备份。备份/减速可能会持续数小时,具体取决于我们的卷。

据我所知,许多File调用实际上都是通过Erlang file_server进行的。这似乎具有有限的吞吐量。此外,当消息队列被备份时,整个应用程序基本上被冻结(锁定),并且它根本无法处理新的IO请求。
所有IO调用都在使用File模块。我已经在任何允许的地方指定了[:raw]选项。我的理解是,传入:raw将绕过file_server。
这对我们来说是一个非常大的问题,我想其他人在某个时候也会遇到这个问题。我尝试用Ruby witch重写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发布于 2020-10-07 22:17:08
对将来发现这个的人来说。问题的根源在于将File.copy!与路径名一起使用。当您这样做时,副本将通过Erlang file_server,它是导致极难诊断的巨大瓶颈的原因。使用打开的文件作为输入,而不是使用带有路径名的File.copy/1。像这样
source = "path/to/some/file"
destination = "path/to/destination/"
with {:ok, source} <- File.open(source, [:raw, :read]),
{:ok, destination} <- File.open(destination, [:raw, :write]),
{:ok, bytes} <- File.copy(source, destination),
:ok <- File.close(source),
:ok <- File.close(destination) do
{:ok, bytes}
end发布于 2020-05-06 06:52:27
考虑使用async_threads调整虚拟机
https://stackoverflow.com/questions/61599521
复制相似问题