﻿<?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-西湖边的穷秀才-文初</title><link>http://www.blogjava.net/cenwenchu/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 10 Jan 2009 04:47:35 GMT</lastBuildDate><pubDate>Sat, 10 Jan 2009 04:47:35 GMT</pubDate><ttl>60</ttl><item><title>精武门之Web安全研讨会首日感受</title><link>http://www.blogjava.net/cenwenchu/archive/2008/12/17/246975.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Wed, 17 Dec 2008 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/12/17/246975.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/246975.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/12/17/246975.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/246975.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/246975.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 应该是去年的年初，我受到普元公司的邀请去参加了一次SCA、SOA的技术交流会，当时也是自己第一次去和那么多陌生的朋友交流技术心得，同时也被普元公司的这种纯技术性的交流方式所打动，也在想哪一天阿里巴巴也能够举办一次这样的小规模有针对性地技术交流会那会让我们这些技术人员收益菲浅。一年后的今天，当老大问我有个这样的会议是否要参加的时候，自己毫不犹豫地报了名，虽然看起来和自己专注的工作不是很相关，但是还是那个想法：首先不了解是无法知道是否和自己相关与否，其次就算不相关，多学多听，触类旁通的技术延展只会给自己带来更多的想象空间和创新思维。</p>
<p>&nbsp;&nbsp;&nbsp; 按照会议安排，早晨有两个讲座，下午有四个讲座，每个讲座1个小时左右。第一个出场的是腾讯的安全中心总监杨勇，整个演讲很轻松，首先是对腾讯的整体产品结构和背景作了一下阐述，然后就从安全中心这个整体来讲述安全对于腾讯的意义，如何实施以及一些流程的制定。没有过多的牵涉安全问题的细节，着重是讲述了安全中心面临的四个方面的问题，以及通过什么手段去解决。这其实和他本身所处的工作职责来说相符合，如果仅仅只是来讲某一个安全技术应用，那么就有些太过狭隘了。不过在提问的时候一个问题的回答让我还是留有一些印象的，主持人收集到一个问题：&#8220;腾迅安全中心的建设初期遇到的最迫切需要解决的问题是什么？&#8221;，他回答道：&#8220;其实腾讯安全中心从建设初期到现在一直面临各种迫切的问题，只是随着时间的不同而不同的演变，最早的协议安全到客户端安全到奥运期间的信息安全都是一个发展的阶段&#8221;（因为没有ppt以及记录，因此描述的可能不太准确）。但是这个思想任何技术行业都是一样的，时代不同关注不同，需要解决的问题也是在发展的。</p>
<p>&nbsp;&nbsp; 第二个议题是Discuz的剑心带来的&#8220;web应用程序中的字符集攻击&#8221;，这个演讲就相对来说比较注重专业细节方面的阐述。作为互联网应用开发者，使用Java的人第一堂课就是中文乱码，很多人只看到如何去配置或者写一点转换语句就可以解决，但是对于编码方式就不求甚解，ISO-8859-1,GB2312,UTF-8,UTF-16区别是什么，为什么会引起乱码。其实了解了编码的原理就很能够解释如何会产生乱码，同时产生乱码的时候也可以根据乱码的情况了解可能是因为什么编码转化造成的（阿里巴巴的宝宝写了一篇很详细的文章说了这个问题，进入公司以后我也是看了那片文章才系统地对编码方式做了完整的了解，以前都是碎片）。不过今天听了这个演讲，到让我知道了原来编码方式也被人用来攻击。其实基本的思想主要就是一点：由于信息转发中对于不同编码解析的方式不同或者是过滤不同，导致出现一些漏洞。通俗的比喻就是刺杀秦始皇的图穷匕见，侍卫就好比第一层把关的信息转发者认为着幅图没有威胁，但是真的按照刺客的处理方式那么就是一个最好的攻击性工具。记得我在和同事探讨REST对于Http协议的使用时说最重要的就是REST不再使用Http协议作为传输承载协议而是作为业务协议，那么解析业务的时候究竟是分析协议中指定的编码方式还是内容中的编码方式，结果会大不一样，同时作为安全人员的角度来看，这也会存在一种安全隐患。所以其实任何一种错误都可以被利用作为攻击的手段。</p>
<p>&nbsp;&nbsp;&nbsp; 下午的议题一共有四个，虽然时间比较长一直连续讲到6点多，但是就像主持人讲的，每一个人都&#8220;坚持&#8221;下来了，呵呵，当然坚持并不是因为不好听，而是做在那儿听比写代码要累很多，当然讲课的同学们也是十分辛苦的。下午第一个演讲的是team509的创始人吴石，讲的主题是&#8220;部分软件安全的思考&#8221;，内容专业化很强，对很多比较底层的安全问题（操作系统等）作了一些介绍，当然对于我这个门外汉只能听懂个大概意思，不过还是有所了解那些名词的意思到底是什么。第二个是微软的大牛蛙同学，也是安全领域专家讲述了一下微软的SDL(Security Development Lifecycle)，望名生意，安全实施的流程化。第三个演讲是两位同学做的，也是我下午听得比较有感触地，先是网名余弦（钟晨鸣）北京知道创宇信息技术公司的安全研究员，讲的是CSRF蠕虫技术，从一个黑客的角度来阐述CSRF的原理以及危害性。这部分比较技术化一些，但是由于和我关注的Web安全也比较相关一些，所以听起来也不是比较迷糊。虽然听着他讲CSRF，但是其实我脑子里面已经在考虑关于Open API的一些安全问题。其实在阿里软件承载淘宝的API过程中，对于客户端的安全问题就一直都在谈，但是对于SIP来说总是鞭长莫及，因为服务集成平台只会保障ISV和ISP之间的信息交互的真实性，但是用户是否由于ISV的技术问题导致信息伪造提交，那么就不得而知，但是最后表现出来的结果就是ISP的Open API计划为ISP带来了更多的安全隐患，也就是说原来淘宝一家漏洞，以后可能会是千千万万家ISV的漏洞，其实这也是上面几个演讲提到的合作风险问题，第三方的技术能力不得而知，同时产生的风险也会很难控制。其实从这里也多多少少看出来为什么FaceBook，myspace，最早对于用户安全隐私数据的开放不仅仅是开放了数据API，同时也会有整一套上层框架支持，其实也是出于开发者能力不足引起隐私数据被恶意修改而作的防护措施。那么现在Open 用户的数据特别是以后涉及到金额的api如何保证isv不欺诈，isv不被欺骗，这可能是后续需要更加重视的问题。同时，在听了CSRF的攻击中谈到的对于资源定位猜测以及操作的时候，让我对REST的风格又打了一个冷颤，REST对于资源的规划和定位十分容易，但是这也为这类攻击提供了便利，同时对于资源操作依赖于Http协议，也会让资源的安全性打了折扣，这需要对Open API开发人员做更多的安全工作指导，或者提供安全框架来防范Open API可能会产生的安全漏洞。紧接着后面的演讲是北京知道创宇信息技术公司的创始人赵伟，应该是业界比较资深的专家了，本来的议题是&#8220;恶意网站检测&#8221;，不过他还是讲了他这些年来的一些经历以及安全领域的黑色产业链的问题。平时这方面关注的不多，不过今天这一番交流，让我对安全领域的发展以及现况有所了解，甚至有时候就觉得现在上网就算装了一大堆东西还是感觉在&#8220;裸奔&#8221;。最后一个议题是51.com的郑歆炜讲的&#8220;运维安全经验谈&#8221;，总结了运维所面对的问题以及解决方案，协调，沟通，总结，知识库，其实这些对于开发人员来说何尝不是呢。最后小黑作了一个简短的总结，同时预报了明天他会做一次附加的构建安全Web架构的讲座，期待明天半天的研讨会和附加讲座。</p>
<p>&nbsp;&nbsp;&nbsp; 好久没有踏踏实实地坐着好好听课了，这次一天半的学习对于自己来说也算是一次新知识的扫盲，同时也为自己后续的工作可能存在的问题或者可以借鉴的知识作一个铺垫。</p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/246975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-12-17 22:32 <a href="http://www.blogjava.net/cenwenchu/archive/2008/12/17/246975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>技术方案的讨论过程来看化繁为简</title><link>http://www.blogjava.net/cenwenchu/archive/2008/12/12/245901.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Fri, 12 Dec 2008 03:49:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/12/12/245901.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/245901.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/12/12/245901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/245901.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/245901.html</trackback:ping><description><![CDATA[Author:<span style="font-family: 宋体">文初</span>
<p>Blog: <a href="http://blog.csdn.net/cenwenchu79/">http://blog.csdn.net/cenwenchu79/</a></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体">问题</span></strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">小丹同学在旺旺上问我是否可以用</span>Memcached<span style="font-family: 宋体">实现简易消息中间件类似的功能。觉得这个需求很奇怪，就问了一下具体的应用场景，然后小丹就上来和我具体的谈了究竟需求是什么。其实小丹的应用场景是这样的：客户需要分析一些业务数据，但是业务数据又是很庞大的，在原有系统每天晚上都有一次日分析，将业务数据分析并且归档，但是如果要产生即时分析的效果，用原有系统无法实现，因为当天的数据内容没有被分析，同时如果即时的去分析并且累加到历史分析数据上，性能也不能满足需求，因此考虑通过消息机制来实现异步分析，至于异步处理的时间容忍度，可以通过配置来实现，同时希望异步分析是可线性扩展的，支持集群，提高效率。为什么不直接使用中间件呢？高并发的稳定性，维护的成本，性能要求，使用成本，这些直接就排出了直接去使用中间件的想法。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体">起始方案的讨论</span></strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">在回到小丹最初提到是否可以通过</span>Memcached<span style="font-family: 宋体">来实现类似于简易消息中间件的问题上来。首先是否将消息队列作为一个对象保存在</span>Memcached<span style="font-family: 宋体">中，这种做法明显不支持高并发的情况，因为</span>Cache<span style="font-family: 宋体">本身的</span>get,put<span style="font-family: 宋体">无法保证事务。在</span>Memcached<span style="font-family: 宋体">中只有计数器是支持高并发的操作，因此考虑是否使用计数器并且按照一定规则来生成</span>key<span style="font-family: 宋体">，通过对计数器的增减来让不同消费者获取到不同的消息，这种机制最大的问题在于：</span>1.<span style="font-family: 宋体">轮询的压力不小（小丹希望是订阅者模式，</span>Push<span style="font-family: 宋体">过去而不是</span>Pull<span style="font-family: 宋体">）。</span>2.<span style="font-family: 宋体">计数器增减不论怎么做都实现的是栈而不是队列。那么是否使用我扩展的</span>Memcached<span style="font-family: 宋体">的</span>KeySet<span style="font-family: 宋体">，这点我自己就反对了，这个功能效率很低，而且对于</span>Memcached<span style="font-family: 宋体">本身在高并发下操作是否有影响还不得而知。问题越绕越走向死胡同了。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体">方案的转变</span></strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong><span style="font-family: 宋体">转换思路，重新分析小丹的需求，究竟哪几点是他真实需要的：</span>1.<span style="font-family: 宋体">通过消息方式解耦</span>Web<span style="font-family: 宋体">应用和业务分析处理。</span>2.<span style="font-family: 宋体">消息必须较为及时的传递到业务分析模块。</span>3.<span style="font-family: 宋体">业务分析模块需要支持集群方式线性扩展性能。实现这些需求真的需要简单的消息中间件或者集中式存储么？看看下图的结构：<br />
</span></p>
<p align="left"><br />
<div align="center"><img height="480" alt="" src="http://www.blogjava.net/images/blogjava_net/cenwenchu/AsynMessage.jpg" width="465" border="0" /></div>
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">从图上可以看出这么几个问题：</span>1.<span style="font-family: 宋体">消息中间件本身处于单点，如果需要扩展或者消息本地化增加了复杂度。</span>2.<span style="font-family: 宋体">对于消息的获取是采用</span>push<span style="font-family: 宋体">还是</span>pull<span style="font-family: 宋体">，如果是</span>push<span style="font-family: 宋体">那么需要中间件支持订阅者的维护，如果是</span>pull<span style="font-family: 宋体">，则需要考虑并发以及性能问题。</span>3.<span style="font-family: 宋体">消息的即时性，这个还是依赖于消息中间件的实现机制。总的来说，如果要通过集中式缓存方式实现消息中间件的简单功能，还是有很多问题。那是否直接使用消息中间件的第三方支持呢，其实又回到了最初提出的不使用的缘由。这么设计是否太复杂呢？</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">回过头来看看</span>Memcached<span style="font-family: 宋体">的使用情况，突然发现其实事情可以简单来说，我记得写过一些说明来解释为什么我说</span>Memcached<span style="font-family: 宋体">是集中式缓存而不是分布式缓存，其实是客户端的分发算法让很多人觉得好像分布了数据和可无限扩展。其实这种技术结合</span>Hadoop <span style="font-family: 宋体">的</span>HDFS<span style="font-family: 宋体">的部分设计思路，可以给出一个比较好的解决方案。看看下图的结构设计：<br />
<br />
<div align="center"><img height="445" alt="" src="http://www.blogjava.net/images/blogjava_net/cenwenchu/AsynMessage2.jpg" width="582" border="0" /></div>
<br />
<br />
</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">上图去掉了消息中间件的角色，增加了</span>Asyn Processor Manager<span style="font-family: 宋体">的角色，但是此角色也可以去掉，更为简化的实现需求，增加</span>Asyn Processor Manager<span style="font-family: 宋体">的功能仅仅是为了提供动态增减</span>Asyn Processor<span style="font-family: 宋体">的功能。具体说一下流程：</span></p>
<p style="margin-left: 57.75pt; text-indent: -36.75pt">1．<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Web<span style="font-family: 宋体">应用启动时，读取本地配置获取</span>Asyn Processor<span style="font-family: 宋体">列表载入内存，同时根据</span>Asyn Processor Manager<span style="font-family: 宋体">的配置去发起请求获取</span>Asyn Processor<span style="font-family: 宋体">最新的可用列表（如果无法获取，则以本地的为准）。</span></p>
<p style="margin-left: 57.75pt; text-indent: -36.75pt">2．<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Web<span style="font-family: 宋体">应用根据本地实现的分发算法（最简单就是采用</span>key hash<span style="font-family: 宋体">），来选择</span>Asyn Processor<span style="font-family: 宋体">，发送请求处理的消息。</span></p>
<p style="margin-left: 57.75pt; text-indent: -36.75pt">3．<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">如果</span>Asyn Processor Manager<span style="font-family: 宋体">不存在，</span>Web<span style="font-family: 宋体">应用也可以实现定时发起</span>query status<span style="font-family: 宋体">请求来确认</span>Asyn Processor<span style="font-family: 宋体">的存活状态，并且更新，保证消息的正常发送。如果</span>Asyn Processor Manager<span style="font-family: 宋体">存在，那么确认</span>Asyn Processor<span style="font-family: 宋体">状态是否存活可以由</span>Asyn Processor Manager<span style="font-family: 宋体">来做（</span>Push<span style="font-family: 宋体">或者</span>Pull<span style="font-family: 宋体">），而</span>Web<span style="font-family: 宋体">应用则可以使用对</span>Asyn Processor Manager<span style="font-family: 宋体">的定时查询来获得最新的</span>Asyn Processor<span style="font-family: 宋体">列表。</span></p>
<p style="margin-left: 57.75pt; text-indent: -36.75pt">4．<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Asyn Processor Manager<span style="font-family: 宋体">可以提供增加和删除</span>Asyn Processor<span style="font-family: 宋体">的接口，这样就可以支持</span>Asyn Processor<span style="font-family: 宋体">的增加和删除，但也正因为</span>Asyn Processor Manager<span style="font-family: 宋体">的单点易于注册和管理</span>Asyn Processor<span style="font-family: 宋体">，也增加了单点的风险，因此每一台</span>Web<span style="font-family: 宋体">应用需要对</span>Asyn Processor Manager<span style="font-family: 宋体">不可用作好本地化配置的后备策略。</span></p>
<p style="margin-left: 57.75pt; text-indent: -36.75pt">5．<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">使用</span>Http<span style="font-family: 宋体">协议作为消息传输协议，这样避免</span>SA<span style="font-family: 宋体">去维护端口的麻烦，同时也能够充分利用</span>REST<span style="font-family: 宋体">的方式来完成业务逻辑（</span>Options<span style="font-family: 宋体">方法可以用于心跳，</span>Put<span style="font-family: 宋体">、</span>Delete<span style="font-family: 宋体">可以用于</span>Processor<span style="font-family: 宋体">的增减（设置</span>Http Head<span style="font-family: 宋体">认证方式即可解决安全问题），</span>Get<span style="font-family: 宋体">方式获取信息（</span>xml,json<span style="font-family: 宋体">等等格式可以很容易处理））。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">上面的方案可以看出，如果去掉</span>Asyn Processor Manager<span style="font-family: 宋体">，其实方案很简化，就是每一个客户端有一层类似于</span>Memcached<span style="font-family: 宋体">客户端的分发机制，同时比</span>Memcached<span style="font-family: 宋体">免去了对于连接池维护的复杂性，仅仅只需要维护状态标示即可。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">最后还嘱咐小丹对于</span>Asyn Processor<span style="font-family: 宋体">的设计需要合理化，这部分需要支持消息接受和处理的并行处理，提高</span>Asyn Processor<span style="font-family: 宋体">的处理能力，同时通过分页批量处理消息的方式减少对于</span>DB<span style="font-family: 宋体">的压力（当然需要根据具体的时效性设置消息页的大小以及消息页</span>Flush<span style="font-family: 宋体">的时间）。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体">后话</span></strong></p>
<span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10.5pt; font-family: 宋体">上面的方案可能不是最好或者最优的，这里仅仅只是分享一下自己解决这个问题的一些心得。这此的方案讨论也走了一些弯路，有时候在做任何选择以前首先需要考虑的是到底自己需求是什么，然后再去考虑选择什么技术去实现。同时尽量还是那句老话</span><span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">&#8221;Make it Simple&#8221;</span><span style="font-size: 10.5pt; font-family: 宋体">，做技术的人总是喜欢做的很复杂，功能很强大，但是最后迷失了最初的目标，忙于去完善那些</span><span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">80%</span><span style="font-size: 10.5pt; font-family: 宋体">没有用的功能，却没有去做好那</span><span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">20%</span><span style="font-size: 10.5pt; font-family: 宋体">客户最</span><span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">Care</span><span style="font-size: 10.5pt; font-family: 宋体">的功能。化繁为简，见招拆招，才能四量拨千斤。</span>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/245901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-12-12 11:49 <a href="http://www.blogjava.net/cenwenchu/archive/2008/12/12/245901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>星巴克REST案例分析读后感</title><link>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245447.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Wed, 10 Dec 2008 03:32:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245447.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/245447.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245447.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/245447.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/245447.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp; 今天收到InfoQ的推荐邮件，看了标题就很感兴趣，花了一些时间一看，果然是很不错的一个案例分析，同时也让自己学到了不少。大致罗列一下看后的一些文章重点内容。案例地址：<a href="http://www.infoq.com/cn/articles/webber-rest-workflow">http://www.infoq.com/cn/articles/webber-rest-workflow</a></p>
<p>&nbsp;&nbsp;&nbsp; 1.通过REST服务请求完成状态迁移，同时合理利用OPTIONS来查看资源操作权限。</p>
<p>&nbsp;&nbsp;&nbsp; 2.合理利用Http Heads来返回资源URI，以及通过ErrorCode来确定操作结果，并且作后处理。</p>
<p>&nbsp;&nbsp;&nbsp; 3.通过返回内容指定后续流程资源定位以及操作来实现流程化。</p>
<p>&nbsp;&nbsp;&nbsp; 4.通过Put报头的两种版本比较标示来防止并发修改。（其实也可以优化来做查询缓存的工作）</p>
<p>&nbsp;&nbsp;&nbsp; 5.使用Atom协议来发布和管理资源（Atom是最适合REST风格服务的数据源格式定义）</p>
<p>&nbsp;&nbsp;&nbsp; 6.URI模版的使用建议，慎用，如果确实能够有把握抽象资源定位。</p>
<p>&nbsp;&nbsp;&nbsp; 7.Auth可以通过轻量级Http Head中的Authentication或者WS-*的方式来实现。（也可以通过https实现）</p>
<p>&nbsp;&nbsp;&nbsp; 总的来说，其实整个案例分析下来以后，可以发现如果要使得服务流程化，那么前提就是数据交互格式统一（XML，Atom），然后利用Http协议作为服务协议而非承载协议，利用已有的操作约定，报文头部标示和返回的错误码来完成资源状态迁移的工作，同时通过在返回内容中嵌入流程化内容，使得整个流程可以贯穿。（这里还是简单的流程串联，其实如果在流程规则协议中增加复杂的逻辑定义，则可以实现更为强大的Web workflow）。</p>
<p>&nbsp;&nbsp;&nbsp; 但对于Open API或者类似的REST流程化业务来说，安全其实还是最大的挑战，特别是在对资源的访问控制权限上。当然可以类似于WS-Security提出一套较为安全成熟的方案，但是性能和使用简易性则会大打折扣，也失去了REST本身的优势。</p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/245447.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-12-10 11:32 <a href="http://www.blogjava.net/cenwenchu/archive/2008/12/10/245447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Open API 分享</title><link>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245414.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Wed, 10 Dec 2008 02:23:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245414.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/245414.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/12/10/245414.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/245414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/245414.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 下周一应该是我今年最后一次参加内部培训了,所要讲的内容也是我这大半年来都在专注的技术:Open API&amp;SIP。由于文章要在程序员1月刊发表，因此文章暂时不能放在Blog上，不过下周一的培训PPT还是可以分享一下的。有兴趣的集团的同学也可以来阿里软件听。同时也很高兴的看到在csdn的blog在年底冲过了10w，希望明年有更多的分享能够贡献出来^_^</p>
<br />
<embed src="http://www.authorstream.com/player.swf?p=120059_633644487240722500" width="425" height="355" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true"></embed><br />
    <font size="2">Uploaded on authorSTREAM by <a title="More presentations by cenwenchu on authorSTREAM" href="http://www.authorstream.com/User-Presentations/cenwenchu/" target="_blank">cenwenchu</a></font> 
<img src ="http://www.blogjava.net/cenwenchu/aggbug/245414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-12-10 10:23 <a href="http://www.blogjava.net/cenwenchu/archive/2008/12/10/245414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Memcached Cache客户端的一个参数</title><link>http://www.blogjava.net/cenwenchu/archive/2008/11/21/241856.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Fri, 21 Nov 2008 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/11/21/241856.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/241856.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/11/21/241856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/241856.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/241856.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 今天，有一个使用我优化的Memcached cache Client给我发了邮件问到一个参数的作用，觉得还是比较重要的一个参数，因此也说一下，同时也在这里说一下，当前优化过的客户端已经作了几次小的升级，修复了一些边界数据的问题，大家如果在使用的话，最好能够升级。（<a href="http://code.google.com/p/memcache-client-forjava/">http://code.google.com/p/memcache-client-forjava/</a>）</p>
<p>&nbsp;&nbsp; 邮件如下：</p>
<p><font color="#993300">&nbsp;&nbsp; 你好：<br />
&lt;socketpool name="pool0" failover="true" initConn="5" minConn="5"<br />
&nbsp; maxConn="250" maintSleep="5000" nagle="false" socketTO="3000"<br />
&nbsp; aliveCheck="true" &gt;<br />
&nbsp; &lt;servers&gt;10.0.0.16:11111&lt;/servers&gt;<br />
&nbsp; &lt;weights&gt;10&lt;/weights&gt;<br />
&nbsp;&lt;/socketpool&gt;<br />
能解释下maintSleep这个意思么？我看有的资料说吧它设置为0性能更好，能给些建议么？谢谢！！我们现在的PV大约每天500万。</font></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 这个参数是对此连接池维护线程的检查间隔时间的配置，如果配置小于等于0，则将不会有后台线程维护此连接池，参数单位为毫秒，下面解释一下维护连接池的含义，其实就和其他的资源池一样，资源池的目的就是为了解决资源的申请和释放的开销增加系统压力的问题，将资源通过池的方式回收重用，有利于系统性能的提高。memcached cache client 其实是通过socket来和服务端进行通信，建立socket连接也是比较消耗时间的工作，因此配置了池的初始连接数（initConn），最小连接数（minConn），最大连接数（maxConn）。这三者关系如下图，维护他们之间状态转移的就是后台线程。</p>
<p align="center"><img height="370" alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cenwenchu79/EntryImages/20081121/Socket%20pool.jpg" width="562" /></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;后台进程维护资源池的作用就是将有限资源回收，例如数据库连接，如果一台oracle只有500个连接数可以支持，那么如果一个应用都占用了50个闲置，那对于其他需要资源的应用来说无疑是一种浪费。但如果配置了资源管理，但由于应用属于忙时和闲时交替比较频繁的情况，那么如果时间配置的不是很合适，就会达不到原来资源池的作用，资源反复回收和申请。所以对于这个参数的配置，个人觉得一定要配，配置的值需要注意，初始化和最小的值可以是自己预估平时平均并发处理的均值，最大的连接数当然依赖于资源的总数，而维护时间间隔则最好是能够根据闲时和忙时的情况来考虑配置，这样既不会浪费资源，同时也不会使资源池时效。</p>
<p>&nbsp;&nbsp;&nbsp; 顺带说一句，如果对于数据丢失要求不是很苛刻，然后网络情况也不错的时候，可以将<font color="#000000">aliveCheck设置为false，因为如果是true，在每一次发送任何数据操作之前都会去做心跳检查，这个未来也会考虑去优化。</font></p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/241856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-11-21 15:28 <a href="http://www.blogjava.net/cenwenchu/archive/2008/11/21/241856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一句话，一个人</title><link>http://www.blogjava.net/cenwenchu/archive/2008/11/20/241537.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Thu, 20 Nov 2008 00:46:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/11/20/241537.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/241537.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/11/20/241537.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/241537.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/241537.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 一句话：&#8220;不要为做别人已经作过的事情而沾沾自喜，要做就做别人没有做或者做不到的&#8221;。原话可能不是这句了，但是意思差不多，这是上次架构委员会开会的时候，阿里集团新来的首席架构师王坚和我们说的一句话。原因就是集团内或者公司内部资源重复去做一些工作，包括我在内很多程序员就整天津津乐道的去重复做一些工作，对于别人的成果（国外开源除外），总是有些排斥，特别是一些关键性技术，但其实真正的架构师应该关注如何能够找到合适的方法正确高效的解决问题，如何积累技术，而不是重复建设，这点很多人都很清楚，但是真的遇到一些情况的时候，就忘记了这些准则。
<p>&nbsp;&nbsp;&nbsp; 一个人，我们阿软的首席架构师赵进。说到对人能力的佩服，我想对于赵进作为首席架构师的能力，我自己真的是很实实在在的佩服。远了不说，就说最近的关于阿里软件自己的基础组件Cache，当前除了SIP以外，其他两个自主产品的cache都采用的我维护的cache组件，这次做外贸重构，其他的架构师作了一个新的Cache，赵进知道后觉得这个关系到未来的整体基础架构统一性的问题，因此反复找我们几个人谈了很久，当然我也很理解架构师为了项目需求不愿意切换或者改变现有成型代码，但是如果作为一种长远的负责的规划，的却是需要统一起来。期间的困难可想而知，赵进最后找了我们的老大来拍板，结果我老大的一句话把赵进打入冷库，连我们老大都因为担心项目影响的风险而不是很赞成，我可以看出当时赵进的失落，但是在他弃而不舍的精神下，我真的算是感动了，大家一起在作了分析和讨论，最后总算确定了一个不算最满意，但也算是达到目的的一个解决方案。</p>
<p>&nbsp;&nbsp;&nbsp; 那么回顾一下我对赵进的感受，那么就能够体现出如果要成为一个架构师，或者是一个首席架构师应该具有的能力，首先就是微笑，其次就是倾听，再则就是引导，最后就是坚持。微笑可以化解敌意，倾听可以找出问题，引导可以商讨解决方案，坚持可以达到目标。当然双赢之类的就不说了。其实说到能力，在我看来技术方面的能力是可以培养的，要成为技术上的能人，需要专注，坚持和勤奋，但是要成为一个架构师那么最重要的还是胸怀和眼界，能够容纳别人才会让别人接受你，这些说起来都很容易，但是做起来却是很难，因为这和个性也有关系，改变自己的个性需要勇气和时间。</p>
<p>&nbsp;&nbsp;&nbsp; 我现在MSN的名字叫做海纳百川，时时告诉自己有容乃大，整天为了一些细枝末节的重复劳动而沾沾自喜，只会变成井底之蛙，要做就要做别人没有做或者做不到的，多了解一些，多学习一些，站在不到巨人的肩膀上也站到石头上，看得更高才会走得更远。</p>
<p>&nbsp;&nbsp;&nbsp; 一年过去之际，勉励自己改变自己。</p>
<p>&nbsp;&nbsp;&nbsp; 有架构师的能力，却没有宽广的胸怀，那么永远只会停留在一个代码编写者阶段。</p>
<p>&nbsp;&nbsp;&nbsp; 有宽广的胸怀，却只有程序员的能力，那么只要努力就会成为架构师甚至首席架构师。<br />
&nbsp;&nbsp;&nbsp; （打个广告^_^，年底关于Open API的文章由于要发表在杂志上，因此无法在这里贴了，不过到了一月份应该就可以贴了，这篇关于Open API的文章是自己沉淀自己大半年工作的一份总结，也希望能够分享给大家）</p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/241537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-11-20 08:46 <a href="http://www.blogjava.net/cenwenchu/archive/2008/11/20/241537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SIP交流PPT</title><link>http://www.blogjava.net/cenwenchu/archive/2008/10/31/237757.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Fri, 31 Oct 2008 01:53:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/10/31/237757.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/237757.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/10/31/237757.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/237757.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/237757.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 昨天集团架构委员会（虚拟组织）作了第二次交流，各个子公司都说了当前的一些进度，问题和想法，我也大致讲了一下阿里软件的服务集成平台的一些进展和自己的一些思考，这里先贴一下PPT的图片，后面想整理以下关于当前Open API的一些想法以及对Open API Framework的一些思路。</p>
<p>&nbsp;</p>
<a title="幻灯片1 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405303/"><img height="375" alt="幻灯片1" src="http://farm4.static.flickr.com/3004/2987405303_459034cf6e.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片2 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2988263504/"><img height="375" alt="幻灯片2" src="http://farm4.static.flickr.com/3242/2988263504_64cc0e1e8c.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片3 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405335/"><img height="375" alt="幻灯片3" src="http://farm4.static.flickr.com/3277/2987405335_6ccf263713.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片4 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405435/"><img height="375" alt="幻灯片4" src="http://farm4.static.flickr.com/3247/2987405435_6e4a4145e4.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片5 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405363/"><img height="375" alt="幻灯片5" src="http://farm4.static.flickr.com/3175/2987405363_97851e1bec.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片6 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405387/"><img height="375" alt="幻灯片6" src="http://farm4.static.flickr.com/3281/2987405387_2e0aef1f09.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片7 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2988263664/"><img height="375" alt="幻灯片7" src="http://farm4.static.flickr.com/3252/2988263664_c8d2877a7e.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片8 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2988263762/"><img height="375" alt="幻灯片8" src="http://farm4.static.flickr.com/3165/2988263762_6b5bd33a05.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片9 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405465/"><img height="375" alt="幻灯片9" src="http://farm4.static.flickr.com/3269/2987405465_b9da99bea8.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片10 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405533/"><img height="375" alt="幻灯片10" src="http://farm4.static.flickr.com/3139/2987405533_2351510aff.jpg" width="500" /></a>
<p>&nbsp;</p>
<a title="幻灯片11 by wenchu_cenwc, on Flickr" href="http://www.flickr.com/photos/cenwenchu/2987405577/"><img height="375" alt="幻灯片11" src="http://farm4.static.flickr.com/3209/2987405577_d2d7cc92fa.jpg" width="500" /></a>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/237757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-10-31 09:53 <a href="http://www.blogjava.net/cenwenchu/archive/2008/10/31/237757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过GC输出分析内存泄露问题</title><link>http://www.blogjava.net/cenwenchu/archive/2008/10/22/235972.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Wed, 22 Oct 2008 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/10/22/235972.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/235972.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/10/22/235972.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/235972.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/235972.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SIP5.0<span style="font-family: 宋体">以后服务的请求量爆发性增长，因此也暴露了原来没有暴露出来的问题。由于过去一般一个新版本发布周期在一个月左右，因此如果是小的内存泄露，在一个月之内重新发布以后也就看不出任何问题。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">因此这阵子除了优化</span>Memcache<span style="font-family: 宋体">客户端和</span>SIP<span style="font-family: 宋体">框架逻辑以外其他依赖部分以外，对于内存泄露的压力测试也开始实实在在的做起来。经过这次问题的定位和解决以后，大致觉得对于一个大用户量应用要放心的话，那么需要做这么几步。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在</span>GC<span style="font-family: 宋体">输出的环境下，大压力下做多天的测试。（可以在</span> JAVA_OPTS<span style="font-family: 宋体">增加</span>-verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError<span style="font-family: 宋体">）</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">检查</span>GC<span style="font-family: 宋体">输出日志来判断是否有内存泄露。（这部分后面有详细的实例说明）</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">如果出现内存泄露问题，则使用</span>jprofiler<span style="font-family: 宋体">等工具来排查内存泄露点（之所以不一开始使用，因为</span>jprofiler<span style="font-family: 宋体">等工具对于压力测试有影响，使得大压力无法上去，也使问题不那么容易暴露）</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">解决问题，并在重复</span>2<span style="font-family: 宋体">步骤。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">这里对</span>SIP<span style="font-family: 宋体">在</span>jdk1.5<span style="font-family: 宋体">和</span>jdk1.6<span style="font-family: 宋体">下做压力测试的</span>GC <span style="font-family: 宋体">日志来做一个实际的分析对比，通过对比来大致描述一下如何根据输出情况能够了解应用是否存在内存泄露问题。（这里的内存泄露问题就是在以前</span>blog<span style="font-family: 宋体">写过的</span>jdk<span style="font-family: 宋体">的</span>concurrent<span style="font-family: 宋体">包内</span>LinkedBlockingQueue<span style="font-family: 宋体">的</span>poll<span style="font-family: 宋体">方法存在比较严重的内存泄露，调用频率越高，内存泄露的越厉害）</span></p>
<p><span style="font-family: 宋体">两次压力测试都差不多都是两天，测试方案如下：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">开始</span>50<span style="font-family: 宋体">个并发，每个并发每次请求完毕后休息</span>0.1<span style="font-family: 宋体">秒，</span>10<span style="font-family: 宋体">分钟后增长</span>50<span style="font-family: 宋体">个并发，按此规律增长到</span>500<span style="font-family: 宋体">并发。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">旧版本</span>SIP<span style="font-family: 宋体">是在</span>JDK1.5<span style="font-family: 宋体">环境下完成的压力测试，</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">新版本</span>SIP<span style="font-family: 宋体">的</span>JDK<span style="font-family: 宋体">版本是</span>1.6<span style="font-family: 宋体">，</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">压力机和以前一样，是</span>10.2.226.40<span style="font-family: 宋体">，</span>DELL1950<span style="font-family: 宋体">，</span>8CPU<span style="font-family: 宋体">，</span>8G<span style="font-family: 宋体">内存。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">压力机模拟发出对一个需要签名的</span>API<span style="font-family: 宋体">不断的调用请求。</span></p>
<p><span style="font-family: 宋体">看看两个</span>Log<span style="font-family: 宋体">的具体内容（内容很多截取部分做分析）</span></p>
<p><span style="font-family: 宋体">先说一下日志输出的结构：</span>(1.6<span style="font-family: 宋体">和</span>1.5<span style="font-family: 宋体">略微有一些不同，只是</span>1.6<span style="font-family: 宋体">对于时间统计更加细致</span>)</p>
<p>[GC [&lt;collector&gt;: &lt;starting occupancy1&gt; -&gt; &lt;ending occupancy1&gt;, &lt;pause time1&gt; secs] &lt;starting occupancy3&gt; -&gt; &lt;ending occupancy3&gt;, &lt;pause time3&gt; secs]</p>
<p>&lt;collector&gt;GC<span style="font-family: 宋体">收集器的名称</span></p>
<p>&lt;starting occupancy1&gt; <span style="font-family: 宋体">新生代在</span>GC<span style="font-family: 宋体">前占用的内存</span></p>
<p>&lt;ending occupancy1&gt; <span style="font-family: 宋体">新生代在</span>GC<span style="font-family: 宋体">后占用的内存</span></p>
<p>&lt;pause time1&gt; <span style="font-family: 宋体">新生代局部收集时</span>jvm<span style="font-family: 宋体">暂停处理的时间</span></p>
<p>&lt;starting occupancy3&gt; JVM Heap <span style="font-family: 宋体">在</span>GC<span style="font-family: 宋体">前占用的内存</span></p>
<p>&lt;ending occupancy3&gt; JVM Heap <span style="font-family: 宋体">在</span>GC<span style="font-family: 宋体">后占用的内存</span></p>
<p>&lt;pause time3&gt; GC<span style="font-family: 宋体">过程中</span>jvm<span style="font-family: 宋体">暂停处理的总时间</span></p>
<p><strong><span style="font-size: 14pt">Jdk1.5 log</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">：</span></strong></p>
<p><strong><span style="color: red; font-family: 宋体">启动时</span><span style="color: red">GC</span></strong><strong><span style="color: red; font-family: 宋体">输出：</span></strong></p>
<p>[GC [DefNew: 209792K-&gt;4417K(235968K), 0.0201630 secs] 246722K-&gt;41347K(498112K), 0.0204050 secs]</p>
<p>[GC [DefNew: 214209K-&gt;4381K(235968K), 0.0139200 secs] 251139K-&gt;41312K(498112K), 0.0141190 secs]</p>
<p><span style="font-family: 宋体">一句输出：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">新生代回收前</span>209792K<span style="font-family: 宋体">，回收后</span>4417K<span style="font-family: 宋体">，回收数量</span>205375K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>246722K<span style="font-family: 宋体">回收后</span>41347K<span style="font-family: 宋体">，回收总量</span>205375K<span style="font-family: 宋体">。这就表示</span>100%<span style="font-family: 宋体">的收回，没有任何新生代的对象被提升到中生代或者永久区（名字说的不一定准确，只是表达意思）。</span></p>
<p><span style="font-family: 宋体">第二句输出：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">按照分析也就只是有</span>1K<span style="font-family: 宋体">内容被提升到中生代。</span></p>
<p><strong><span style="color: red; font-family: 宋体">运行一段时间后：</span></strong></p>
<p>[GC [DefNew: 210686K-&gt;979K(235968K), 0.0257140 secs] 278070K-&gt;68379K(498244K), 0.0261820 secs]</p>
<p>[GC [DefNew: 210771K-&gt;1129K(235968K), 0.0275160 secs] 278171K-&gt;68544K(498244K), 0.0280050 secs]</p>
<p><span style="font-family: 宋体">第一句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>210686K<span style="font-family: 宋体">，回收后</span>979K<span style="font-family: 宋体">，回收数量</span>209707K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>278070K<span style="font-family: 宋体">回收后</span>68379K<span style="font-family: 宋体">，回收总量</span>209691K<span style="font-family: 宋体">。这就表示有</span>16k<span style="font-family: 宋体">没有被回收。</span></p>
<p><span style="font-family: 宋体">第二句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>210771K<span style="font-family: 宋体">，回收后</span>1129K<span style="font-family: 宋体">，回收数量</span>209642K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>278171K<span style="font-family: 宋体">回收后</span>68544K<span style="font-family: 宋体">，回收总量</span>209627K<span style="font-family: 宋体">。这就表示有</span>15k<span style="font-family: 宋体">没有被回收。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">比较一下启动时与现在的新生代占用内存情况和</span>Heap<span style="font-family: 宋体">使用情况发现</span>Heap<span style="font-family: 宋体">的使用增长很明显，新生代没有增长，而</span>Heap<span style="font-family: 宋体">使用总量增长了</span>27M<span style="font-family: 宋体">，这就表明可能存在内存泄露，虽然每一次泄露的字节数很少，但是频率很高，大部分泄露的对象都被升级到了中生代或者持久代。</span></p>
<p><strong><span style="color: red; font-family: 宋体">又一段时间后：</span></strong></p>
<p>[GC [DefNew: 211554K-&gt;1913K(235968K), 0.0461130 secs] 350102K-&gt;140481K(648160K), 0.0469790 secs]</p>
<p>[GC [DefNew: 211707K-&gt;2327K(235968K), 0.0546170 secs] 350275K-&gt;140921K(648160K), 0.0555070 secs]</p>
<p><span style="font-family: 宋体">第一句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>211554K<span style="font-family: 宋体">，回收后</span>1913K<span style="font-family: 宋体">，回收数量</span>209641K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>350102K<span style="font-family: 宋体">回收后</span>140481K<span style="font-family: 宋体">，回收总量</span>209621K<span style="font-family: 宋体">。这就表示有</span>20k<span style="font-family: 宋体">没有被回收。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">分析到这里就可以看出每一次泄露的内存只有</span>10<span style="font-family: 宋体">几</span>K<span style="font-family: 宋体">，但是在大压力长时间的测试下，内存泄露还是很明显的，此时</span>Heap<span style="font-family: 宋体">已经增长到了</span>140M<span style="font-family: 宋体">，较启动时已经增长了</span>100M<span style="font-family: 宋体">。同时</span>GC<span style="font-family: 宋体">占用的时间越来越长。</span></p>
<p><strong><span style="color: red; font-family: 宋体">后续的现象：</span></strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">后续观察日志会发现，</span>Full GC<span style="font-family: 宋体">的频率越来越高，收集所花费时间也是越来越长。（</span>Full GC<span style="font-family: 宋体">定期会执行，同时局部回收不能满足分配需求的情况下也会执行）。</span></p>
<p>[Full GC [Tenured: 786431K-&gt;786431K(786432K), 3.4882390 secs] 1022399K-&gt;1022399K(1022400K), [Perm : 36711K-&gt;36711K(98304K)], 3.4887920 secs]</p>
<p>java.lang.OutOfMemoryError: Java heap space</p>
<p>Dumping heap to java_pid7720.hprof ...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">出现这个语句表示内存真的被消耗完了。</span></p>
<p><strong><span style="font-size: 14pt">Jdk1.6 log</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">：</span></strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span style="color: red; font-family: 宋体">启动时</span><span style="color: red">GC</span></strong><strong><span style="color: red; font-family: 宋体">的输出：</span></strong></p>
<p>[GC [PSYoungGen: 221697K-&gt;31960K(229376K)] 225788K-&gt;36051K(491520K), 0.0521830 secs] [Times: user=0.26 sys=0.05, real=0.05 secs] </p>
<p>[GC [PSYoungGen: 228568K-&gt;32752K(229376K)] 232659K-&gt;37036K(491520K), 0.0408620 secs] [Times: user=0.21 sys=0.02, real=0.04 secs]</p>
<p><span style="font-family: 宋体">第一句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>221697K<span style="font-family: 宋体">，回收后</span>31960K<span style="font-family: 宋体">，回收数量</span>189737K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>225788K<span style="font-family: 宋体">回收后</span>36051K<span style="font-family: 宋体">，回收总量</span>189737K<span style="font-family: 宋体">。</span>100%<span style="font-family: 宋体">被回收。</span></p>
<p><strong><span style="color: red; font-family: 宋体">运行一段时间后输出：</span></strong></p>
<p>[GC [PSYoungGen: 258944K-&gt;2536K(259328K)] 853863K-&gt;598135K(997888K), 0.0471620 secs] [Times: user=0.15 sys=0.00, real=0.05 secs] </p>
<p>[GC [PSYoungGen: 259048K-&gt;2624K(259328K)] 854647K-&gt;598907K(997888K), 0.0462980 secs] [Times: user=0.16 sys=0.02, real=0.04 secs]</p>
<p><span style="font-family: 宋体">第一句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>258944K<span style="font-family: 宋体">，回收后</span>2536K<span style="font-family: 宋体">，回收数量</span>256408K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>853863K<span style="font-family: 宋体">回收后</span>598135K<span style="font-family: 宋体">，回收总量</span>255728K<span style="font-family: 宋体">。</span>680K<span style="font-family: 宋体">没有被回收，但这并不意味着就会产生内存泄露。同时可以看出</span>GC<span style="font-family: 宋体">回收时间并没有增加。</span></p>
<p><strong><span style="color: red; font-family: 宋体">在运行一段时间后输出：</span></strong></p>
<p>[GC [PSYoungGen: 258904K-&gt;2488K(259264K)] 969663K-&gt;713923K(1045696K), 0.0485140 secs] [Times: user=0.16 sys=0.01, real=0.04 secs] </p>
<p>[GC [PSYoungGen: 258872K-&gt;2448K(259328K)] 970307K-&gt;714563K(1045760K), 0.0473770 secs] [Times: user=0.16 sys=0.01, real=0.05 secs]</p>
<p><span style="font-family: 宋体">第一句输出：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">新生代回收前</span>258904K<span style="font-family: 宋体">，回收后</span>2488K<span style="font-family: 宋体">，回收数量</span>256416K<span style="font-family: 宋体">，</span>Heap<span style="font-family: 宋体">总量回收前</span>969663K<span style="font-family: 宋体">回收后</span>713923K<span style="font-family: 宋体">，回收总量</span>255740K<span style="font-family: 宋体">。</span>676K<span style="font-family: 宋体">没有被回收，同时总的</span>Heap<span style="font-family: 宋体">也有所增加。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">此时看起来好像和</span>1.5<span style="font-family: 宋体">的状况一样。但是查看了一下</span>Full GC<span style="font-family: 宋体">的执行还是</span>400-500<span style="font-family: 宋体">次</span>GC<span style="font-family: 宋体">执行一次，因此继续观察。</span></p>
<p><span style="font-family: 宋体">运行一天多以后输出：</span></p>
<p>[GC [PSYoungGen: 257016K-&gt;3304K(257984K)] 1019358K-&gt;766310K(1044416K), 0.0567120 secs] [Times: user=0.18 sys=0.01, real=0.06 secs] </p>
<p>[GC [PSYoungGen: 257128K-&gt;2920K(258112K)] 1020134K-&gt;766622K(1044544K), 0.0549570 secs] [Times: user=0.19 sys=0.00, real=0.05 secs]</p>
<p><span style="font-family: 宋体">可以发现</span>Heap<span style="font-family: 宋体">增长趋缓。</span></p>
<p><span style="font-family: 宋体">运行两天以后输出：</span></p>
<p>[GC [PSYoungGen: 256936K-&gt;3584K(257792K)] 859561K-&gt;606969K(1044224K), 0.0565910 secs] [Times: user=0.18 sys=0.01, real=0.06 secs] </p>
<p>[GC [PSYoungGen: 256960K-&gt;3368K(257728K)] 860345K-&gt;607445K(1044160K), 0.0553780 secs] [Times: user=0.18 sys=0.01, real=0.06 secs]</p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">发现</span>Heap<span style="font-family: 宋体">反而减少了，此时可以对内存泄露问题作初步排除了。（其实在</span>jdk1.6<span style="font-family: 宋体">环境下用</span>jprofiler<span style="font-family: 宋体">来观察，对于</span>concurrent<span style="font-family: 宋体">那个内存泄露点的跟踪发现，内存的确还是会不断增长的，不过在一段时间后还是有回收，因此也就可以部分解释前面出现的情况）</span></p>
<p><strong><span style="font-size: 14pt; color: red; font-family: 宋体">总结：</span></strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">对于</span>GC<span style="font-family: 宋体">输出的观察需要分两个维度来看。一个是纵向比较，也就是一次回收对于内存变化的观察。一个是横向比较，对于长时间内存分配占用情况的比较，这部分比较需要较长时间的观察，不能仅仅凭短时间的几个抽样比较，因为对于抽样来说，</span>Full GC<span style="font-family: 宋体">前后的区别，运行时长的区别，资源瞬时占用的区别都会影响判断。同时要结合</span>Full GC<span style="font-family: 宋体">发生的时间周期，每一次</span>GC<span style="font-family: 宋体">收集所耗费的时间作为辅助判断标准。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">顺便说一下，</span>Heap<span style="font-family: 宋体">的</span> YoungGen,OldGen,PermGen<span style="font-family: 宋体">的设置也是需要注意的，并不是越大越好，越大执行收集的时间越久，但是可能执行</span>Full GC<span style="font-family: 宋体">的频率会比较低，因此需要权衡。这些仔细的去了解一下</span>GC<span style="font-family: 宋体">的基础设计思想会更有帮助，不过一般用默认的也不错。还有就是可以配置一些特殊的</span>GC<span style="font-family: 宋体">，并行，同步等等，充分利用多</span>CPU<span style="font-family: 宋体">的资源。</span></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong><span style="font-family: 宋体">对于</span>GC<span style="font-family: 宋体">的优化可以通过现在很多图形工具来做，也可以类似于我这样采用最原始的分析方式，好处就是任何时间任何地点只要知道原理就可以分析无需借助外部工具。原始的总是最好的</span>^_^<span style="font-family: 宋体">。</span></p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/235972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-10-22 16:36 <a href="http://www.blogjava.net/cenwenchu/archive/2008/10/22/235972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>“开放”的一些感想</title><link>http://www.blogjava.net/cenwenchu/archive/2008/10/07/232902.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Tue, 07 Oct 2008 05:24:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/10/07/232902.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/232902.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/10/07/232902.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/232902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/232902.html</trackback:ping><description><![CDATA[<p><font size="3"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">从去年到今年，开放这个词也在互联网上炒得火热，自己一年多的工作也让自己对开放这个词有了自己的一些理解和认识。</span></p>
<p><span style="font-family: 宋体">开放的平台</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">去年到今年自己的工作也随着公司的战略改变不断的发生着变化。最早公司定位致力于为中小企业提供商务管理软件，让中小企业能够通过使用在线软件轻松搞定电子商务贸易管理。随后公司又致力于提供开放的在线软件运营平台，为众多</span>ISV<span style="font-family: 宋体">和中小企业建立一个软件交易平台，中小企业可以随需定制管理软件。到今年年初，提出了服务集成平台，</span>ISV<span style="font-family: 宋体">的应用开发不再是封闭的开发模式，可以基于</span>ISP<span style="font-family: 宋体">提供的服务定制出更加丰富的应用。其实这种转变也是对平台的开放的思想不断成熟的一个过程。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">独自实现在线管理软件和传统软件其实没有太大的差别，唯一的差别就是把应用由客户的机器拉到了软件提供商的服务器上，对于维护，更新和商业模式可能有部分的变化，但是根本上来说软件的封闭性还是和传统软件一样。互联网软件的最大特点就是个性化需求强烈以及需求变更周期短，要适应行业客户的需求，仅仅靠一个公司的几杆枪几号人的创意远远不够。</span>Web2.0<span style="font-family: 宋体">的热潮其实能够给开发人员最大的启示就是参与才是力量的源泉，其实软件开发也是一样，如果能够集合互联网上众多</span>ISV<span style="font-family: 宋体">的思想和创意，那么满足用户需求并不是一件难事，同时及时响应用户需求也不再是火烧屁股的事情。同时，看看互联网应用开发的今天，国外</span>Open API<span style="font-family: 宋体">前几年就已经兴起，</span>Amazon,Google,Yahoo,FaceBook,MySpace<span style="font-family: 宋体">等等，将自己的数据，存储，计算通过</span>API<span style="font-family: 宋体">的方式提供给第三方，让第三方开发者能够通过使用这些服务有机会实践自己的创新和创意，互联网应用的开发也有了新的开放式开发模式。服务集成平台其实就是为</span>ISV<span style="font-family: 宋体">提供了创建应用的一个资源平台，</span>ISV<span style="font-family: 宋体">可以通过服务集成平台获取到各个</span>ISP(<span style="font-family: 宋体">例如淘宝</span>)<span style="font-family: 宋体">的</span>API<span style="font-family: 宋体">，在其基础上开发出在线应用，然后直接挂接到应用运营平台为终端用户提供应用服务。这很类似于传统行业的产业链，服务集成平台就好比原料交易市场，应用运营平台就好比商品交易市场。回过头来看，阿里系的各个子公司，其实都是在以这种思路做事，从加入公司到现在，给我印象最深刻的一句话就是：&#8220;凡事不要先想着如何赚到别人的钱，让别人先赚到钱，别人自然很乐意的和你分享&#8221;，这种双赢的思想在开放中能够得到最好的实践。</span></p>
<p><span style="font-family: 宋体">开放的框架</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">一个公司技术是需要积累的，如果纯粹让每一个开发人员根据自己的能力去合作开发企业的产品和平台，对于企业，对于产品都是不利的。</span>Java<span style="font-family: 宋体">吸引人就在于它的开源世界，每一个开发人员可以去获得自己想要的，或者去贡献给他人自己创造的。现在很多公司应聘的过程就是一个开源知识问答，其实是否用过能说明什么问题呢，关键是没用过如何去学习和了解并且快速上手，如果能力再强一点，那就知道如何定制和扩展，我想这样的才可以叫做企业需要的人才。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">从公司成立那时起，内部就有一个应用开发框架，作用就是为了快速开发应用，尽最大可能降低开发者对于开发技术的学习，集中精力致力于业务开发。（当然看到这里估计</span>98%<span style="font-family: 宋体">的开发人员都会皱起眉头）。我也为此贡献了自己</span>2<span style="font-family: 宋体">个</span>Q<span style="font-family: 宋体">的工作时间，当时我主要负责后台重构，需要建立起一个服务框架，开始参考了</span>OSGI<span style="font-family: 宋体">（因为它的模块化和动态载入机制），发现并不是很合适，然后接触了</span>SCA<span style="font-family: 宋体">框架（可扩展，模块化，</span>SOA<span style="font-family: 宋体">的支持），最后决定在开源项目</span>Tuscany0.91<span style="font-family: 宋体">版本的基础上再次开发和封装，实现了内部的</span>ASF(<span style="font-family: 宋体">应用服务框架</span>)<span style="font-family: 宋体">，</span>ASF<span style="font-family: 宋体">作为我们开发框架的后台基础框架被广泛使用在了我们的多条产品线以及基础平台上，但是</span>ASF<span style="font-family: 宋体">的质疑就一直没有停过，性能，学习成本，调试困难度等等。虽然自己竭力去写了厚厚的一套文档，一组单元测试工具，一系列的问题查找工具，作了多次的压力测试，学习普及，但是还是得不到一些架构师的支持。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">其实，自己在后面也做过一些思考，其实对于</span>ASF<span style="font-family: 宋体">来说，它的可扩展性没有什么好怀疑，他不像其他开源项目，我可以封装</span>Hessian<span style="font-family: 宋体">组件，</span>REST<span style="font-family: 宋体">组件等等，随需载入，开发者只需要配置一下标签，即可使用，因此这样的框架下，不会随着技术的发展和自己的封闭而腐烂。但是，有一点就导致推广产生了那么多问题，那就是参与。我记忆很深的就是我们的首席架构师在今年招开会议评估</span>ASF<span style="font-family: 宋体">的问题时地邮件中说的：&#8220;</span>ASF<span style="font-family: 宋体">不是岑文初一个人的</span>ASF<span style="font-family: 宋体">，也不是平台一部的</span>ASF<span style="font-family: 宋体">，而是大家的</span>ASF<span style="font-family: 宋体">&#8221;。其实那时候我已经不再专职负责</span>ASF<span style="font-family: 宋体">，当今年因为一个项目进度由于开发受到影响时再次提出</span>ASF<span style="font-family: 宋体">的质疑地时候，我自己真的觉得比较沮丧，很多架构师和开发者从来就没有看过文档，没有用过调试工具，没有看过</span>Q&amp;A<span style="font-family: 宋体">，一出问题就觉得无所适从，要找人解决框架问题，我曾经说是否</span>Spring<span style="font-family: 宋体">用的时候出现问题，第一想法就是去找</span>Spring<span style="font-family: 宋体">的开发者，还是先会看看文档，调试一下。我想这应该是两方面的原因，但如果能够让每个人都参与进来，那么就不会是今天一人独挡的局面。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">因此未来自己的工作中，不论是内部的基础组件还是基础平台都会多邀请一些参与者，毕竟自己的肩膀有限，蚂蚁就算在大力也需要有伙伴的支持。</span></p>
<p><span style="font-family: 宋体">开放的心态</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">这点其实是做人的基本要素，有一个宽阔的胸怀才会有更多的机会，才会成长的更快。但是自己这点的却做得很不够。开发人员都有一个相同的特点就是热衷于技术钻研，今天搞一个东西比你快一点，明天做一个东西比他功能多一点，总是在技术方面去寻找满足。其实老大一直和我们也在说，现在公司内部的架构师并不是一个&#8220;全专&#8221;，也不一定是一个写代码高手，但是在某一个领域会有深入的研究，同时接触其他领域也能够胜任。没有什么技术人员是绝对的高手，其实随着工作重心的不断变化，所接触的领域也会不断发生变化，因此不可能有所谓的&#8220;全才&#8221;。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">有时候自己也会用技术的眼光去看待人或者事，其实这样只会让自己看不到自己的不足，也忽略了别人的优点，更重要的就是失去了一次进步的机会。其实经常给自己换换思路会对自己有很大的帮助，就好比最近忙于写了一阵子代码，那么就给自己一个机会去看看一些关于搜索领域的知识。开发了一个阶段的服务集成平台，去了解一下所有的国外网站</span>Open API<span style="font-family: 宋体">的风格，结构，流程。用惯了</span>Java<span style="font-family: 宋体">后，去学习学习</span>Php,Ruby<span style="font-family: 宋体">等等。这样换换脑子对自己来说会有新的收获。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">开放的心态理解容易，但是要让他不仅仅写在</span>MSN<span style="font-family: 宋体">的</span>title<span style="font-family: 宋体">中，而写在心里却需要不断地督促和付出。不过知道自己有问题好过觉得自己没有问题。</span></p>
<p><span style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10.5pt; font-family: 宋体">写了那么些，其实思路比较乱，我想从随笔里面也看得出来，但是还是想记录一下自己的一些思考，起码以后回过头来可以看到自己成长的过程。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><o:p></o:p></span></font></font></p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/232902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-10-07 13:24 <a href="http://www.blogjava.net/cenwenchu/archive/2008/10/07/232902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Memcached Cache是集中式还是分布式的一点补充</title><link>http://www.blogjava.net/cenwenchu/archive/2008/09/26/231265.html</link><dc:creator>岑文初</dc:creator><author>岑文初</author><pubDate>Fri, 26 Sep 2008 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/cenwenchu/archive/2008/09/26/231265.html</guid><wfw:comment>http://www.blogjava.net/cenwenchu/comments/231265.html</wfw:comment><comments>http://www.blogjava.net/cenwenchu/archive/2008/09/26/231265.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/cenwenchu/comments/commentRss/231265.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cenwenchu/services/trackbacks/231265.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 昨天贴了这个帖子以后，有同学说我是不是写错了，Memcached Cache应该是分布式的Cache，怎么变成集中式了。</p>
<p>&nbsp;&nbsp;&nbsp; 这里把我另外一部分的内容贴出来。</p>
<p>&nbsp;&nbsp;&nbsp; Memcached是一种集中式Cache，支持分布式横向扩展。这里需要有点说明，很多开发者觉得Memcached是一种分布式Cache，但是其实Memcached服务端本身是单实例的，只是在客户端实现过程中可以根据存储的主键作分区存储，而这个区就是Memcached服务端的一个或者多个实例，如果将客户端也囊括到Memcached中，那么可以部分概念上说是集中式的。其实回顾一下集中式的构架，无非两种情况：1.节点均衡的网状（JBoss Tree Cache），利用JGroup的多播通信机制来同步数据。2.Master-Slaves模式（分布式文件系统），由Master来管理Slave，如何选择Slave，如何迁移数据，都是由Master来完成，但是Master本身也存在单点问题。</p>
<p>总结几个它的特点来理解一下它的优点和限制。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Memory：内存存储，不言而喻，速度快，对于内存的要求高，不指出的话所缓存的内容非持久化。对于CPU要求很低，所以常常采用将Memcached服务端和一些CPU高消耗Memory低消耗应用部属在一起。（作为我们AEP正好有这样的环境，我们的接口服务器有多台，接口服务器对于CPU要求很高（由于WS-Security），但是对于Memory要求很低，因此可以用作Memcached的服务端部属机器）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 集中式Cache：避开了分布式Cache的传播问题，但是需要非单点保证其可靠性，这个就是后面集成中所作的cluster的工作，可以将多个Memcached作为一个虚拟的cluster，同时对于cluster的读写和普通的memcached的读写性能没有差别。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 分布式扩展：Memcached的很突出一个优点，就是采用了可分布式扩展的模式。可以将部属在一台机器上的多个Memcached服务端或者部署在多个机器上的Memcached服务端组成一个虚拟的服务端，对于调用者来说完全屏蔽和透明。提高的单机器的内存利用率，也提供了scale out的方式。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket通信：传输内容的大小以及序列化的问题需要注意，虽然Memcached通常会被放置到内网作为Cache，Socket传输速率应该比较高（当前支持Tcp和udp两种模式，同时根据客户端的不同可以选择使用nio的同步或者异步调用方式），但是序列化成本和带宽成本还是需要注意。这里也提一下序列化，对于对象序列化的性能往往让大家头痛，但是如果对于同一类的Class对象序列化传输，第一次序列化时间比较长，后续就会优化，其实也就是说序列化最大的消耗不是对象序列化，而是类的序列化。如果穿过去的只是字符串，那么是最好的，省去了序列化的操作，因此在Memcached中保存的往往是较小的内容。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 特殊的内存分配机制：首先要说明的是Memcached支持最大的存储对象为1M。它的内存分配比较特殊，但是这样的分配方式其实也是对于性能考虑的，简单的分配机制可以更容易回收再分配，节省对于CPU的使用。这里用一个酒窖比喻来说明这种内存分配机制，首先在Memcached起来的时候可以通过参数设置使用的总共的Memory，这个就是建造一个酒窖，然后在有酒进入的时候，首先申请（通常是1M）的空间，用来建酒架，酒架根据这个酒瓶的大小分割酒架为多个小格子安放酒瓶，将同样大小范围内的酒瓶都放置在一类酒架上面。例如20cm半径的酒瓶放置在可以容纳20-25cm的酒架A上，30cm半径的酒瓶就放置在容纳25-30cm的酒架B上。回收机制也很简单，首先新酒入库，看看酒架是否有可以回收的地方，如果有直接使用，如果没有申请新的地方，如果申请不到，采用配置的过期策略。这个特点来看，如果要放的内容大小十分离散，同时大小比例相差梯度很明显，那么可能对于使用空间来说不好，可能在酒架A上就放了一瓶酒，但占用掉了一个酒架的位置。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cache机制简单：有时候很多开源的项目做的面面俱到，但是最后也就是因为过于注重一些非必要性的功能而拖累了性能，这里要提到的就是Memcached的简单性。首先它没有什么同步，消息分发，两阶段提交等等，它就是一个很简单的Cache，把东西放进去，然后可以取出来，如果发现所提供的Key没有命中，那么就很直白的告诉你，你这个key没有任何对应的东西在缓存里，去数据库或者其他地方取，当你在外部数据源取到的时候，可以直接将内容置入到Cache中，这样下次就可以命中了。这里会提到怎么去同步这些数据，两种方式，一种就是在你修改了以后立刻更新Cache内容，这样就会即时生效。另一种是说容许有失效时间，到了失效时间，自然就会将内容删除，此时再去去的时候就会命中不了，然后再次将内容置入Cache，用来更新内容。后者用在一些时时性要求不高，写入不频繁的情况。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 客户端的重要性：Memcached是用C写的一个服务端，客户端没有规定，反正是Socket传输，只要语言支持Socket通信，通过Command的简单协议就可以通信，但是客户端设计的合理十分重要，同时也给使用者提供了很大的空间去扩展和设计客户端来满足各种场景的需要，包括容错，权重，效率，特殊的功能性需求，嵌入框架等等。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 几个应用点：小对象的缓存（用户的token，权限信息，资源信息）。小的静态资源缓存。Sql结果的缓存（这部分用的好，性能提高相当大，同时由于Memcached自身提供scale out，那么对于db scale out的老大难问题无疑是一剂好药）。ESB消息缓存。</p>
<img src ="http://www.blogjava.net/cenwenchu/aggbug/231265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cenwenchu/" target="_blank">岑文初</a> 2008-09-26 11:45 <a href="http://www.blogjava.net/cenwenchu/archive/2008/09/26/231265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>