jjzjj

ruby-on-rails - 由于 Phusion Passenger 队列阻塞导致 Web 服务负载过重

coder 2023-11-06 原文

我们正在使用 Ruby 2 on Rails 4、Mongoid 4、MongoDB 2.6 开发 Web 服务。它使用 Sidekiq 3.3.0 和 Redis 2.8,并在 Phusion Passenger 5.0.4 + Nginx 1.7.10 上运行。它仅通过 JSON API 为移动客户端和 AngularJS 网络客户端提供服务。

通常一切正常,API 处理和响应不到 1 秒。但在高峰时段,服务负载很重(API 呈现为503 Service Unavailable)。下面是我们的 Nginx 和 Mongoid 配置:

Nginx 配置

passenger_root /home/deployer/.rvm/gems/ruby-2.1.3/gems/passenger-4.0.53;
#passenger_ruby /usr/bin/ruby;
passenger_max_pool_size 70;
passenger_min_instances 1;
passenger_max_requests 20; # A workaround if apps are mem-leaking
passenger_pool_idle_time 300;
passenger_max_instances_per_app 30;
passenger_pre_start http://production_domain/;

## Note: there're 2 apps with the same config
server {
  listen 80;
  server_name production_domain;
  passenger_enabled on;
  root /home/deployer/app_name-production/current/public;

  more_set_headers 'Access-Control-Allow-Origin: *'
  more_set_headers 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD';
  more_set_headers 'Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

  if ($request_method = 'OPTIONS') {
    # more_set_headers 'Access-Control-Allow-Origin: *';
    # add_header 'Access-Control-Allow-Origin' '*';
    # add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    # add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-FooA$
    # add_header 'Access-Control-Max-Age' 1728000;
    # add_header 'Content-Type' 'text/plain charset=UTF-8';
    # add_header 'Content-Length' 0;
    return 200;
  }

  access_log /var/log/nginx/app_name-production.access.log;
  error_log /var/log/nginx/app_name-production.error.log;

  error_page 404 /404.html;
  error_page 500 502 503 504 /50x.html;
  location = /50x.html {
    root /etc/nginx/html/;
  }
  rails_env production;
}

Mongoid 配置

development:
  sessions:
    default:
      another:
      uri: mongodb://127.0.0.1:27017/database_name
test:
  sessions:
    default:
      another:
      uri: mongodb://127.0.0.1:27017/database_name
      options:
        pool_size: 10
        pool_timeout: 15
        retry_interval: 1
        max_retries: 30
        refresh_interval: 10
        timeout: 15
staging:
  sessions:
    default:
      another:
      uri: mongodb://staging_domain/staging_database
      options:
        pool_size: 10
        pool_timeout: 15
        retry_interval: 1
        max_retries: 30
        refresh_interval: 10
        timeout: 15
production:
  sessions:
    default:
      another:
      uri: mongodb://production_domain/production_database
      options:
        pool_size: 30
        pool_timeout: 15
        retry_interval: 1
        max_retries: 30
        refresh_interval: 10
        timeout: 15

Sidekiq 配置

重载时的乘客日志:

Version : 5.0.4
Date    : 2015-04-04 09:31:14 +0700
Instance: MxPcaaBy (nginx/1.7.10 Phusion_Passenger/5.0.4)

----------- General information -----------
Max pool size : 120
Processes     : 62
Requests in top-level queue : 0

----------- Application groups -----------
/home/deployer/memo_rails-staging/current/public (staging)#default:
  App root: /home/deployer/memo_rails-staging/current
  Requests in queue: 0
  * PID: 20453   Sessions: 0       Processed: 639     Uptime: 14h 34m 26s
    CPU: 0%      Memory  : 184M    Last used: 14s ago
  * PID: 402     Sessions: 0       Processed: 5       Uptime: 13h 0m 42s
    CPU: 0%      Memory  : 171M    Last used: 23m 35s
  * PID: 16081   Sessions: 0       Processed: 3       Uptime: 10h 26m 9s
    CPU: 0%      Memory  : 163M    Last used: 24m 9s a
  * PID: 30300   Sessions: 0       Processed: 1       Uptime: 4h 19m 43s
    CPU: 0%      Memory  : 164M    Last used: 24m 15s

/home/deployer/memo_rails-production/current/public (production)#default:
  App root: /home/deployer/memo_rails-production/current
  Requests in queue: 150
  * PID: 25924   Sessions: 1       Processed: 841     Uptime: 20m 49s
    CPU: 3%      Memory  : 182M    Last used: 7m 58s ago
  * PID: 25935   Sessions: 1       Processed: 498     Uptime: 20m 49s
    CPU: 2%      Memory  : 199M    Last used: 5m 40s ago
  * PID: 25948   Sessions: 1       Processed: 322     Uptime: 20m 49s
    CPU: 1%      Memory  : 200M    Last used: 7m 57s ago
  * PID: 25960   Sessions: 1       Processed: 177     Uptime: 20m 49s
    CPU: 0%      Memory  : 158M    Last used: 19s ago
  * PID: 25972   Sessions: 1       Processed: 115     Uptime: 20m 48s
    CPU: 0%      Memory  : 151M    Last used: 7m 56s ago
  * PID: 25987   Sessions: 1       Processed: 98      Uptime: 20m 48s
    CPU: 0%      Memory  : 179M    Last used: 7m 56s ago
  * PID: 25998   Sessions: 1       Processed: 77      Uptime: 20m 48s
    CPU: 0%      Memory  : 145M    Last used: 7m 2s ago
  * PID: 26012   Sessions: 1       Processed: 97      Uptime: 20m 48s
    CPU: 0%      Memory  : 167M    Last used: 19s ago
  * PID: 26024   Sessions: 1       Processed: 42      Uptime: 20m 47s
    CPU: 0%      Memory  : 148M    Last used: 7m 55s ago
  * PID: 26038   Sessions: 1       Processed: 44      Uptime: 20m 47s
    CPU: 0%      Memory  : 164M    Last used: 1m 0s ago
  * PID: 26050   Sessions: 1       Processed: 29      Uptime: 20m 47s
    CPU: 0%      Memory  : 142M    Last used: 7m 54s ago
  * PID: 26063   Sessions: 1       Processed: 41      Uptime: 20m 47s
    CPU: 0%      Memory  : 168M    Last used: 1m 1s ago
  * PID: 26075   Sessions: 1       Processed: 23      Uptime: 20m 47s
    CPU: 0%      Memory  : 126M    Last used: 7m 51s ago
  * PID: 26087   Sessions: 1       Processed: 19      Uptime: 20m 46s
    CPU: 0%      Memory  : 120M    Last used: 7m 50s ago
  * PID: 26099   Sessions: 1       Processed: 37      Uptime: 20m 46s
    CPU: 0%      Memory  : 131M    Last used: 7m 3s ago
  * PID: 26111   Sessions: 1       Processed: 20      Uptime: 20m 46s
    CPU: 0%      Memory  : 110M    Last used: 7m 49s ago
  * PID: 26126   Sessions: 1       Processed: 28      Uptime: 20m 46s
    CPU: 0%      Memory  : 172M    Last used: 1m 56s ago
  * PID: 26141   Sessions: 1       Processed: 20      Uptime: 20m 45s
    CPU: 0%      Memory  : 107M    Last used: 7m 19s ago
  * PID: 26229   Sessions: 1       Processed: 20      Uptime: 20m 21s
    CPU: 0%      Memory  : 110M    Last used: 11s ago
  * PID: 26241   Sessions: 1       Processed: 9       Uptime: 20m 21s
    CPU: 0%      Memory  : 105M    Last used: 7m 47s ago
  * PID: 26548   Sessions: 1       Processed: 23      Uptime: 19m 14s
    CPU: 0%      Memory  : 125M    Last used: 7m 44s ago
  * PID: 27465   Sessions: 1       Processed: 30      Uptime: 15m 23s
    CPU: 0%      Memory  : 109M    Last used: 2m 22s ago
  * PID: 27501   Sessions: 1       Processed: 28      Uptime: 15m 18s
    CPU: 0%      Memory  : 117M    Last used: 7m 15s ago
  * PID: 27511   Sessions: 1       Processed: 34      Uptime: 15m 17s
    CPU: 0%      Memory  : 144M    Last used: 5m 40s ago
  * PID: 27522   Sessions: 1       Processed: 30      Uptime: 15m 17s
    CPU: 0%      Memory  : 110M    Last used: 26s ago
  * PID: 27533   Sessions: 1       Processed: 38      Uptime: 15m 17s
    CPU: 0%      Memory  : 110M    Last used:"4m 44s ago
  * PID: 27555   Sessions: 1       Processed: 27      Uptime: 15m 15s
    CPU: 0%      Memory  : 120M    Last used: 1m 29s ago
  * PID: 27570   Sessions: 1       Processed: 21      Uptime: 15m 14s
    CPU: 0%      Memory  : 107M    Last used: 7m 1s ago
  * PID: 27590   Sessions: 1       Processed: 8       Uptime: 15m 13s
    CPU: 0%      Memory  : 105M    Last used: 7m 34s ago
  * PID: 27599   Sessions: 1       Processed: 13      Uptime: 15m 13s
    CPU: 0%      Memory  : 107M    Last used: 7m 0s ago
  * PID: 27617   Sessions: 1       Processed: 26      Uptime: 15m 12s
    CPU: 0%      Memory  : 114M    Last used: 4m 49s ago
  * PID: 27633   Sessions: 1       Processed: 19      Uptime: 15m 11s
    CPU: 0%      Memory  : 137M    Last used: 1m 14s ago
  * PID: 27643   Sessions: 1       Processed: 15      Uptime: 15m 11s
    CPU: 0%      Memory  : 132M    Last used: 6m 19s ago
  * PID: 27661   Sessions: 1       Processed: 23      Uptime: 15m 10s
    CPU: 0%      Memory  : 112M    Last used: 9s ago
  * PID: 27678   Sessions: 1       Processed: 24      Uptime: 15m 9s
    CPU: 0%      Memory  : 108M    Last used: 6m 53s ago
  * PID: 27692   Sessions: 1       Processed: 9       Uptime: 15m 9s
    CPU: 0%      Memory  : 105M    Last used: 7m 22s ago
  * PID: 28400   Sessions: 1       Processed: 19      Uptime: 12m 45s
    CPU: 0%      Memory  : 111M    Last used: 1m 25s ago
  * PID: 28415   Sessions: 1       Processed: 26      Uptime: 12m 45s
    CPU: 0%      Memory  : 149M    Last used: 3m 45s ago
  * PID: 28439   Sessions: 1       Processed: 14      Uptime: 12m 44s
    CPU: 0%      Memory  : 106M    Last used: 59s ago
  * PID: 28477   Sessions: 1       Processed: 12      Uptime: 12m 42s
    CPU: 0%      Memory  : 108M    Last used: 1m 34s ago
  * PID: 28495   Sessions: 1       Processed: 14      Uptime: 12m 41s
    CPU: 0%      Memory  : 108M    Last used: 18s ago
  * PID: 29315   Sessions: 1       Processed: 7       Uptime: 10m 1s
    CPU: 0%      Memory  : 107M    Last used: 7m 0s ago
  * PID: 29332   Sessions: 1       Processed: 13      Uptime: 10m 0s
    CPU: 0%      Memory  : 108M    Last used: 5m 39s ago
  * PID: 29341   Sessions: 1       Processed: 7       Uptime: 10m 0s
    CPU: 0%      Memory  : 105M    Last used: 6m 53s ago
  * PID: 29353   Sessions: 1       Processed: 11      Uptime: 10m 0s
    CPU: 0%      Memory  : 119M    Last used: 5m 4s ago
  * PID: 29366   Sessions: 1       Processed: 16      Uptime: 9m 59s
    CPU: 0%      Memory  : 119M    Last used: 3m 13s ago
  * PID: 29377   Sessions: 1       Processed: 10      Uptime: 9m 59s
    CPU: 0%      Memory  : 113M    Last used: 1m 34s ago
  * PID: 29388   Sessions: 1       Processed: 2       Uptime: 9m 59s
    CPU: 0%      Memory  : 97M     Last used: 7m 28s ago
  * PID: 29400   Sessions: 1       Processed: 6       Uptime: 9m 59s
    CPU: 0%      Memory  : 103M    Last used: 6m 53s ago
  * PID: 29422   Sessions: 1       Processed: 17      Uptime: 9m 58s
    CPU: 0%      Memory  : 132M    Last used: 1m 24s ago
  * PID: 29438   Sessions: 1       Processed: 1       Uptime: 9m 57s
    CPU: 0%      Memory  : 96M     Last used: 6m 52s ago
  * PID: 29451   Sessions: 1       Processed: 21      Uptime: 9m 56s
    CPU: 0%      Memory  : 133M    Last used: 2m 10s ago
  * PID: 29463   Sessions: 1       Processed: 19      Uptime: 9m 56s
    CPU: 0%      Memory  : 111M    Last used: 27s ago
  * PID: 29477   Sessions: 1       Processed: 23      Uptime: 9m 56s
    CPU: 0%      Memory  : 117M    Last used: 14s ago
  * PID: 30625   Sessions: 1       Processed: 7       Uptime: 6m 49s
    CPU: 0%      Memory  : 106M    Last used: 1m 21s ago
  * PID: 30668   Sessions: 1       Processed: 2       Uptime: 6m 44s
    CPU: 0%      Memory  : 105M    Last used: 1m 13s ago
  * PID: 30706   Sessions: 1       Processed: 16      Uptime: 6m 43s
    CPU: 0%      Memory  : 148M    Last used: 1m 11s ago
  * PID: 30718   Sessions: 1       Processed: 12      Uptime: 6m 43s
    CPU: 0%      Memory  : 112M    Last used: 1m 16s ago

我有一些问题:

  1. 似乎是互联网连接速度较慢的人正在请求我们的服务,导致 Passenger 进程被阻止。我们必须重新启动 Nginx 才能使 Web 服务再次运行。有人有这方面的经验吗?
  2. 我们还使用 Sidekiq 作为工作队列。我们的大多数 Worker 都是在不影响 MongoDB 的情况下实现的。他们工作得很好。

但是我们使用 2 个 Worker 来更新用户的数据,它们查询、更新和插入数据到数据库中。我们尝试使用 MongoDB 批量命令(updateinsert)优化这些所有任务。

正常情况下,当少量用户请求web服务时,Workers工作正常,繁忙队列在1分钟左右处理完毕,但当它收到更多请求时,繁忙队列会阻塞整个系统。我们必须再次重新启动 Nginx 才能使其正常工作。以下是 Sidekiq 配置:

development:
  :concurrency: 5
  :logfile: ./log/sidekiq_development.log
  :pidfile: ./log/sidekiq.pid
staging:
  :concurrency: 5
  :logfile: ./log/sidekiq_staging.log
  :pidfile: ./log/sidekiq.pid
production:
  :concurrency: 15
  :logfile: ./log/sidekiq_production.log
  :pidfile: ./log/sidekiq.pid
:queues:
  - ...

我们对这些问题没有任何经验。有人有什么想法吗?

更新 1:

在服务器负载过重时进行一些监控后,我们得到了这样的结果:MongoDB 进程有很多故障和堆积的读取队列,以下是 mongostat 在停机期间记录的内容:

insert  query update delete getmore command flushes mapped  vsize    res faults      locked db idx miss %     qr|qw   ar|aw  netIn netOut  conn       time
    *0      2     *0     *0       0     4|0       0    79g   160g  3.36g    137   memo_v2:2.6%          0      17|0     8|0    36k     8k    61   15:05:22
    *0      6     *0     *0       0     1|0       0    79g   160g  3.38g    144   memo_v2:2.1%          0      30|0     3|0   722b    11k    61   15:05:23
  1595     15      1     *0       0     5|0       0    79g   160g  3.41g    139  memo_v2:19.7%          0      20|0     8|0   164k   179k    61   15:05:25
     1     18      2     *0       1     6|0       0    79g   160g  3.38g    198  memo_v2:14.4%          0      31|0     1|0     3k   122k    61   15:05:26
     2     20      4     *0       0     7|0       0    79g   160g  3.38g    169   memo_v2:8.6%          0      29|0     1|0     3k   157k    61   15:05:27
     1      6     23     *0       0     4|0       0    79g   160g  3.39g    190  memo_v2:18.7%          0      32|0     1|0     1k    63k    61   15:05:28
     1      4     42     *0       0     4|0       0    79g   160g   3.1g    115  memo_v2:35.9%          0      30|0     0|1     1k    20k    61   15:05:29
     1      5     51     *0       0     4|0       0    79g   160g  3.11g    177  memo_v2:30.0%          0      28|0     1|0     1k    23k    61   15:05:30
    *0      6     20     *0       0     2|0       0    79g   160g  3.12g    174  memo_v2:40.9%          0      28|0     1|0    15k     7k    61   15:05:31
     2      9     *0     *0       1     7|0       0    79g   160g   3.1g    236   memo_v2:4.4%          0      26|0     2|0     2k    31k    61   15:05:32

有人遇到过这个问题吗?

最佳答案

我没有足够的声誉来发表评论,所以我必须添加一个非常乏味的答案。

我对堆栈没有任何经验,但如果您认为缓慢的客户端是造成乘客问题的原因是正确的,那么我建议您确保乘客面前有足够的缓冲流程

对于 nginx,重要的设置看起来是 proxy_buffers。以下文章中标题为“使用缓冲区释放后端服务器”的部分讨论了 nginx 模块:https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching

对于 mongodb 问题,听起来您只需要深入挖掘一下。如果您能在代码中找到问题发生的位置,那么解决方案可能会自行出现。 Hongli 链接的文章看起来非常好。

关于ruby-on-rails - 由于 Phusion Passenger 队列阻塞导致 Web 服务负载过重,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29442467/

有关ruby-on-rails - 由于 Phusion Passenger 队列阻塞导致 Web 服务负载过重的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  4. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  5. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  6. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  7. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  8. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  9. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  10. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

随机推荐