【问题标题】:How to catch Memory Quota exceptions in a heroku worker如何在 Heroku 工作者中捕获内存配额异常
【发布时间】:2011-12-30 01:42:45
【问题描述】:

我正在使用delayed_job 通过heroku 处理我的后台作业。有时我会超出我的内存分配,我会得到类似的东西:

2011-11-16T02:41:25+00:00 heroku[worker.1]:错误 R14(超出内存配额) 2011-11-16T02:41:45+00:00 heroku[worker.1]: 进程运行 mem=542M(106.0%)

我想优雅地处理这个问题。有没有办法知道我什么时候会超过我的内存限制?

rack-timeout 这样的东西会很棒

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby exception-handling heroku


    【解决方案1】:

    我想我找到了一个很好的解决方案,方法是从Oink gem 中窃取一些代码。特别是这个文件:memory_snapshot.rb,你应该阅读它。它概述了 4 种不同的方法来混淆内存使用

    所以没有办法在机架级别进行此操作,您需要在导致内存问题的过程中添加内存检查(在我的情况下,它正在构建一个 csv 文件)。

    所以在那个循环中它看起来像:

      def build_string_io(collection)
        csv_io = StringIO.new
        csv_io << collection.first.to_comma_headers.join(',') + "\n"
        collection.each do |imp|
          csv_io << imp.to_comma.join(',') + "\n"
          check_memory!
        end
        csv_io.rewind
        csv_io
      end
    
      def check_memory!
        raise 'AboutToRunOutOfMemory' if memory > 400.megabytes #Or whatever size your worried about
      end
    
    
      # Taken from Oink
      def memory
         pages = File.read("/proc/self/statm")
         pages.to_i * self.class.statm_page_size
      end
    
      def self.statm_page_size
          @statm_page_size ||= begin
          sys_call = SystemCall.execute("getconf PAGESIZE")
          if sys_call.success?
            sys_call.stdout.strip.to_i / 1024
          else
            4
          end
        end
      end
    

    【讨论】:

    • 出于好奇,您如何处理 R14 错误?您是否正在使用GC 清除内存?您要开始新员工了吗?
    • 在我的情况下,当我接近我的内存限制时,我可以截断我的 csv 文件。但如果我不能这样做——我想我会翻阅收藏。希望我可以避免使用 GC。好奇你最终是如何解决它的。
    • 我能想到的唯一方法是解雇一个新的工人并终止当前的工人。你是什​​么意思“通过集合页面”?
    【解决方案2】:

    您遇到的问题是您需要只能从日志中获得的数据。

    这里最好的方法是使用 syslog drain 将您的日志发送到 Papertrailapp.com 或 Loggly 等服务 - 使用这些服务,您可以设置搜索 R14 错误,然后接收通知 - Papertrail 支持篝火、帖子,电子邮件等,您可以在其中处理错误。

    我们将这个确切的过程发布到同样托管在 Heroku 上的 sinatra 应用程序中,我们正在查看 heroku 路由器日志条目和 queue= 大小或积压太深的错误,然后在需要时自动扩展我们的应用程序 - 因为系统日志几乎是实时的,我们的应用基本上是自我感知的。

    【讨论】:

      【解决方案3】:

      您遇到的问题是,当您收到此错误时,您已经被排除在 Ruby 进程之外,而 Heroku 平台正在处理该错误。再多的开始、救援、结束都无法帮助您。

      就看到它的到来而言,您可以通过运行以下命令来查看可用内存量:

      memory = `free -m`
      

      然后您可以解析这些结果以获得有意义的记忆状态。但是,我不确定您可以用这些信息做什么。

      (请记住,测功机只是一个 unix 盒子,您可以通过将命令包装在反引号中来使用 Ruby 运行任意系统命令)

      【讨论】:

        【解决方案4】:

        我使用了这个系统调用,想法来自这个脚本 memory_snapsot.rb 来自 oink gem:

        system("ps -o vsz= -p #{$$}")

        通过这种方式,您可能会对内存增加以及可以在代码中产生的位置有所了解

        【讨论】:

          猜你喜欢
          • 2015-12-08
          • 1970-01-01
          • 2011-12-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-10
          • 1970-01-01
          • 2012-03-16
          相关资源
          最近更新 更多