代码之家  ›  专栏  ›  技术社区  ›  BushyMark

张贴一个大的机构崩溃我们的堆栈-但只有在生产模式?

  •  2
  • BushyMark  · 技术社区  · 15 年前

    我们的rails应用程序有两个部署到服务器的环境一个是登台环境,另一个是默认的生产环境。

    staging.rb文件是config/environments文件夹中production.rb的副本。两者的区别在于whiny nils被设置为true:

    config.whiny_nils = true
    

    由于rails应用程序主要用于它的api,因此我们在内部的一个登台服务器上运行它,供开发人员使用。这一做法奏效了,几乎连续4个月毫无进展。当传输到我们的生产服务器时,每当post或put带有一个大(有时非常大)的主体时,堆栈就开始持续崩溃。在两台服务器之间进行测试时,登台服务器完美地处理了相同的请求。

    崩溃的最令人沮丧的部分是缺少日志或跟踪在堆栈(NGIX,PHIVUS乘客,Ruby 1.9补丁级别243,Rails 2.3.4)中发生碰撞的地方。nginx错误日志、rails日志或任何我们可以找到的地方都没有出现。由于我们使用nginx、passenger和ruby的更新版本运行生产服务器(更高的补丁级别然后是staging,但仍然是1.9),我们开始一次一个地还原每个组件,甚至将所有可执行文件和支持文件(基本上是我们在/usr/local中安装的所有文件)传输到生产机器上都没有用。就在我们要擦拭机器并再次尝试每一步时,有人建议将生产机器切换到“暂存”环境。…就像魔法一样,问题解决了!

    想知道是什么可能导致了这个错误,我们开始梳理rails核心、我们自己的代码和所有的插件,寻找一些线索,看看是什么可能在生产环境中导致如此巨大的挂起/崩溃,但还是没有结果。

    我唯一能找到的线索就是行为。当测试“on”应用程序(rails应用程序实际提供的页面之一)时,我会通过发送请求来崩溃该应用程序,然后在频繁刷新(通常是3-4次)之后,我将能够从nginx日志中生成一个错误,最终该应用程序将再次开始处理请求。错误如下:

        Error during failsafe response: incompatible character encodings: UTF-8 and ASCII-8BIT
        2009/10/09 17:52:40 [error] 8691#0: *88 upstream prematurely closed connection while reading response header from upstream, client: *my ip address*, server: myapp.mydomain.com, request: "GET /api/sections/4/edit        HTTP/1.1", upstream: "passenger://unix:/tmp/passenger.8677/master/helper_server.sock:", host: "myapp.mydomain.com"
        *** Exception NoMethodError in application (undefined method `each' for nil:NilClass) (process 8703): from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/rack/request_handler.rb:95:in `process_request'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_request_handler.rb:206:in `main_loop'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/railz/application_spawner.rb:376:in `start_request_handler'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/railz/application_spawner.rb:334:in `block in handle_spawn_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/utils.rb:182:in `safe_fork'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/railz/application_spawner.rb:332:in `handle_spawn_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server.rb:351:in `main_loop'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server.rb:195:in `start_synchronously'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server.rb:162:in `start'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/railz/application_spawner.rb:213:in `start'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/spawn_manager.rb:261:in `block (2 levels) in spawn_rails_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server_collection.rb:126:in `lookup_or_add'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/spawn_manager.rb:255:in `block in spawn_rails_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server_collection.rb:80:in `block in synchronize'
        from :8:in `synchronize'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server_collection.rb:79:in `synchronize'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/spawn_manager.rb:254:in `spawn_rails_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/spawn_manager.rb:153:in `spawn_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/spawn_manager.rb:286:in `handle_spawn_application'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server.rb:351:in `main_loop'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/lib/phusion_passenger/abstract_server.rb:195:in `start_synchronously'
        from /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.4/bin/passenger-spawn-server:61:in `'
    

    通常,当出现字符编码错误时,我的第一个任务是Ruby1.9。…但是,从我的测试中可以看出,这两台机器的版本是一样的!

    在那之后,我想我在想。…有人知道发生了什么事吗?显然,我们可以暂时运行我们的应用程序,但我担心我可能发现了一些更深层次的问题,需要解决。对下一个我应该找的地方有什么想法吗?

    我们的设置: Mac OS X服务器:10.6.1,
    Rails 2.3.4,
    红宝石1.9p243,
    nginx 0.8.17,
    乘客2.2.5

    我们需要的宝石:
    环境.rb
    守护进程
    雷马克
    RB
    RSPEC
    RSPEC轨道
    工厂女工
    齿条试验

    我们安装的插件:
    充当DAG(用于创建定向非循环图的活动记录插件)
    守护程序生成器
    全局化2
    禁止偷窥(测试用)
    思维狮身人面像


    更新(针对khelll):

    我试图添加 config.whiny_nils=真 但对于生产环境,仍然会发生崩溃。

    另外,我返回到我们的登台服务器,并将环境设置为“生产”。…同样的碰撞!

    关于我所说的“大型”请求机构的一些澄清。一个POST /PUT会一致地破坏应用程序,大约是20000个字符(JSON)。由于api在一天中始终使用小的put/post,并且保持在up状态,但是只有在发出这些较大的请求时才崩溃/挂起,所以我假设这两个请求是连接的。

    就Rack/Ruby1.9而言。由于有大量关于rack和1.9的信息,我确实将rack gem升级到了git存储库中的最新版本(据说修复了一些1.9问题)。我已经阅读了关于ReReavabl的输入,Ruby 1.9和更多的AY的大量困难,但是,由于我没有得到我的另一个1.9应用程序所经历的Reunababl输入错误,所以我假设这是一个不同的问题。另外,我在更改rails环境时排除了rack,解决了这个问题(当我搜索rack源代码时,似乎没有任何特定于环境的方法会导致错误)。

    希望这有帮助!


    更新以响应paliephonic

    根本没有任何消息触及rails日志(这实际上促使我在我们的web堆栈中搜索一段时间来解决这个问题)。我认为发生崩溃/挂起的线索是,一旦发出大请求,应用程序只会在每个请求上返回500个错误,但是这500个错误不会显示在rails日志中。

    我们的数据库配置是相同的(我们使用的是MySQL集群),所以它是 字面 完全相同,目前正在使用本地mysql数据库,但已确认无论使用何种数据库都会存在错误)

    就多字节/unicode而言。…我们正在一个国际化的应用程序中工作。…但是我不认为rails处理生产和其他产品之间unicode变化的方式是对的?如上所述,这发生在 POST PUT . 在调试期间我要测试的方法是去 相同的 编辑我的一个大的,重嵌套模型的页面,并尝试“保存”它。这将导致应用程序在生产中崩溃,但不会导致应用程序在暂存中崩溃。每次我测试相同的字符,相同的内容,相同的按钮,相同的行为。…基于环境的不同反应。我连胡椒都不会 puts 我的代码中到处都有语句,因为(看起来)请求没有进入rails应用程序。我在Rails日志或NGIX错误日志中没有错误消息(保存我在多个刷新中发布的错误日志)。

    4 回复  |  直到 15 年前
        1
  •  0
  •   khelll    15 年前

    我能理解的是 config.whiny_nils 使一切都不同。 我会看着你吗 activesupport/lib/active_support/whiny_nils.rb 文件(看起来很简单)并试着从那里玩它来理解是什么造成了不同。 我相信这与您在生产环境中遇到的异常类型有关,在使用whiny-nils时可能不会引发这种异常。

    我相信您还需要提供更多关于“发布一个大的主体崩溃了我们的堆栈”部分的细节,因为这可能是rack和ruby 1.9的问题。

        2
  •  0
  •   pjb3    15 年前

    我会尝试在apache/passenger上运行这个应用程序,看看这个问题是否是nginx/passenger特有的

        3
  •  0
  •   Bob Aman    15 年前

    从外观上看,这个错误是ruby对编码的挑剔。你得到一个字符串,它认为是utf-8,你把它当作原始字节,可能是正确的。您需要识别有问题的字符串并调用 buggy_string.force_encoding(Encoding::ASCII_8BIT) 关于它。但是,如果我知道哪段代码正在对该字符串进行操作,或者知道为什么它只在生产中发生,那就见鬼了。我不会惊讶地发现问题其实是在乘客的内心深处。

    关于暂存和生产之间的区别,几乎可以肯定的是,应该作为字节字符串移动的内容存在问题,并且它被视为字符串。有大量的代码只在生产环境中发生(比如缓存),如果有任何代码这样做,那就是你的问题。

    这个 whiny_nils 事情可能无关紧要。

        4
  •  0
  •   Adam Elhardt    15 年前

    在过去的几个月里,我遇到了一个类似的问题——直到最近才真正调试它。在我的例子中,告诉乘客把临时缓冲区文件放在哪里就成功了。使其难以查找的不仅是日志文件中缺少错误消息,而且事实上,这种缓冲区不仅用于多部帖子,而且用于任何类型的大型帖子体。

    PassengerUploadBufferDir /tmp