【问题标题】:Ruby threads not working after upgrading to Rails 5升级到 Rails 5 后 Ruby 线程不工作
【发布时间】:2019-11-28 08:24:02
【问题描述】:

我有一个使用服务的 API,其中我使用 Ruby 线程来减少 API 的响应时间。我尝试使用以下示例共享上下文。它在 Rails 4、ruby 2.2.1 上运行良好

现在,我们已将 rails 升级到 5.2.3 和 ruby​​ 2.6.5。之后服务停止工作。我可以从控制台调用服务,它工作正常。但是通过 API 调用,服务一旦到达 CurrencyConverter.new 就会变得无响应。任何想法可能是什么问题?


class ParallelTest
  def initialize
    puts "Initialized"
  end

  def perform
    # Our sample set of currencies
    currencies = ['ARS','AUD','CAD','CNY','DEM','EUR','GBP','HKD','ILS','INR','USD','XAG','XAU']
# Create an array to keep track of threads
    threads = []

    currencies.each do |currency|
      # Keep track of the child processes as you spawn them
      threads << Thread.new do
        puts currency
        CurrencyConverter.new(currency).print
      end
    end
# Join on the child processes to allow them to finish
    threads.each do |thread|
      thread.join
    end
    { success: true }
  end
end


class CurrencyConverter
  def initialize(params)
    @curr = params
  end

  def print

    puts @curr
  end
end

如果我删除 CurrencyConverter.new(currency),那么一切正常。 CurrencyConverter 是我拥有的一个服务对象。

发现问题 感谢@anothermh 提供此链接 https://guides.rubyonrails.org/threading_and_code_execution.html#wrapping-application-code https://guides.rubyonrails.org/threading_and_code_execution.html#load-interlock

根据博客,当一个线程通过评估适当文件中的类定义来执行自动加载时,重要的是没有其他线程遇到对部分定义常量的引用。

一次只能加载或卸载一个线程,要执行其中任何一项,它必须等到没有其他线程正在运行应用程序代码。如果一个线程正在等待执行加载,它不会阻止其他线程加载(实际上,它们会合作,并在所有恢复一起运行之前依次执行其排队的加载)。

这可以通过允许并发加载来解决。 https://guides.rubyonrails.org/threading_and_code_execution.html#permit-concurrent-loads

Rails.application.executor.wrap do
  urls.each do |currency|
    threads << Thread.new do
        CurrencyConverter.new(currency)
        puts currency
    end
    ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
      threads.map(&:join)
    end
  end
end

感谢大家的宝贵时间,我很感激。

【问题讨论】:

  • 您使用的是什么应用服务器?独角兽,美洲狮,...?
  • @ZedTuX 我正在使用彪马
  • 尝试在线程中添加 Thread.current.abort_on_exception = true 并报告你得到了什么
  • @nPn 服务器没有响应任何内容,也没有打印任何内容。我在 Thread.new 下方添加了 Thread.current.abort_on_exception = true
  • 您也可以尝试在文件顶部添加 Thread.abort_on_exception = true。线程中的异常将导致线程结束但主程序继续运行,所以我认为您在调用 CurrencyConverter.new 时遇到了异常

标签: ruby-on-rails ruby ruby-thread


【解决方案1】:

不要重新发明轮子,而是使用Sidekiq。 ?

来自项目页面:

简单、高效的 Ruby 后台处理。

Sidekiq 使用线程在同一进程中同时处理多个作业。它不需要 Rails,但会与 Rails 紧密集成,让后台处理变得非常简单。

拥有 400 多个贡献者,并且 10k+ 在 Github 上启动,他们构建了一个可靠的并行作业执行流程,可用于生产且易于设置。

看看他们的Getting Started自己看看吧。

【讨论】:

  • 我使用的例子只是为了给出上下文。实际要求不同。我正在创建三个 HTTP 请求并合并每个请求的结果,然后返回结果。由于每个外部请求需要 4-5 秒,因此我使用线程来确保我的 API 的响应时间更短。所以,我不能为此目的使用Sidekiq
  • 我明白了。那么类似的东西呢:gist.github.com/yob/5895100。代码看起来不错,似乎很容易测试。
  • @mukesh4139 你检查过我在上一条评论中给你的建议了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多