首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Elixir/Erlang file_server消息积压和不可靠的吞吐量导致性能问题

Elixir/Erlang file_server消息积压和不可靠的吞吐量导致性能问题
EN

Stack Overflow用户
提问于 2020-05-05 02:53:37
回答 2查看 83关注 0票数 2

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

据我所知,许多File调用实际上都是通过Erlang file_server进行的。这似乎具有有限的吞吐量。此外,当消息队列被备份时,整个应用程序基本上被冻结(锁定),并且它根本无法处理新的IO请求。

所有IO调用都在使用File模块。我已经在任何允许的地方指定了[:raw]选项。我的理解是,传入:raw将绕过file_server。

这对我们来说是一个非常大的问题,我想其他人在某个时候也会遇到这个问题。我尝试用Ruby witch重写IO逻辑,结果吞吐量有了很大提高(我没有确切的数字,但这是一个明显的差异)。

有人知道我还可以做些什么来提高性能/吞吐量吗?

示例代码:

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-07 22:17:08

对将来发现这个的人来说。问题的根源在于将File.copy!与路径名一起使用。当您这样做时,副本将通过Erlang file_server,它是导致极难诊断的巨大瓶颈的原因。使用打开的文件作为输入,而不是使用带有路径名的File.copy/1。像这样

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2020-05-06 06:52:27

考虑使用async_threads调整虚拟机

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61599521

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档