<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Ruby论坛最新讨论 - JavaEye</title>
    <description>Ruby编程、Ruby DSL、Ruby on rails - Java编程，Ruby编程，微软.net，AJAX，敏捷软件开发，综合软件技术</description>
    <link>http://www.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>rails oracle 定时生成数据 </title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://aroundworld2008.javaeye.com">aroundworld2008</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/237721" style="color:red;">http://www.javaeye.com/topic/237721</a>&nbsp;
          发表时间: 2008年09月05日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          因项目需要 ，写了一个task 定时从oracle 拉数据再插入到mysql里，程序写出来了已经测试过了，但搬到linux cron 里一用，linux cron 报找不到oracle 的libclnth.so.10.1这个文件，估计是LD_LIBRARY_PATH 这个路径他找不到，所以一般报错，但我更改里了/etc/crontab这里的path也没有用呀， 哎，整了一下午，没有什么头绪了！！<br />在console and  ide （即 rake loaddata ）里是可以正常从oracle里拉数据的！有兄弟碰到这个问题吗？
          <br/><br/>
          <span style="color:red;">
            <a href="http://tales.javaeye.com/topic/237721" style="color:red;">已有 <strong>1</strong> 人发表回复，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 05 Sep 2008 17:29:29 +0800</pubDate>
        <link>http://www.javaeye.com/topic/237721</link>
        <guid>http://www.javaeye.com/topic/237721</guid>
      </item>
      <item>
        <title>配置和使用ruby_imaps</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://platoon.javaeye.com">platoon</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/237715" style="color:red;">http://www.javaeye.com/topic/237715</a>&nbsp;
          发表时间: 2008年09月05日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          把下载回来的ruby_imaps.zip解压后得到二个文件夹，把这二个文件夹拷到你的VIM配置目录里。<br />Linux一般是<br /><pre name="code" class="java">~/.vim</pre><br />在windows里有二个地方，<br /><pre name="code" class="java">C:\Documents and Settings\账号\vimfiles</pre><br />和VIM安装目录下的vimfiles下。<br />现在要配置一下，在VIM的配置文件里加上<br /><pre name="code" class="java">source $VIM\vimfiles\ftplugin\ruby_imaps.vim</pre><br />就可以了！<br /><br /><br />ruby_imaps介绍<br /><a href="http://blogger.org.cn/blog/more.asp?name=lhwork&id=21961" target="_blank">http://blogger.org.cn/blog/more.asp?name=lhwork&id=21961</a><br />ruby_imaps下载<br /><a href="http://www.vim.org/scripts/script.php?script_id=1726" target="_blank">http://www.vim.org/scripts/script.php?script_id=1726</a>
          <br/><br/>
          <span style="color:red;">
            <a href="http://tales.javaeye.com/topic/237715" style="color:red;">已有 <strong>0</strong> 人发表回复，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 05 Sep 2008 17:19:08 +0800</pubDate>
        <link>http://www.javaeye.com/topic/237715</link>
        <guid>http://www.javaeye.com/topic/237715</guid>
      </item>
      <item>
        <title>对Ruby VM的GC的思考</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/235937" style="color:red;">http://www.javaeye.com/topic/235937</a>&nbsp;
          发表时间: 2008年09月02日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby虽然是动态脚本语言，但是和Java一样，带有VM，有自己的内存堆，创建对象的时候在堆里面分配内存，对象使用完毕由GC进行回收。但是通过我们运营Rails网站两年多的实践来看，Ruby VM的GC还是存在很大的问题。简单的来说，就是GC之后，尽管对象已经完全回收，但是物理内存释放不够充分，有泄漏的现象。通过pmap来dump ruby进程物理内存地址映射表进行分析，观察到ruby的内存堆总是在不停的扩张，GC之后回收不干净。而我对比观察Java VM，其Full GC之后，物理内存释放的非常干净。所以用Ruby做服务器长期的跑，就会发现Ruby进程没有理由的缓慢泄漏内存，内存堆缓慢增长，貌似没有上限。<br /><br />由于pmap命令可以dump进程的内存映射表，因此我们可以对比RubyVM和JVM在GC前后的内存映射情况。比方说Ruby的内存状况大概是这样的：<br /><br />下图是一个Ruby进程的物理内存映射表，堆内存占据的空间是我抽取出来的三行：<br /><br /><pre name="code" class="ruby">
00000000005d4000 125260K rwx--    [ anon ]
0000002a95c23000  23456K rw---    [ anon ]
0000002a99186000  50980K rw---    [ anon ]</pre><br /><br /><pre name="code" class="ruby">
0000000000400000    760K r-x--  /usr/local/ruby/bin/ruby
00000000005bd000     92K rw---  /usr/local/ruby/bin/ruby
00000000005d4000 125260K rwx--    [ anon ]
0000002a95556000     84K r-x--  /lib64/ld-2.3.3.so
0000002a9556b000     12K rw---    [ anon ]
0000002a9556e000     24K r--s-  /usr/lib64/gconv/gconv-modules.cache
0000002a95574000      4K rw---    [ anon ]
0000002a95577000     12K rw---    [ anon ]
0000002a9557a000    204K r----  /usr/lib/locale/en_US.utf8/LC_CTYPE
0000002a9566a000     12K rw---  /lib64/ld-2.3.3.so
0000002a9566d000      8K r-x--  /lib64/libdl.so.2
0000002a9566f000   1024K -----  /lib64/libdl.so.2
0000002a9576f000      4K rw---  /lib64/libdl.so.2
......
</pre><br /><br />可以看出来Ruby的堆内存分配比较连续，分段不多。而JVM的堆内存分配段就很多了，由于堆地址段太多，我就不贴出来了，大家可以自己观察。<br /><br /><span style="color: red">由于Ruby的内存分配算法和回收算法还是比较原始的，因此在进行多次回收之后，内存堆很容易出现大量的内存碎片，很多内存碎片并不能够被有效的利用，并且ruby没有好的碎片归并压缩算法，因此碎片造成的内存堆地址空间浪费就会越来越大。其结果就是Ruby进程在长期高负载运行之下，表现出缓慢的内存泄漏现象！</span><br /><br />对比JVM的堆分配，他分配了很多的段，每个段的内存存活期不一样，根据分代算法，可以把不同存活期的对象在堆之间移动，堆内部则进行碎片归并。比方说我对一个Tomcat应用服务器的实际应用先pmap记录内存映射，然后GC，再pmap记录内存映射，两者diff一下，就可以发现某些堆在收缩，但是某些堆甚至在GC后扩张了，这便是对象在堆之间进行移动的现象。因此我不得不赞赏一下JVM的内存分配。<br /><br />话说回来，由于Ruby的VM内存分配的碎片问题，导致Ruby进程几乎无可避免的内存泄漏。其结果就是你必须实时监控Ruby进程的运行情况，一旦发现内存使用超过限额，则必须果断的杀掉进程重起。比方说现在很多流行的Rails网站都是用monit去监控mongrel实例，一旦发现内存使用超过限额就杀掉重起。这种监控方式虽然可以有效的解决ruby的内存泄漏问题，但是太过简单粗暴，如果杀掉进程重起的时候，Ruby进程正好在处理请求，那么该请求是肯定会失败掉的，对于一些极端的情况，似乎很难令人接受这种现象的存在。我现在没有用monit，而是自己写shell脚本来监控(写几行shell就可以搞定的事情没必要那么麻烦搞什么monit)，每天大概能出现两三次这种需要杀掉重起的情况，对比每天要处理将近100 万动态请求来说，可靠性还是达到了99.999%，还算可以。<br /><br />那么将于今年年底发布的ruby 1.9.1能够解决这个问题吗？ 答案是悲观的，1.9的GC并没有本质的提高，可以预见还是会出现无可避免的内存泄漏问题。但是1.9的内存泄漏会比现在的1.8要轻微一些，原因是1.9会对堆空间的内存碎片从小到大进行排序，因此对于内存碎片的利用率要高一些，再加上1.9的GC相对来说更积极主动一些，因此在一定程度上可以减轻内存碎片问题。<br /><br />但不管怎么说，在可以预见的未来，Ruby的内存泄漏问题无可避免，我们还是要做好动不动杀掉ruby进程重起的准备。所以你要好好操练一下monit，或者像我一样，写个shell脚本进行监控，用crontab每隔几分钟跑一下。<br /><br />我们的Rails部署方式是lighttpd+fcgi，用Unix Socket通信，监控脚本示例如下：<br /><br /><pre name="code" class="ruby">#!/bin/sh

. /etc/profile.local

RUBY_HEAP_MIN_SLOTS=600000
RUBY_HEAP_SLOTS_INCREMENT=600000
RUBY_HEAP_FREE_MIN=100000
RUBY_GC_MALLOC_LIMIT=60000000
RAILS_ENV=production
export RUBY_HEAP_MIN_SLOTS RUBY_HEAP_SLOTS_INCREMENT RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN RAILS_ENV

SPAWN=/usr/local/lighttpd/bin/spawn-fcgi
DISPATCH_PATH=/.../yourrailsapp/public/dispatch.fcgi
SOCKET_PATH=/yourlighttpd/socket
PID_PATH=/yourlighttpd/pids

RSS_MAX=307200

for PSDATA in `ps -e v | grep dispatch.fcgi | awk '{print $1 ":" $8 }'`
do
  RSS=${PSDATA#*:}
  PID=${PSDATA%:*}
  if [ $RSS -ge $RSS_MAX ]; then
    echo 
    echo `date`
    echo "----------------------------------------"
    echo "PID["$PID"]: RSS="$RSS"KB is too big!"
    for num in 0 1 2 3 4 5 6 7 8 9
    do
      if [ $PID -eq `cat $PID_PATH/javaeye.pid-$num` ]; then
        echo "PID["$PID"] using socket: "$num
        kill -9 $PID
        rm -rf $SOCKET_PATH/javaeye.socket-$num
        $SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num
      fi
    done
  fi
done

sleep 10

for num in 0 1 2 3 4 5 6 7 8 9
do
  if [ ! -d /proc/`cat $PID_PATH/javaeye.pid-$num` ]; then
    echo
    echo "Ruby Server using socket: "$num" had been crashed, need to be starting..."
    rm -rf $SOCKET_PATH/javaeye.socket-$num
    $SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num
  fi
done </pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://tales.javaeye.com/topic/235937" style="color:red;">已有 <strong>8</strong> 人发表回复，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 02 Sep 2008 23:41:16 +0800</pubDate>
        <link>http://www.javaeye.com/topic/235937</link>
        <guid>http://www.javaeye.com/topic/235937</guid>
      </item>
  </channel>
</rss>
