﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-上善若水-随笔分类-GemFire</title><link>http://blogjava.net/DLevin/category/54889.html</link><description>In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation.
To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra</description><language>zh-cn</language><lastBuildDate>Thu, 13 Aug 2015 10:48:42 GMT</lastBuildDate><pubDate>Thu, 13 Aug 2015 10:48:42 GMT</pubDate><ttl>60</ttl><item><title>Log4J引起的程序“装死”</title><link>http://www.blogjava.net/DLevin/archive/2015/08/13/426751.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Thu, 13 Aug 2015 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2015/08/13/426751.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/426751.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2015/08/13/426751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/426751.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/426751.html</trackback:ping><description><![CDATA[<h2>问题起因</h2>
依然是在使用GemFire的集群中，我们发现偶尔会出现一些GemFire的Function执行特别慢，并且超过了两分钟（为了保证数据的一致性，我们在写之前需要先拿一个Lock，因为不能每个Key都对应一个Lock，因而我们使用了Guava的Stripe Lock（关于Stripe Lock可以参考<a href="http://www.blogjava.net/DLevin/archive/2013/12/25/407990.html">这里</a>），而且这个Lock本身我们指定了2分钟的超时时间，因而如果写超过两分钟，我们就会收到Exception）。这个问题其实已经困扰了我们好几年了，刚前段时间，我们发现长时间的Stop-The-World GC会引起这个问题，而且这种时候很多时候会引起那个节点从集群中退出，并不是所有的这种错误都有GC的问题，我特地查了GC的日志，有些这种写超过两分钟的情况下，GC一直处于非常健康的状态，而且查了GemFire的日志和我们自己的日志，也没有发现任何异常。由于我们每个数据保留两分份拷贝，也就是说每次数据写都要写两个节点，两分钟对CPU来说可以做太多的事情，因而只有IO才能在某些时候产生这种问题，在问题发生的时候也没有任何overflow数据，而且本地操作，即使对IO来说2分钟也是一个非常长的时间了，因而我们只能怀疑这是写另一个节点引起的，对另一个节点，它是在同一个Data Center中，而且基本是在同一个Chasis内部，因而它们之间小于1M的数据量通信也不太可能花去2分钟的时间，所以剩下的我们就只能怀疑网络的问题了，比如数据丢包、网络抖动、网络流量太大一起传输变慢等，但是我们没有找到任何相关的问题。所以我们很长一段时间素手无策，只能怪GemFire闭源，我们不知道这两分钟是不是GemFire自己内部在做一些不为人知的事情，因而太忙了而每来得及处理我们的写请求。虽然我一直觉得不管在处理什么炒作，两分钟都没有响应根本无法解释的通，更何况GemFire节点之间并没有报告有任何异常，或者像以前发现的一个节点向Locator举报另一个节点没有响应的问题，Locator自己也能很正常的向那个节点发送新的成员信息（View），因而看起来向是这个节点虽然花了两分钟多来写一个数据，但是它还是有响应的，有点&#8220;假死&#8221;的赶脚。<br />
<br />
<h2>问题发现</h2>
这个问题这么几年以来时不时的就会发生，而且因为以前花的时间太多了，而且也没有找到任何出错的地方，现在索性不去花太多时间在上面了，更何况这个它很长时间才发生一次，并且今年以来就一直没发生过，直到前几周出现一次，我有点不信邪的重新去看这个问题，依然没有找到任何可疑的地方，GC日志、应用程序日志、GemFire自己的日志、网络、CPU使用情况等所有的都是正常的，除了问题发生的那个时刻，应用程序没有任何日志，另外在问题发生之前出现过Log4J日志文件的Rolling（我们使用RollingFileAppender，并且只保留20个日志文件），但是Log4J日志文件Roll的日志出现了断结，在开始要Roll到真正完成Roll中间还有几行GemFire自身的日志，此时我并没有觉得这个是有很大问题的，因为我始终觉得Log4J除了它自己提到平均对性能有10%的影响以外，它就是一个简单的把日志写到文件的过程，不会影响的整个应用程序本身，因为它太简单了，直到今天这个问题再次出现，依然没有任何其他方面的收获，所有的地方都显示正常状态，甚至我们之前发现的网卡问题今天也没有发生，然而同样是出问题的两分钟没有出现应用程序日志，日志文件Roll的日志和上次类似，开始Roll到结束出现GemFire日志的交叉。
<div><fieldset><legend>最近一次发生的日志</legend>
<div>[info 2015/08/12 01:56:07.736 BST &#8230;] ClientHealthMonitor: Registering client with member id &#8230;</div>
<div>log4j: rolling over count=20971801</div>
<div>log4j: maxBackupIndex=20</div>
<div>[info 2015/08/12 01:56:12.265 BST &#8230;] ClientHealthMonitor: Unregistering client with member id &#8230;</div>
<div>&#8230;&#8230;</div>
<div>[info 2015/08/12 01:56:23.773 BST &#8230;] ClientHealthMonitor: Registering client with member id &#8230;</div>
<div>log4j: Renaming file logs/&#8230;.log.19 to logs/&#8230;.log.20</div>
</fieldset></div>
<div><fieldset><legend>一周前发生的日志</legend>
<div>[info 2015/08/04 01:43:45.761 BST &#8230;] ClientHealthMonitor: Registering client with member id &#8230;</div>
<div>log4j: rolling over count=20971665</div>
<div>log4j: maxBackupIndex=20</div>
<div>&#8230;&#8230;</div>
<div>[info 2015/08/04 01:45:25.506 BST &#8230;] ClientHealthMonitor: Registering client with member id &#8230;</div>
<div>log4j: Renaming file logs/&#8230;.log.19 to logs/&#8230;.log.20</div>
</fieldset></div>
<div>看似这个是一个规律（套用同事的一句话：一次发生时偶然，两次发生就是科学了）。然而此时我其实依然不太相信Log4J是&#8220;凶手&#8221;，因为我一直觉得Log4J是一个简单的日志输出框架，它要是出问题也只是它自己的问题，是局部的，而这个问题的出现明显是全局的，直到我突然脑子一闪而过，<strong>日志打印的操作是synchronized，也就是说在日志文件Roll的时候，所有其它需要打日志的线程都要等待直到Roll完成，如果这个Roll过程超过了2分钟，那么就会发生我们看到的Stripe Lock超时，也就是发生了程序&#8220;假死&#8221;的状态。</strong>重新查看Log4J打印日志的方法调用栈，它会在两个地方用synchronized，即同一个Category（Logger）类实例：<br />
<div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;callAppenders(LoggingEvent&nbsp;event)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;writes&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(Category&nbsp;c&nbsp;=&nbsp;<span style="color: #0000FF; ">this</span>;&nbsp;c&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>;&nbsp;c=c.parent)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000;">&nbsp;Protected&nbsp;against&nbsp;simultaneous&nbsp;call&nbsp;to&nbsp;addAppender,&nbsp;removeAppender,<img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">synchronized</span>(c)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(c.aai&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writes&nbsp;+=&nbsp;c.aai.appendLoopOnAppenders(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!c.additive)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
。。。<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
</div>以及同一个Appender在doApppend时：<br /><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">synchronized</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;doAppend(LoggingEvent&nbsp;event)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>.append(event);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>而Roll的过程就是在append方法中，进一步分析，在下面两句话之间，他们分别花费了超过100s和超过11s的时间：</div><div>log4j: maxBackupIndex=20<br />。。。</div><div>log4j: Renaming file logs/&#8230;.log.19 to logs/&#8230;.log.20</div><div>而这两句之间只包含了两个File.exists()，一个File.delete()，一个File.rename()操作：</div><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;rollOver()&nbsp;{<br />&nbsp; &nbsp; &nbsp; 。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(maxBackupIndex&nbsp;&gt;&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000;">&nbsp;Delete&nbsp;the&nbsp;oldest&nbsp;file,&nbsp;to&nbsp;keep&nbsp;Windows&nbsp;happy.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;File(fileName&nbsp;+&nbsp;'.'&nbsp;+&nbsp;maxBackupIndex);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(file.exists())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renameSucceeded&nbsp;=&nbsp;file.delete();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;maxBackupIndex&nbsp;-&nbsp;1;&nbsp;i&nbsp;&gt;=&nbsp;1&nbsp;&amp;&amp;&nbsp;renameSucceeded;&nbsp;i--)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;File(fileName&nbsp;+&nbsp;"."&nbsp;+&nbsp;i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(file.exists())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;File(fileName&nbsp;+&nbsp;'.'&nbsp;+&nbsp;(i&nbsp;+&nbsp;1));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogLog.debug("Renaming&nbsp;file&nbsp;"&nbsp;+&nbsp;file&nbsp;+&nbsp;"&nbsp;to&nbsp;"&nbsp;+&nbsp;target);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renameSucceeded&nbsp;=&nbsp;file.renameTo(target);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp; &nbsp; &nbsp; 。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><div><h2>NFS简单性能测试和分析</h2>因而我对NFS的性能作了一些简单测试：</div><div>只有一个线程时，在NFS下rename性能：</div><div>1 file: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3ms</div><div>10 files: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;48ms</div><div>20 files: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;114ms</div><div>相比较，在本地磁盘rename的性能：</div><div>1 file: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1ms</div><div>3 files: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1ms</div><div>10 files: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3ms</div><div>对NFS和本地磁盘写的性能（模拟日志，每行都会flush）：</div><table border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse;">  <tbody><tr style="height:13.4pt">   <td width="139" valign="top" style="width: 1.45in; border: 1pt solid windowtext; padding: 0in 5.4pt; height: 13.4pt;">   <p>&nbsp;</p>   </td>   <td width="78" valign="top" style="width: 58.5pt; border-style: solid solid solid none; border-top-color: windowtext; border-right-color: windowtext; border-bottom-color: windowtext; border-top-width: 1pt; border-right-width: 1pt; border-bottom-width: 1pt; padding: 0in 5.4pt; height: 13.4pt;">   <p><span style="color:#1F497D">NFS</span></p>   </td>   <td width="78" valign="top" style="width: 58.5pt; border-style: solid solid solid none; border-top-color: windowtext; border-right-color: windowtext; border-bottom-color: windowtext; border-top-width: 1pt; border-right-width: 1pt; border-bottom-width: 1pt; padding: 0in 5.4pt; height: 13.4pt;">   <p><span style="color:#1F497D">LOCAL</span></p>   </td>  </tr>  <tr>   <td width="139" valign="top" style="width: 1.45in; border-style: none solid solid; border-right-color: windowtext; border-bottom-color: windowtext; border-left-color: windowtext; border-right-width: 1pt; border-bottom-width: 1pt; border-left-width: 1pt; padding: 0in 5.4pt;">   <p><span style="color:#1F497D">1 writer, 11M</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">443ms</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">238ms</span></p>   </td>  </tr>  <tr>   <td width="139" valign="top" style="width: 1.45in; border-style: none solid solid; border-right-color: windowtext; border-bottom-color: windowtext; border-left-color: windowtext; border-right-width: 1pt; border-bottom-width: 1pt; border-left-width: 1pt; padding: 0in 5.4pt;">   <p><span style="color:#1F497D">1 writer, 101M</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">2793ms</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">992ms</span></p>   </td>  </tr>  <tr>   <td width="139" valign="top" style="width: 1.45in; border-style: none solid solid; border-right-color: windowtext; border-bottom-color: windowtext; border-left-color: windowtext; border-right-width: 1pt; border-bottom-width: 1pt; border-left-width: 1pt; padding: 0in 5.4pt;">   <p><span style="color:#1F497D">10 writers, 11M</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">~4400ms</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">~950ms</span></p>   </td>  </tr>  <tr>   <td width="139" valign="top" style="width: 1.45in; border-style: none solid solid; border-right-color: windowtext; border-bottom-color: windowtext; border-left-color: windowtext; border-right-width: 1pt; border-bottom-width: 1pt; border-left-width: 1pt; padding: 0in 5.4pt;">   <p><span style="color:#1F497D">10 writers, 101M</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">~30157ms</span></p>   </td>   <td width="78" valign="top" style="width:58.5pt;border-top:none;border-left:none;   border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;   padding:0in 5.4pt 0in 5.4pt">   <p><span style="color:#1F497D">~5500ms</span></p>   </td>  </tr></tbody></table><div><br />一些其他的统计：</div><div><strong>100同时写:</strong></div><div>Create 20 files spend: 301ms</div><div>Renaming 20 files spends: 333ms</div><div>Delete 20 files spends: 329ms</div><div></div><div><strong>1000同时写:</strong></div><div>Create 20 files spend: 40145ms</div><div>Renaming 20 files spends: 39273ms<br /></div><div><strong>而在1000个同时写的过程中，重命名：</strong></div><div>Rename file: LogTest1.50 take: <strong>36434ms</strong></div><div>Rename file: LogTest1.51 take: <strong>39ms</strong></div><div>Rename file: LogTest1.52 take: <strong>34ms</strong><br /></div><div>也就是说在这个模拟过程中，一个文件的rename超过36s，而向我们有十几台机器同时使用相同的NFS，并且每台机器上都跑二三十个程序，如果那段时间同时有上万个的日志写，可以预计达到100s情况是可能发生的。</div><div>关于NFS性能的问题，在《构建高性能WEB站点》的书（330页）中也有涉及。简单的介绍，NFS由Sun在1984年开发，是主流异构平台实现文件共享的首选方案。它并没有自己的传输协议，而是使用RPC（Remote Procedure Call）协议（应用层），RPC协议默认底层基于UDP传输，但是自己实现在丢包时的重传机制，而且NFS服务器采用多进程模型，默认进程为4，但是一般都会调优增加服务进程数，然而&#8220;不管怎么对NFS进行性能优化，NFS注定不适合作为I/O密集型文件共享方案，但可以作为一般用途，比如提供站点内部的资源共享，它的优势在于容易搭建，而且可以减少不必要的数据冗余。&#8221;</div><div>可以使用命令：&#8220;nfsstat -c&#8221;获取对NFS服务器的操作的简单统计，具体可以参考《构建高性能WEB站点》的相关章节，里面还有更详细的对NFS服务器性能的测试。</div><div><br /><h2>总结</h2><strong>从这个事件我总结了两件事情：</strong></div><div>1. 日志的影响可能是全局性的，因而要非常小心，一个耗时的操作可能引起程序的&#8220;假死&#8221;，因而要非常小心。</div><div>2. 虽然把日志打印在NFS上，对大量的日志文件查找会方便很多，但是这是一个很耗性能的设计，特别是当大量的程序共享这个NFS的时候，因而要尽量避免。</div><img src ="http://www.blogjava.net/DLevin/aggbug/426751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2015-08-13 16:28 <a href="http://www.blogjava.net/DLevin/archive/2015/08/13/426751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java CMS GC 361s引发的血案</title><link>http://www.blogjava.net/DLevin/archive/2015/08/01/426418.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Fri, 31 Jul 2015 19:02:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2015/08/01/426418.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/426418.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2015/08/01/426418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/426418.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/426418.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 文章从Java CMS GC花费361s后引起GemFire节点掉出集群过程中各个节点交互的详细流程以及日志情况，重点介绍了ParNew＋CMS GC promotion failed和concurrent mode failure产生的原因以及解决方案。解决方案从两方面入手：JVM参数调优和减少类的创建，其中JVM参数调优过程中详细介绍了ParNew和CMS的工作原理、调优参数、各种不同情况下产生的GC日志解释；着重于避免Full GC引起长时间停顿的问题。&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2015/08/01/426418.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/426418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2015-08-01 03:02 <a href="http://www.blogjava.net/DLevin/archive/2015/08/01/426418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>