<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>rubyist518 (superiorlu)</title>
    <link>https://ruby-china.org/rubyist518</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>如何持续监控 Unicorn 的性能指标</title>
      <description>&lt;h3 id="背景介绍"&gt;背景介绍&lt;/h3&gt;
&lt;p&gt;最近用 &lt;a href="https://github.com/ruby-grape/grape" rel="nofollow" target="_blank" title=""&gt;Grape&lt;/a&gt; 重写了一份 API，马上要上线了，突然接到 boss 通知，需要做好应用服务器监控，以便上线遇到突发情况。于是乎从万能的 &lt;a href="https://github.com/" rel="nofollow" target="_blank" title=""&gt;github&lt;/a&gt; 上找到了这个开源的代码：&lt;a href="https://github.com/TheClimateCorporation/unicorn-metrics" rel="nofollow" target="_blank" title=""&gt;unicron_metrics&lt;/a&gt;。用起来还不错，下面给大家介绍一下认识。&lt;/p&gt;
&lt;h3 id="是什么"&gt;是什么&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;unicorn_metrics&lt;/code&gt;是采集基于 Rack 应用服务性能数据的工具，尤其针对类似 Unicorn
的多进程服务器，并提供一个对外查看数据的接口。&lt;/p&gt;
&lt;h3 id="如何监控"&gt;如何监控&lt;/h3&gt;
&lt;p&gt;通过 &lt;a href="http://raindrops.bogomips.org" rel="nofollow" target="_blank" title=""&gt;raindrops&lt;/a&gt; 来采集&lt;code&gt;Uincorn&lt;/code&gt;指标数据，同时通过构建&lt;code&gt;Middleware&lt;/code&gt;统计应用中 HTTP 指标数据。&lt;/p&gt;
&lt;h3 id="监控指标"&gt;监控指标&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;unicorn_metrics&lt;/code&gt;监控指标分 2 部分：http 指标和 raindrops 指标，下面介绍各方面的指标：&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th style="text-align:left;"&gt;指标名称&lt;/th&gt;
&lt;th style="text-align:left;"&gt;指标类型&lt;/th&gt;
&lt;th style="text-align:left;"&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;request.GET&lt;/td&gt;
&lt;td style="text-align:left;"&gt;timer&lt;/td&gt;
&lt;td style="text-align:left;"&gt;GET 请求的消耗时间 (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;request.POST&lt;/td&gt;
&lt;td style="text-align:left;"&gt;timer&lt;/td&gt;
&lt;td style="text-align:left;"&gt;POST 请求的消耗时间 (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;request.PUT&lt;/td&gt;
&lt;td style="text-align:left;"&gt;timer&lt;/td&gt;
&lt;td style="text-align:left;"&gt;PUT 请求的消耗时间 (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;request.DELETE&lt;/td&gt;
&lt;td style="text-align:left;"&gt;timer&lt;/td&gt;
&lt;td style="text-align:left;"&gt;DELETE 请求的消耗时间 (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;request.HEAD&lt;/td&gt;
&lt;td style="text-align:left;"&gt;timer&lt;/td&gt;
&lt;td style="text-align:left;"&gt;HEAD 请求的消耗时间 (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;responses.2xx&lt;/td&gt;
&lt;td style="text-align:left;"&gt;counter&lt;/td&gt;
&lt;td style="text-align:left;"&gt;响应状态为 2xx 的次数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;responses.3xx&lt;/td&gt;
&lt;td style="text-align:left;"&gt;counter&lt;/td&gt;
&lt;td style="text-align:left;"&gt;响应状态为 3xx 的次数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;responses.4xx&lt;/td&gt;
&lt;td style="text-align:left;"&gt;counter&lt;/td&gt;
&lt;td style="text-align:left;"&gt;响应状态为 4xx 的次数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;responses.5xx&lt;/td&gt;
&lt;td style="text-align:left;"&gt;counter&lt;/td&gt;
&lt;td style="text-align:left;"&gt;响应状态为 5xx 的次数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;raindrops.calling&lt;/td&gt;
&lt;td style="text-align:left;"&gt;gauge&lt;/td&gt;
&lt;td style="text-align:left;"&gt;应用服务器调度的数量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;raindrops.writing&lt;/td&gt;
&lt;td style="text-align:left;"&gt;gauge&lt;/td&gt;
&lt;td style="text-align:left;"&gt;被写入数据的客户端的数量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;raindrops.active&lt;/td&gt;
&lt;td style="text-align:left;"&gt;gauge&lt;/td&gt;
&lt;td style="text-align:left;"&gt;所有进程中已连接并尚未关闭的 sockets 的连接数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left;"&gt;raindrops.queued&lt;/td&gt;
&lt;td style="text-align:left;"&gt;gauge&lt;/td&gt;
&lt;td style="text-align:left;"&gt;等待连接 sockets 的请求数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h3 id="监控步骤"&gt;监控步骤&lt;/h3&gt;
&lt;p&gt;1.安装&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'unicorn_metrics'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;github: &lt;/span&gt;&lt;span class="s1"&gt;'superiorlu/unicorn_metrics'&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.配置 unincor_metric.rb&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#config/initializers/unicorn_metrics.rb&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UnicornMetrics&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;UnicornMetrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'app_name'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3.配置 config.ru (Rails 无需配置)&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.ru&lt;/span&gt;

 &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'unicorn_metrics/middleware'&lt;/span&gt;
 &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;UnicornMetrics&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Middleware&lt;/span&gt;
 &lt;span class="c1"&gt;# other middleware...&lt;/span&gt;
 &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;N&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;4.visit &lt;a href="http://localhost:3000/metrics" rel="nofollow" target="_blank" title=""&gt;http://localhost:3000/metrics&lt;/a&gt;, 返回 unicorn 的各方面的指标。&lt;/p&gt;
&lt;h3 id="实时监控和报警"&gt;实时监控和报警&lt;/h3&gt;
&lt;p&gt;由于&lt;code&gt;unicorn_metrics&lt;/code&gt;只提供了查看&lt;code&gt;unicorn&lt;/code&gt;性能指标的接口，根据业务的需求我们对其进行了修改，使其可以在装有我们 &lt;a href="http://www.oneapm.com/ci/feature.html" rel="nofollow" target="_blank" title=""&gt;CloudInsight 探针&lt;/a&gt; 的服务器上使用 &lt;a href="http://docs-ci.oneapm.com/api/ruby.html" rel="nofollow" target="_blank" title=""&gt;Cloud Insight Ruby SDK&lt;/a&gt; 进行实时回传性能数据，形成 dashboard 图表同时在服务器出现问题时及时报警。具体数据图表 见下图：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://superiorlu.github.io/index.html" rel="nofollow" target="_blank" title=""&gt;&lt;img src="https://l.ruby-china.com/photo/2016/dd8a1e361cc1a347c5dcc4f2f496c79d.png" title="" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;数据图表组成仪表盘示例：&lt;a href="http://superiorlu.github.io/dashboards.html" rel="nofollow" target="_blank" title=""&gt;http://superiorlu.github.io/dashboards.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;源码见：&lt;a href="https://github.com/superiorlu/unicorn_metrics" rel="nofollow" target="_blank" title=""&gt;https://github.com/superiorlu/unicorn_metrics&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="小结"&gt;小结&lt;/h3&gt;
&lt;p&gt;本文介绍了使用&lt;code&gt;unicorn_metris&lt;/code&gt;对&lt;code&gt;Unicorn&lt;/code&gt;进行持续监控。使用&lt;a href="http://docs-ci.oneapm.com/api/ruby.html" rel="nofollow" target="_blank" title=""&gt;Cloud Insight Ruby SDK&lt;/a&gt;，不但可以传输性能数据，还可以传输自定义的业务数据，将数据以图表的展示出来，并根据需求添加相应的报警服务。&lt;/p&gt;</description>
      <author>rubyist518</author>
      <pubDate>Wed, 20 Apr 2016 16:28:18 +0800</pubDate>
      <link>https://ruby-china.org/topics/29792</link>
      <guid>https://ruby-china.org/topics/29792</guid>
    </item>
    <item>
      <title>RubyCritic-一款不错的检测代码质量工具</title>
      <description>&lt;p&gt;最近在开发&lt;a href="http://www.oneapm.com/ci/feature.html" rel="nofollow" target="_blank" title=""&gt;Cloud Insight&lt;/a&gt; API 时，发现一个可以检测 ruby 代码质量的工具-&lt;a href="https://github.com/whitesmith/rubycritic" rel="nofollow" target="_blank" title=""&gt;RubyCritic&lt;/a&gt;。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RubyCritic 集成 &lt;a href="https://github.com/troessner/reek" rel="nofollow" target="_blank" title=""&gt;Reek&lt;/a&gt;, &lt;a href="https://github.com/seattlerb/flay" rel="nofollow" target="_blank" title=""&gt;Flay&lt;/a&gt; 和 &lt;a href="https://github.com/seattlerb/flog" rel="nofollow" target="_blank" title=""&gt;Flog&lt;/a&gt;这 3 个分析代码的工具，对你的 Ruby 代码进行静态分析并生成质量报告。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="功能介绍"&gt;功能介绍&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;可以总览你的项目，并且可以对代码打分 (百分制)
&lt;img src="http://upload-images.jianshu.io/upload_images/334070-7fdec9ad235198e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt=""&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;根据各自的坏味道数量建立文件索引&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;对不同文件按照&lt;code&gt;改动频率&lt;/code&gt;、&lt;code&gt;复杂度&lt;/code&gt;、&lt;code&gt;重复度&lt;/code&gt;和&lt;code&gt;坏味道&lt;/code&gt;4 个维度进行综合评定代码质量等级&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/334070-ecb14c8223ecc2d2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt=""&gt;3. 可以查看具体的类文件中的代码质量问题&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/334070-05af269cc72e0716.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="用法"&gt;用法&lt;/h3&gt;
&lt;p&gt;看一下 rubycritic(2.7.0) 指令&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rubycritic --help&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Usage: rubycritic [options] [paths]}

-p, --path [PATH]               设置质量报告存放的路径(默认: tmp/rubycritic)  
-f, --format [FORMAT]           设置报告格式:
                                  html (默认)
                                  json
                                  console 
-s, --minimum-score [MIN_SCORE] 设置最小分数
-m, --mode-ci                   使用CI模式(更快，但仅分析最后一次提交)
    --deduplicate-symlinks      基于最后目标去除重复的符号链接
    --no-browser                不使用浏览器打开html格式的报告
    --suppress-ratings          压制质量评级 
-v, --version                   显示版本号
-h, --help                      显示帮助信息
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;rubycritic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;的效果如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/334070-f40ca5b5b16c0f60.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;从上图也能看出 rubycritic 分析代码流程。&lt;/p&gt;
&lt;h3 id="其他用法"&gt;其他用法&lt;/h3&gt;
&lt;p&gt;平时使用&lt;a href="https://github.com/guard/guard" rel="nofollow" target="_blank" title=""&gt;guard&lt;/a&gt;工具的同学，可以使用&lt;a href="https://github.com/whitesmith/guard-rubycritic" rel="nofollow" target="_blank" title=""&gt;guard-rubycritic&lt;/a&gt;, 代码改动时会自动分析你的代码。
有兴趣的同学也可以将它集成到&lt;a href="http://jenkins-ci.org/" rel="nofollow" target="_blank" title=""&gt;Jenkins CI&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id="扩展功能"&gt;扩展功能&lt;/h3&gt;
&lt;p&gt;在使用&lt;code&gt;rubycritic&lt;/code&gt;过程中，每次都要手动打开浏览器进行查看质量报告，太麻烦了。于是给它添加一个功能 &lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/334070-e6faffc555b6ff22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;目前仅支持 Linux 和 Mac OSX 系统：&lt;/p&gt;

&lt;p&gt;支持 Linux 浏览器： &lt;code&gt;Firefox（默认）&lt;/code&gt;、&lt;code&gt;Chrome&lt;/code&gt;和 &lt;code&gt;Chromium&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;支持 Mac OSX 浏览器： &lt;code&gt;Safari（默认）&lt;/code&gt;、&lt;code&gt;Chrome&lt;/code&gt;和 &lt;code&gt;Firefox&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="运行步骤"&gt;运行步骤&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt; 修改 Gemfile 
&lt;code&gt;ruby
gem 'rubycritic', github: 'superiorlu/rubycritic', branch: 'open_with_browser'
&lt;/code&gt; &lt;/li&gt;
&lt;li&gt; 运行&lt;code&gt;rubycritic -O chrome&lt;/code&gt;即可。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;源代码：&lt;a href="https://github.com/superiorlu/rubycritic/tree/open_with_browser" rel="nofollow" target="_blank" title=""&gt;https://github.com/superiorlu/rubycritic/tree/open_with_browser&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="总结"&gt;总结&lt;/h3&gt;
&lt;p&gt;本文简单介绍了&lt;code&gt;rubycritic&lt;/code&gt;和用法，可能某些知识点会有所遗漏，不足之处请大家指正。&lt;/p&gt;
&lt;h3 id="更新(2016.01.29)"&gt;更新 (2016.01.29)&lt;/h3&gt;
&lt;p&gt;目前&lt;code&gt;rubycritic&lt;/code&gt;已经更新到了&lt;code&gt;2.7.0&lt;/code&gt;,  已经默认使用浏览器打开 html 格式的报告了。&lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt;&lt;/p&gt;</description>
      <author>rubyist518</author>
      <pubDate>Fri, 15 Jan 2016 17:49:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/28746</link>
      <guid>https://ruby-china.org/topics/28746</guid>
    </item>
    <item>
      <title>你应该使用的 5 种 Ruby 方法</title>
      <description>&lt;p&gt;最近&lt;a href="http://rubyweekly.com/issues/279" rel="nofollow" target="_blank" title=""&gt;rubyweekly&lt;/a&gt;回顾了 2015 年比较好的文章，看到一篇文章，感觉挺有意思。分享给大家 &lt;a href="https://blog.engineyard.com/2015/five-ruby-methods-you-should-be-using" rel="nofollow" target="_blank" title=""&gt;原文&lt;/a&gt; 。&lt;/p&gt;
&lt;h3 id="5种方法："&gt;5 种方法：&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.3.0/Object.html#method-i-tap" rel="nofollow" target="_blank" title=""&gt;Object#tap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.3.0/Array.html#method-i-bsearch" rel="nofollow" target="_blank" title=""&gt;Array#bsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-flat_map" rel="nofollow" target="_blank" title=""&gt;Enumerable#flat_map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.3.0/Array.html#method-c-new" rel="nofollow" target="_blank" title=""&gt;Array.new&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.3.0/Fixnum.html#method-i-3C-3D-3E" rel="nofollow" target="_blank" title=""&gt;&amp;lt;=&amp;gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;大家平时写 Ruby 的遇到比较有用的方法，不妨一起分享一下。&lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt;&lt;/p&gt;</description>
      <author>rubyist518</author>
      <pubDate>Fri, 08 Jan 2016 14:38:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/28658</link>
      <guid>https://ruby-china.org/topics/28658</guid>
    </item>
    <item>
      <title>探讨如何统计 Ruby 应用服务器使用内存方法</title>
      <description>&lt;p&gt;最近在解决探针获取 Ruby 应用服务器的内存使用的情况，将解决的思路总结一下，希望对此感兴趣的伙伴一起探讨。&lt;/p&gt;

&lt;p&gt;先对比应用服务器：&lt;a href="http://puma.io/" rel="nofollow" target="_blank" title=""&gt;Puma&lt;/a&gt;和&lt;a href="https://www.phusionpassenger.com/" rel="nofollow" target="_blank" title=""&gt;Passenger&lt;/a&gt;，下面对比这 2 个服务器内存统计，&lt;/p&gt;
&lt;h2 id="Puma (2.13.4)"&gt;Puma (2.13.4)&lt;/h2&gt;
&lt;p&gt;单进程模式：直接获取进程 id: &lt;code&gt;Process.pid&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`ps -o rss= &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="c1"&gt;#单位:MB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;cluster 模式：以启动 2 个 worker 进程为例:
 &lt;img src="https://l.ruby-china.com/photo/2015/60a1b6bc9287dffc9009bc01326c6035.png" title="" alt="Puma cluster"&gt;
从上面截图可以看到，Puma 启动后会出现 3 个进程：1 个 master 进程和 2 个 worker 进程。
内存的使用情况 (见&lt;strong&gt;RSS&lt;/strong&gt;列): &lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;109908&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;109868&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7256&lt;/span&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;221.7109375&lt;/span&gt; &lt;span class="c1"&gt;#单位:MB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而对于探针来说，一个探针实例是伴随进程一起启动的，也就说一个探针只能识别自己所在的进程 id，那如何获取应用服务器使用的内存？我们用其中 1 个 woker 进程所在的进程组 [&lt;strong&gt;PGID&lt;/strong&gt;] 看一下:(为啥不是父进程？, 见下文 Passenger)
&lt;img src="https://l.ruby-china.com/photo/2015/be497a0b55f9f290a647aab6b7d7d9c6.png" title="" alt="puma 2"&gt;
这 3 个进程都在相同的进程组里，而且进程组号为 master 的进程 id，那我们就可以用这个信息获取应用服务器的所使用的内存：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;得到 1 个 worker 进程 id: &lt;code&gt;Process.pid&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;获取所在进程组：&lt;code&gt;Process.getpgrp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;获取到进程组内所有的进程：
&lt;code&gt;ruby
`ps -o pid,pgid -e | grep -w "#{pgrp_id}"`.split(/\s+/).uniq 
&lt;/code&gt;
4.累加进程组内进程内存和即为应用服务器使用内存：
&lt;code&gt;ruby
pids.inject(0.0){|m, pid| m + memory(pid)}
&lt;/code&gt;
## Passenger (5.0.20)
启动 Passenger 后的 Process 信息：
&lt;img src="https://l.ruby-china.com/photo/2015/5c2b218898a242c6744c1601108baf1b.png" title="" alt="passenger 1"&gt;
对 Passenger 架构感兴趣的请移步到&lt;a href="https://www.phusionpassenger.com/documentation/Design%20and%20Architecture.html" rel="nofollow" target="_blank" title=""&gt;这儿&lt;/a&gt;. 
查看一下 worker 所在进程组和父进程:
&lt;img src="https://l.ruby-china.com/photo/2015/3e2b7e8997c30a308e8bf52d42a394c6.png" title="" alt="passenger 2"&gt;
通过 PPID 可以看出
&lt;code&gt;Passenger core —&amp;gt; Passenger AppPreloader —&amp;gt; Passenger RubyApp&lt;/code&gt;
三者为爷 - 父-子关系，当服务器请求量增大时&lt;code&gt;AppPreloader&lt;/code&gt;会产生新的进程来响应请求，从而新的&lt;code&gt;RubyApp&lt;/code&gt;进程的&lt;strong&gt;PPID&lt;/strong&gt;即为&lt;code&gt;AppPreloader&lt;/code&gt;的&lt;strong&gt;PID&lt;/strong&gt;，这样看来就可以将同一个&lt;strong&gt;PPID&lt;/strong&gt;的进程加起来得到应用服务器的内存？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;由于 Passenger 会根据服务器的负载量动态调整进程数，当服务器请求量较小时，Passenger 会 kill 多余的进程，会出现下面的情况：
&lt;img src="https://l.ruby-china.com/photo/2015/f5a5787b87b97c6cd904aa5df5f84559.png" title="" alt="pssenger 3"&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AppPreloader&lt;/code&gt;也被 Passenger 杀掉了。原&lt;code&gt;RubyApp&lt;/code&gt;进程的&lt;strong&gt;PPID&lt;/strong&gt;变成了 1。这时如果服务器的请求量增大，应用服务器进程会成为这样：
&lt;img src="https://l.ruby-china.com/photo/2015/2075d985c4df04fec32fb9bf13114a2d.png" title="" alt="passener 4"&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Passenger core&lt;/code&gt; 产生新的&lt;code&gt;AppPreloader&lt;/code&gt;进程，并且&lt;code&gt;AppPreloader&lt;/code&gt;产生新的&lt;code&gt;RubyApp&lt;/code&gt;进程，这时如果只用&lt;strong&gt;PPID&lt;/strong&gt;统计应用服务器内存就会不准确，所以要统计 Passenger 的使用的内存还得通过累加在同一个进程组 (&lt;strong&gt;PGID&lt;/strong&gt;) 的所有进程使用的内存和得到。&lt;/p&gt;

&lt;p&gt;由于&lt;a href="http://unicorn.bogomips.org/" rel="nofollow" target="_blank" title=""&gt;Unicorn&lt;/a&gt;和&lt;a href="http://rainbows.bogomips.org/" rel="nofollow" target="_blank" title=""&gt;Rainbows&lt;/a&gt;都与 Puma 的 cluster 模式 [master+worker 模式] 类似，内存统计的方式可以参考上文的 Puma。&lt;/p&gt;
&lt;h2 id="总结："&gt;总结：&lt;/h2&gt;
&lt;p&gt;由于&lt;a href="http://code.macournoyer.com/thin/" rel="nofollow" target="_blank" title=""&gt;Thin&lt;/a&gt;启动多个 server 后没有类似的特点，上面方法不适用于 Thin，有好方法的伙伴们可以告知&lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt;&lt;/p&gt;

&lt;p&gt;在解决探针统计应用服务器的内存问题上，摸索出了上面的一条路子，如果小伙伴们有其他更好的方式，可以一起探讨一下。&lt;/p&gt;
&lt;h2 id="10月15日更新"&gt;10 月 15 日更新&lt;/h2&gt;
&lt;p&gt;对于&lt;a href="http://code.macournoyer.com/thin/" rel="nofollow" target="_blank" title=""&gt;Thin&lt;/a&gt;，有一种思路是使用&lt;a href="https://github.com/ddollar/foreman" rel="nofollow" target="_blank" title=""&gt;foreman&lt;/a&gt;来管理应用进程，这样就可以统一计算应用服务器内存方法。
&lt;img src="https://l.ruby-china.com/photo/2015/81d29c59cb07e9802a6b481c668b2230.png" title="" alt="Thin"&gt;  欢迎拍砖。&lt;/p&gt;</description>
      <author>rubyist518</author>
      <pubDate>Wed, 14 Oct 2015 16:44:53 +0800</pubDate>
      <link>https://ruby-china.org/topics/27675</link>
      <guid>https://ruby-china.org/topics/27675</guid>
    </item>
  </channel>
</rss>
