<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>JavaEye论坛精彩帖子</title>
    <description>JavaEye论坛精彩帖子 - 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>MemCached Cache Java Client封装优化历程</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://cenwenchu.javaeye.com">cenwenchu</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/246729" style="color:red;">http://www.javaeye.com/topic/246729</a>&nbsp;
          发表时间: 2008年09月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US"><span style="font-family: Calibri;">Author</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">：文初</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small; color: #000000; font-family: Calibri;">Email: </span><a href="mailto:wenchu.cenwc@alibaba-inc.com"><span style="text-decoration: underline;"><span style="font-size: small; color: #0000ff; font-family: Calibri;">wenchu.cenwc@alibaba-inc.com</span></span></a></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small; color: #000000; font-family: Calibri;">Blog: </span><a href="http://blog.csdn.net/cenwenchu79/"><span style="text-decoration: underline;"><span style="font-size: small; color: #800080; font-family: Calibri;">http://blog.csdn.net/cenwenchu79/</span></span></a></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US"><span style="font-family: Calibri;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>MemCached Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">在大型网站被应用得越来越广泛，不同语言的客户端也都在官方网站上有提供，但是</span><span lang="EN-US"><span style="font-family: Calibri;">Java</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">的选择并不多。由于现在的</span><span lang="EN-US"><span style="font-family: Calibri;">MemCached Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">服务端是用</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">写的，因此我这个</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">不太熟悉的人也就没有办法去优化它，当然对于它的内存分配机制等细节还是有所了解，因此在使用的时候也会十分注意，这些文章</span><span lang="EN-US"><span style="font-family: Calibri;">Google</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">一把应该也有很多了。这里就说说对于</span><span lang="EN-US"><span style="font-family: Calibri;">MemCache Java</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">客户端的优化的两个阶段。</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="font-size: 14pt;"><span style="color: #000000;"><span style="font-family: Calibri;">First Stage</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: #000000;"><span lang="EN-US" style="font-size: 14pt;"><span style="mso-tab-count: 1;"><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">我也和其他使用</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Memcached Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">的同学一样，看了官方网站的内容，然后去下载了</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">whalin memcached Client</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">，后来</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Stat</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">的时候遇到问题，就给作者发了邮件说明了情况，作者让我下载</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;"> 2.0.1 </span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">版本，这个版本也是比较不错的一个版本，后续的封装也是基于这个版本之上。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="mso-tab-count: 1;"><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">第一阶段主要是在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">whalin</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的客户端作了再次封装。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">1.</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cache</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">服务接口化。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">定义了</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">IMemCache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">接口，在应用部分仅仅只是使用接口，为将来替换</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">服务实现提供基础。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">2.</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">使用配置代替代码初始化客户端。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 39pt; text-indent: 21pt;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">通过配置客户端和</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SocketIO Pool</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">属性，直接交管由</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">CacheManager</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">来维护</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache Client Pool</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的生命周期，方便实用以及单元测试。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">3.</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">KeySet</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的实现。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">对于</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">MemCached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">来说本身是不提供</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">KeySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的方法的，在接口封装初期，同事向我提出这个需求的时候，我个人觉得也是没有必要提供，因为</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">轮询是比较低效的，同时这类场景，往往可以去数据源获取</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">KeySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，而不是从</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">MemCached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">去获取。但是</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SIP</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的一个场景的出现，让我不得不去实现了</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">KeySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SIP</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">在作服务访问频率控制的时候需要记录在控制间隔期内的访问次数和流量，此时由于是集群，因此数据必须放在集中式的存储或者缓存中，数据库肯定是撑不住这样大数据量的更新频率的，因此考虑使用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的很出彩的操作，全局计数器（</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">storeCounter,getCounter,inc,dec</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">），但是在检查计数器的时候如何去获取当前所有的计数器，曾考虑使用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">DB</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">或者文件，但是效率还是问题，同时如果放在一个字段中并发还是有问题。因此不得不实现了</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">KeySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，在使用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">KeySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的时候有一个参数，类型是</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Boolean</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，这个字段的存在是因为，在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">中数据的删除并不是直接删除，而是标注一下，这样会导致实现</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">keySet</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的时候取出可能已经删除的数据，如果对于数据严谨性要求低，速度要求高，那么不需要再去验证</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">key</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">是否真的有效，如果要求</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">key</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">必须正确存在，就需要再多一次的轮询查找。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">4.</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cluster</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的实现。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">作为集中式</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，就存在着集中式的致命问题：单点问题，</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">支持多</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Instance</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">分布在多台机器上，仅仅只是解决了数据全部丢失的问题，但是当其中一台机器出错以后，还是会导致部分数据的丢失，一个篮子掉在地上还是会把部分的鸡蛋打破。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">因此就需要实现一个备份机制，能够保证</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">在部分失效以后，数据还能够依然使用，当然大家很多时候都用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">不命中就去数据源获取的策略，但是在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SIP</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的场景中，如果部分信息找不到就去数据库查找，那么要把</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SIP</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">弄垮真的是很容易，因此</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SIP</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">对于</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">中的数据认为是可信的，因此做</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cluster</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">也是必要的。</span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"></span></span>&nbsp;</p>
<p class="MsoListParagraph" align="center" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span lang="EN-US"><span style="font-family: Calibri;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/cenwenchu79/EntryImages/20080925/Memcache.jpg" height="512" alt="" width="533" /></span></span></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span>&nbsp;</p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-no-proof: yes;"></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 110.25pt; text-indent: -47.25pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">（1）</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">应用传入需要操作的</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">key</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">，通过</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">CacheManager</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">获取配置在</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cluster</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">中的客户端。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 110.25pt; text-indent: -47.25pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">（2）</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">当获得</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cache Client</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">以后，执行</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cache</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">操作。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 110.25pt; text-indent: -47.25pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">（3）</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">A.</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">如果是读取操作，当不能命中时去集群其他</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">客户端获取数据，如果获取到数据，尝试写入到本次获得的</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Cache</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">客户端，并返回结果。（达到数据恢复的作用）</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 110.25pt; text-indent: 0cm; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">B.</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">如果是更新操作，在本次获取得</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">客户端执行更新操作以后，立即返回，将更新集群其他机器命令提交给客户端的异步更新线程对列去异步执行。（由于如果是根据</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">key</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">来获取</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，那么异步执行不会影响到此主键的查询操作）</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">存在的问题：如果是设置了</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Timeout</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的数据，那么在丢失以后被复制的过程中就会变成永久有效的内容。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">5.</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">LocalCache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">结合</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Memcached</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">使用，提高数据获取效率。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">在第一次压力测试过程中，发现和原先预料的一样，</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">并不是完全无损失的，</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">是通过</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Socket</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">数据交互来进行通信的，因此机器的带宽，网络</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">IO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Socket</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">连接数都是制约</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">发挥其作用的障碍。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的一个突出优点就是</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Timeout</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的设置，也就是放入进去的数据可以设置有效期，自动会失效，这样对于一些不敏感的数据就可以在一定的容忍时间内不去更新，提高效率。根据这个思想，其实在集群中的每一个</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">客户端也可以使用本地的</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，来缓存获取过的数据，设置一定的失效时间，来减少对于</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的访问次数，提高整体性能。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; text-indent: 0cm; mso-char-indent-count: 0;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="mso-tab-count: 1;"><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">因此，在每一个客户端中内置了一个有超时机制的本地缓存（采用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">lazy timeout</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">机制），在获取数据的时候，首先在本地查询数据是否存在，如果不存在则再向</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">发起请求，获得数据以后，将其缓存在本地，并设置有效时间。方法定义如下：</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">/**</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-tab-count: 2;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">*</span><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><span style="font-size: 9pt; color: #3f5fbf; font-family: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">降低</span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">memcache</span><span style="font-size: 9pt; color: #3f5fbf; font-family: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">的交互频繁造成的性能损失，因此采用本地</span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">cache</span><span style="font-size: 9pt; color: #3f5fbf; font-family: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">结合</span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">memcache</span><span style="font-size: 9pt; color: #3f5fbf; font-family: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">的方式</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-tab-count: 2;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">*</span><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><strong><span lang="EN-US" style="font-size: 9pt; color: #7f9fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">@param</span></strong><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">key</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-tab-count: 2;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">*</span><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><strong><span lang="EN-US" style="font-size: 9pt; color: #7f9fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">@param</span></strong><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><span style="font-size: 9pt; color: #3f5fbf; font-family: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">本地缓存失效时间单位秒</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-tab-count: 2;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">*</span><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> </span><strong><span lang="EN-US" style="font-size: 9pt; color: #7f9fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">@return</span></strong><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" align="left" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;</span></span><span lang="EN-US" style="font-size: 9pt; color: #3f5fbf; font-family: 'Courier New'; mso-font-kerning: 0pt;">*/</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 42pt; text-indent: 0cm; mso-char-indent-count: 0;"><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp; </span></span><strong><span lang="EN-US" style="font-size: 9pt; color: #7f0055; font-family: 'Courier New'; mso-font-kerning: 0pt;">public</span></strong><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> Object <span style="background: silver; mso-highlight: silver;">get</span>(String key,</span><strong><span lang="EN-US" style="font-size: 9pt; color: #7f0055; font-family: 'Courier New'; mso-font-kerning: 0pt;">int</span></strong><span lang="EN-US" style="font-size: 9pt; color: black; font-family: 'Courier New'; mso-font-kerning: 0pt;"> localTTL);</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="font-size: 9pt;"><span style="color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="font-size: 9pt;"><span style="color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="font-size: 14pt;"><span style="color: #000000;"><span style="font-family: Calibri;">Second Stage</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="mso-tab-count: 1;"><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">第一阶段的封装基本上已经可以满足现有的需求，也被自己的项目和其他产品线使用，但是不经意的一句话，让我开始了第二阶段的优化。单位里面有个同学说</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">客户端里面在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SocketIO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">代码里面有太多的</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">synchronized</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，多多少少会影响性能。虽然过去看过这部分代码，但是当时只是关注里面的</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Hash</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">算法，那天回去后一看，果然有不少的</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">synchronized</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，可能是与客户端当时写的时候</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Jdk</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">版本较早的缘故造成的，现在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Concurrent</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">包被广泛应用，因此优化并不是一件很难的事情。但是由于原有</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">whalin</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">没有提供扩展的接口，因此不得不将</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">whalin</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">除了</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SockIO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">部分全部纳入到封装过的客户端中，然后改造</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SockIO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">部分。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">因此也有了这个放在</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Google</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">上的</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Calibri;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="color: #000000;">open source: </span></span><span lang="EN-US"><a href="http://code.google.com/p/memcache-client-forjava/"><span style="mso-bidi-font-size: 10.5pt;"><span style="text-decoration: underline;"><span style="color: #800080;">http://code.google.com/p/memcache-client-forjava/</span></span></span></a></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l2 level1 lfo3;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">一．</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">优化</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">synchronized</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">部分。在原有代码中</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">SockIO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">的资源池分成三个池（普通</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Map</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">实现），</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Free</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">，</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Busy</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">，</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">Dead</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">，然后根据</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">SockIO</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">使用情况来维护这三个资源池。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 39pt; text-indent: 21pt;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">优化方式，首先简化资源池，只有一个资源池，设置一个状态池，在变更资源状态的过程时仅仅变更资源池中的内容。再次，用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">ConcurrentMap</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">来替代</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Map</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，同时使用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">putIfAbsent</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">方法来简化</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Synchronized</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">，具体的代码可以看</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">open source</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的代码部分。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoListParagraph" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l2 level1 lfo3;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><span style="font-size: small; font-family: Calibri;">二．</span><span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">原以为这优化后，效率应该会有很大的提高，但是在初次压力测试后发现，并没有明显的提高，看来有其他地方的耗时远远大于连接池资源维护，因此用</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">JProfiler</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">作了性能分析，发现了最大的一个瓶颈：</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">read</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">数据部分，原有设计中读取数据是按照单字节读取，然后逐步分析，为的仅仅就是遇到协议中的分割符可以识别，但是循环</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">read</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;"><span style="font-size: small;">单字节和批量分页</span></span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; font-family: Calibri;">read</span></span><span style="font-size: small;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">性能相差很大，因此内置了读入缓存页（可设置大小），然后再按照协议的需求去读取和分析数据，效率得到了很大的提高。具体的看最后部分的压力测试结果。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: 18pt;"><span style="font-size: small;"><span style="color: #000000;"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">上面两部分的工作不论是否提升了性能，但是对于客户端本身来说都是有意义的，当然提升性能给应用带来的吸引力更大。这部分细节内容可以参看代码实现部分，对于调用者来说完全没有任何功能影响，仅仅只是性能。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: #000000;"><span style="font-size: 14pt; font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;">压力测试</span><span lang="EN-US" style="font-size: 14pt;"></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="mso-tab-count: 1;"><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">在这个压力测试之前，其实已经做过很多次压力测试了，测试中的数据本身并没有衡量</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Memcached</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的意义，因为测试是使用我自己的机器，性能，带宽，内存，网络</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">IO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">都不是服务器级别的，这里仅仅是将使用原有的第三方客户端和改造后的客户端作一个比较。场景就是模拟多用户多线程在同一时间发起</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">操作，然后记录下操作的结果。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Client</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">版本在测试中有两个：</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">2.0</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">和</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">2.2</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">2.0</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">是封装调用</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">whalin memcached Client 2.0.1</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">版本的客户端实现。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">2.2</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">是使用了新</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">SockIO</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">的无第三方依赖的客户端实现。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>checkAlive</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">指的是在使用连接资源以前是否需要验证连接资源有效（发送一次请求并接受响应），因此打开对于性能来说会有不少的影响，不过建议还是使用这个检查。</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-size: small; color: #000000; font-family: Calibri;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">One Cache Server instance</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">各种配置和操作下比较：</span><span style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;"> <span lang="EN-US"></span></span></span></span></span></p>
<p>
<table class="MsoNormalTable" cellspacing="0" border="1" cellpadding="0" style="border-collapse: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid black .5pt; mso-yfti-tbllook: 1184; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid black; mso-border-insidev: .5pt solid black;">
<tbody>
<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes;">
<td valign="top" width="92" style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 69.2pt; padding-top: 0cm; background-color: transparent; mso-border-alt: solid black .5pt; border: black 1pt solid;">
<p class="MsoNormal" align="center" style="margin: 0cm 0cm 0pt; text-align: center;"><span style="font-size: small;"><span style="color: #000000;"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"><span style="font-family: Calibri;">Cache</span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-bidi-font-size: 10.5pt;">配置</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt;"></span></span></span></p>
</td>
<td valign="top" width="47" style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 35.45pt; padding-top: 0cm; border-bottom: black 1pt solid; background-color: transparent; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt;">
<p class="MsoNormal" </td></tr></tbody></table></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/246729" style="color:red;">已有 <strong>29</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/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 25 Sep 2008 16:44:56 +0800</pubDate>
        <link>http://www.javaeye.com/topic/246729</link>
        <guid>http://www.javaeye.com/topic/246729</guid>
      </item>
          <item>
        <title>Cucumber - 将在RSpec1.1.5中取代Story Runner</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhangpeihao.javaeye.com">zhangpeihao</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/248074" style="color:red;">http://www.javaeye.com/topic/248074</a>&nbsp;
          发表时间: 2008年09月29日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="text-align: center;"><span style="font-size: medium;"><strong>Cucumber</strong>
（黄瓜）</span>
</p>
<p style="text-align: center;">原文：<a href="http://blog.davidchelimsky.net/2008/9/22/cucumber" title="Cucumber" target="_blank">Cucumber</a>
</p>
<p>在即将推出的RSpec1.1.5发布版中，将用Aslak Helles&oslash;y的<a href="http://github.com/aslakhellesoy/cucumber/tree/master" title="Cucumbe" target="_blank">Cucumber</a>
库来取代RSpec的故事运行器。</p>
<p>&nbsp;</p>
<p>Cucumber是完全重写的故事运行器。她使用了Treetop语法解析器。当我刚开始使用纯文本故事来工作的时候，由于很多原因我没有写一个语法解析器而是使用自己的解析。后来证明这给我们带来了许多好处。</p>
<p>&nbsp;</p>
<p><strong>Cucumber支持多种口语</strong>
</p>
<p>&nbsp;</p>
<p>现在你可以这样来描述：</p>
<p>&nbsp;</p>
<pre name="code" class="ruby">Funcionalidade: Adição
  Para evitar erros bobos
  Como um péssimo matemático
  Eu quero saber como somar dois números

  Cenário: Adicionar dois números
    Dado que eu digitei 50 na calculadora
    E que eu digitei 70 na calculadora
    Quando eu aperto o botão de soma
    Então o resultado na calculadora deve ser 120
</pre>
<p>&nbsp;用葡萄牙语写的，完全合法！（酷吧！虽然我一点也不明白写了些什么）</p>
<p>&nbsp;</p>
<p>现在已经支持了几种语言，增加新的语言需要一些工作，所以过一段时间我们也许会为增加你们自己的语言提供支持。</p>
<p>&nbsp;</p>
<p><strong>改善了代码回查</strong>
</p>
<p>&nbsp;</p>
<p>Cucumber在纯文本功能（Feature）文件上增加了行号，这使得定位错误变得非常非常方便。（注意：现在我们用功能取代了故事-在这个主题的另一个帖子里可以找到）</p>
<p>&nbsp;</p>
<p><strong>更简单的配置</strong>
</p>
<p>&nbsp;</p>
<p>Cucumber去掉了steps_for和using_steps_for。而是通过Given, When和Then函数简单地定义步骤：</p>
<pre name="code" class="ruby">#features/steps/accounts.rb
Given /I have \$(\d+) in my (.*) account/ do |dollars, account_type|
  ...
end
</pre>
<p>&nbsp;接下来，你需要引用包含这个步骤定义的文件：</p>
<pre name="code" class="ruby">cucumber -r features/steps/accounts.rb features/transfer_money
</pre>
<p>&nbsp;这样就搞定了。而且，大多数情况下，你都不需要这样明确地指定，你可以只是：</p>
<pre name="code" class="ruby">cucumber features</pre>
<p>&nbsp;Cucumber在运行功能文件之前会自动引用features目录下的所有.rb文件。</p>
<p>&nbsp;</p>
<p><strong>更少的手足无措<br />
</strong>
</p>
<p>&nbsp;</p>
<p>当RSpec的故事运行器在一个步骤的处理里找到了一个以上的步骤定义的话，找到的第一定义胜出。这可能会导致很多痛苦的调试工作。</p>
<p>&nbsp;</p>
<p>当Cucumber发现一个步骤的处理里能找到了一个以上的步骤定义的话，你将得到一个错误结果，告诉你步骤定义存在冲突，同时提供它们的位置（文件和行号），这样你就可以容易地找到和解决这个冲突了。</p>
<p>&nbsp;</p>
<p><strong>如果你已经使用了故事运行器，Cucumber对你意味着什么<br />
</strong>
</p>
<p>&nbsp;</p>
<p>Cucumber只有几个月大，几乎和RSpec的故事运行器的功能没有冲突，并且增加了很多功能强大的新功能。Aslak也把许多故事转换成了Cucumber的功能，并且<a href="http://github.com/aslakhellesoy/cucumber/wikis/migration-from-rspec-stories" target="_blank">把他的经验贴出来了</a>
，在帖子里他精炼出了他所完成的过程。在我们发布Cucumber的官方版本时，这个转移方法将会有很多文档支持并且不难得到。</p>
<p>&nbsp;</p>
<p>至于时限，这很难说。我们一直希望发布1.1.5版，但是由于一些原因一直被推后。我们很可能等到Rails2.2发布之后，在确认它们是否兼容后推出。虽然有传言1.1.5版马上就要发布，但是已经&ldquo;马上&rdquo;了好几个星期，我们只有耐心等待了。</p>
<p>&nbsp;</p>
<p>同时，我们正在结束故事运行器的开发，这样我们才能专注于Cucumber的开发。在Cucumber作为RSpec的官方部件发布之前，我们会在github上另建一个故事运行器的工程（可能叫rspec-stories）这样如果有人想继续使用或者维护故事运行器的话也可以找得到。</p>
<p>&nbsp;</p>
<p>我将在这里和<a href="http://rubyforge.org/mailman/listinfo/rspec-users" target="_blank">rspec-users邮件列表</a>
（<a href="http://groups.google.com/group/rspec" target="_blank">rspec google组</a>
的镜像）继续发布事情的进展。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/248074" 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/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 29 Sep 2008 14:26:23 +0800</pubDate>
        <link>http://www.javaeye.com/topic/248074</link>
        <guid>http://www.javaeye.com/topic/248074</guid>
      </item>
          <item>
        <title>大胆预测下JS框架的走势</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lifesinger.javaeye.com">lifesinger</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/245057" style="color:red;">http://www.javaeye.com/topic/245057</a>&nbsp;
          发表时间: 2008年09月21日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="post-meta">
				<span class="edit"><a href="http://lifesinger.org/blog/wp-admin/post.php?action=edit&amp;post=147" title="Edit post"></a></span>			</p>
<div class="post-content">
<p class="blockstrong"><span style="color: #0000ff; font-size: small;">MooTools将在接下来的几年内像jQuery一样迅速走红<br />
而jQuery则会慢慢销声匿迹<br />
YUI将不尴不尬的活着，YUI 3.x将成为小部分人的玩物，大部分人的忽视物<br />
Ext将在web app应用中有一番作为</span></p>
<h3>理由：</h3>
<ol>
<li>jQuery最大的特点是简洁易用，强大的CSS选择器和简洁易用的API，可以说是以用户为中心的理念在JS框架里的一次完胜。但jQuery
终究只是个人英雄主义的一个产物，其内部的基本架构、代码的可维护性等方面已渐渐散发出腐败的气息。jQuery像是一个一夜走红的神童，如今已渐渐的江
郎才尽，感觉很难再有大的突破。</li>
<li>YUI则带着浓厚的&ldquo;官方、团队&rdquo;js库的气息。其严谨的代码组织风格，以及对web开发思想（指Unobtrusive,
Progressive Enhancement等）的融入，让YUI成为不少开发团队的选择。但YUI
2.x缓慢的更新速度，以及对新思想的接纳程度，很多时候让人恨得牙痒痒，太慢了，和其它新生代框架相比，YUI
2.x像是一个步履蹒跚的老年人，让人很无奈。YUI
3.x目前还处于preview阶段，可以将其看成一个全新的JS库（底层代码全重写了，组织风格做了极大的调整）。YUI
3.x里最明显的一个改变是，将jQuery等框架里的CSS选择器、基本元素（jQuery里jQuery对象，MooTools里的Element对
象）等概念正式化，成为框架最基本的组成部分（在YUI 2.5.x里也有CSS
Selector和Element，但一直处于beta阶段，功能很鸡肋）。YUI
3.x自赞的动态加载，在新生代框架里也是早就有了的。仔细比较后，YUI
3.x并没有带来什么新东西，更多的只是吸收接纳了新生代框架的许多理念。对YUI的前景，就如对YAHOO的期待的一样，我相信它会存活着，但也许仅仅
就是这样活着下去。</li>
<li>MooTools是开源社区形式下发展起来的一个js框架。在它的早期代码里，能感觉到Prototype,
jQuery等框架的痕迹，但它一直保持着开放的心态，小步前进，快速更新。其代码组织风格、对无侵入等Web思想的理解，各个方面都呈现出少年新贵、武
林新秀的姿态来。不仅仅是对其它框架优点的吸收，MooTools每次更新经常给人惊喜：比如lambda表达式，比如Swiff,
还有非常小但很nice的chain操作的改进等等，一点一滴中能看出MooTools的开发者们开放的心态和极其活跃的思路。jQuery是个人英
雄，YUI是官僚体系，MooTools是开放团队，对我来说，一个开放的、活跃的团队下的产物是最让我放心的。</li>
<li>Ext最早叫做YUI-Ext. 一个使用YUI的牛人Jack Slocum,
用YUI用得不大爽，给YUI官方提意见，无奈YUI更新速度忒慢了，于是Slocum叫了声nnd，挽着袖子便自己干了起来。这一干不得了，Ext迅速
流行，噼里啪啦的如今已成立公司，过得很滋润。Ext我用得不多，直觉里感觉Ext过于庞大繁复，也许会在web
app的应用里有一番作为，但对于占据互联网上大部分web page来说，Ext的应用并不乐观。</li>
</ol>
<p>欢迎讨论。</p>
</div>
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/245057" style="color:red;">已有 <strong>76</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/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 21 Sep 2008 11:27:44 +0800</pubDate>
        <link>http://www.javaeye.com/topic/245057</link>
        <guid>http://www.javaeye.com/topic/245057</guid>
      </item>
          <item>
        <title>LightURL——打造零配置的Struts2开发方式</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://downpour.javaeye.com">downpour</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/242838" style="color:red;">http://www.javaeye.com/topic/242838</a>&nbsp;
          发表时间: 2008年09月16日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景</strong><br /><br />Struts2已经日益成为Web层比较主流的开发框架，它来源于Webwork2，是一个非常优秀的MVC框架。在Webwork2设计之处，Annotation和Ruby on Rails还没有像现在那么火，所以整个框架在配置方面还是沿用了Web框架惯用的XML作为主要的配置方式。<br /><br />随着时代的发展，对于Web程序员来说，如何简化配置成了一个很重要的课题。在这方面，Struts2也有一些探索。在Struts2的官方网站上，我们可以找到一些优秀的plugin来做这些工作：<br /><br /><a href="http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html" target="_blank">http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html</a><br /><br /><a href="http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html" target="_blank">http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html</a><br /><br />LightURL的目的是为了吸取这些优秀的plugin的优点，并支持更方便的配置方式。<br /><br /><strong>安装</strong><br /><br />1. 将struts2-lighturl-plugin.jar加入到classpath下<br /><br />2. 配置你的web.xml<br /><br /><pre name="code" class="java">        
        &lt;!-- Struts Filter -->
    &lt;filter>
        &lt;filter-name>struts&lt;/filter-name>
        &lt;filter-class>com.demo2do.lighturl.LightURLFilter&lt;/filter-class>
    &lt;/filter>

    &lt;!-- Struts URL Definition -->
    &lt;filter-mapping>
        &lt;filter-name>struts&lt;/filter-name>
        &lt;url-pattern>/*&lt;/url-pattern>
    &lt;/filter-mapping>    
</pre><br /><br />3. 需要指定你的action package所在位置和一些基本配置<br /><br />这一步一般在struts.properties中完成。你可以建一个struts.properties的配置文件，并放到classpath下，并指定如下配置<br /><br /><pre name="code" class="java">
## action package config
lighturl.action.packages=com.demo2do.lighturl.action

## action mapping implementation class
struts.mapper.class=com.demo2do.lighturl.LightURLActionMapper

## default parent package
lighturl.action.default.parent.package=struts-config

## define your entity package (optional)
# lighturl.entity.package=com.demo2do.lighturl.entity
</pre><br /><br />在完成以上的步骤后，lighturl的所有配置即告完成，现在你已经可以使用所有lighturl所提供的特性。<br /><br /><strong>Namespace, ActionName和URL映射</strong><br /><br />lighturl所提供的最基本的特性是根据你的Action所在的package，确定namespace和actionName，并进行对应的URL映射。<br /><br />举例说明，你在上面所讲述的struts.properties中，已经指定了你的action package<br /><br /><pre name="code" class="java">
lighturl.action.packages=com.demo2do.lighturl.action
</pre><br /><br />那么，如果你有以下的Action类，那么lighturl将根据如下的规则来确定每个Action类所对应的namespace，actionName和url映射关系<br /><br />1. 根据lighturl.action.packages的配置的package到你的Action类的相对package来确定namespace，如果其中有驼峰法命名，那么转化成"-"连接的单词<br /><ul><li>com.demo2do.lighturl.action.Index&nbsp; ----> /</li><li>com.demo2do.lighturl.action.user.Search ----> /user</li><li>com.demo2do.lighturl.action.blog.category.Index ----> /blog/category</li><li>com.demo2do.lighturl.action.accoutDetail.View ----> /account-detail</li></ul><br />2. 将Action类的类名转化成actionName。如果碰到的Action类以"Action"结尾，则去掉末尾的"Action"，如果其中有驼峰法命名,那么转化成"-"连接的单词<br /><ul><li>com.demo2do.lighturl.action.Index ----> index</li><li>com.demo2do.lighturl.action.user.SearchAction ----> search</li><li>com.demo2do.lighturl.action.blog.CategoryBlog ----> category-blog</li></ul><br />3. 将namespace与actionName拼起来，就成构成映射到具体Action类的url<br /><ul><li>http://host:port/app/user/index ---> com.demo2do.lighturl.action.user.Index </li><li>http://host:port/app/blog/category-blog ---> com.demo2do.lighturl.action.blog.CategoryBlog</li></ul><br />上面的这种URL匹配方式，我称之为：<strong>package匹配</strong><br /><br /><strong>特殊形式的URL</strong><br /><br />应该说根据package来进行Action映射，可以解决绝大多数从url到action的映射配置问题。不过有的时候，我们可能需要支持一些特殊形式的url。LightURL在默认情况下，支持下列2种特殊形式的URL<br /><br />1. 支持将名为Index的Action直接映射到package上<br /><br />这种匹配我称之为：<strong>Namespace匹配</strong>。这一个特性很直观。如果你在某个Action的package下面有一个名为Index的Action类，那么如果你直接访问这个package，那么你可以访问到这个类：<br /><ul><li>com.demo2do.lighturl.action.Index ---> http://host:port/app/</li><li>com.demo2do.lighturl.action.user.Index ---> http://host:port/app/user</li><li>com.demo2do.lighturl.action.blog.category.Index ---> http://host:port/app/blog/category</li></ul><br />2. 支持类似: /entity/${id}形式的URL<br /><br />这种匹配我通常称之为：<strong>entity匹配</strong>。这个特性也比较简单，如果你有某个entity，并且在你的Action package下有一个与entity同名的package。同时在这个package下有一个叫View的Action，那么上述形式的URL会被映射到该Action。<br /><ul><li>com.demo2do.lighturl.action.user.View ---> http://host:port/app/user/3456</li><li>com.demo2do.lighturl.action.blog.View ---> http://host:port/app/user/1113</li></ul><br />你可以通过在struts.properties中指定你entity所在的package来对哪些url可以具备这些特性，如果你输入的url不在你所指定的package中含有entity，那么这个url将无法被识别。<br />针对有些情况，数据库的主键可能不是数字。此时，你可以通过自己实现com.demo2do.lighturl.config.EntityPrimaryKeyIdentifier的接口来指定你的url中id具备什么特点。默认的实现是将主键识别为数字。<br /><br /><strong>使用Annotation来指定映射</strong><br /><br />除了上述这些基本特性以外，还可以通过Annotaion来指定URL映射。目前情况下，LightURL所支持的Annotation有两种类型:<br /><br />1. URL完整匹配<br /><br />URL完整匹配是指如果某个url完整匹配于Annotation中所指定的内容，那么这个URL将被映射到Annotation所在的Action类的method<br /><br /><pre name="code" class="java">
package com.demo2do.lighturl.action.user;

import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Downpour
 *
 */
public class Search extends ActionSupport {
	
	private static final long serialVersionUID = -1728616675239859226L;

	/* (non-Javadoc)
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 */
	@Override
	@Action("/all/search-user")
	public String execute() throws Exception {
		return super.execute();
	}

}
</pre><br /><br />例如，上述的Action类有一个Annotation，那么这个Action和method将被映射到对应的URL:http://host:port/app/all/search-user。<br /><br />注意，此时，虽然从url上来看，这是一个没有什么规则的url，但是其所对应的namespace和actionName还是根据com.demo2do.lighturl.action.user.Search来进行计算的。<br /><br />2. URL Template<br /><br />URL Template是指，url可以匹配Annotaion中指定的某种URL Template，并将其中的可变部分作为参数映射到Action中。<br /><br /><pre name="code" class="java">
package com.demo2do.lighturl.action.blog;

import com.demo2do.lighturl.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Downpour
 *
 */
public class Category extends ActionSupport {

	private static final long serialVersionUID = -1535992103374733252L;

        private Long id;
	
	private int year;
	
	private int month;
	
	private int day;

	/* (non-Javadoc)
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 */
	@Override
	@Action("/blogs/${year}/${month}/${day}")
	public String execute() throws Exception {
		return super.execute();
	}
        
        @Action("/blog/${id}/edit")
	public String edit() throws Exception {
		return super.execute();
	}
        // setters and getters
	
}
</pre><br /><br />在上述的例子中，可以发现，在Annotation中所指定的内容是一个URL Template，如果你有一个url，可以匹配上面的URL Template，那么url将匹配到这个Action的method，并且将对应位置的值注入到Action中的同名参数中。<br /><br />针对上面的例子：<br />http://host:port/app/blogs/2008/08/07将被映射到这个Action的execute，并且2008，08和07分别映射到year，month和day中。<br />http://host:port/app/blog/2345/edit将被映射到Action的edit方法，并且2345映射到id中作为参数<br /><br /><strong>URL的匹配顺序与重复配置的校验</strong><br /><br />在上面的例子中，介绍了那么多的url映射到Action中的方式。他们之间可能会出现冲突，有些冲突，LightURL会在系统启动时为你检查出来，并强制要求你纠正它，而有些冲突，则通过优先级匹配的方式进行。<br /><br />下列冲突将被认为是你必须在系统启动前就进行纠正的：<br />1. Annotation中定义的URL Template互相之间冲突<br /><br />例如：/blogs/${year}/${month}/${day}和/blogs/${category}/${id}/edit就是冲突的。<br /><br />2. Annotation中定义的URL Template与其他Annotation中定义的完全匹配URL冲突<br /><br />例如：/blogs/${year}/${month}和/blogs/category/index就是冲突的。<br /><br />3. Annotation中定义的URL Template与形如/entity/${id}的url定义冲突<br /><br />例如：/user/${id}形式的Annotation定义可能会与系统默认支持的冲突。<br /><br />在其他情况下，如果你定义的URL映射互相直接有冲突，那么LightURL将根据某个顺序进行URL匹配，并找到第一个匹配的映射方式，然后放弃查找。这个顺序为：<br />1. 首先进行<strong>Namespace匹配</strong>，如果url恰好能匹配某个namespace，并且其对应的package下有Index作为Action，那么直接进行匹配。<br />2. 其次查看所有的Annotation定义中，是否存在<strong>完整的URL匹配</strong>，如果找到，那么进行直接匹配。<br />3. 接着进行<strong>package匹配</strong>，将url分解成相应的namespace和actionName，与已有的配置进行匹配，如果找到，那么直接匹配。<br />4. 然后进行<strong>entity匹配</strong>，看看url是否形如:/entity/${id}，如果是，那么直接匹配。<br />5. 最后进行Annotation定义的<strong>Url Template匹配</strong>。<br /><br />如果所有的五种情况都无法进行匹配，那么这个URL将无法被LightURL识别，继续交由Struts2进行后续处理。<br /><br /><br />上面所描述的内容都是Url到Action的映射。下面的部分，描述的是如何在Action执行完毕之后，转到相应的结果view。<br /><br /><strong>Codebehind</strong><br /><br />LightURL支持codebehind。有关codebehind的相关知识，可以参考struts2的相关文档：<br /><a href="http://struts.apache.org/2.x/docs/codebehind-plugin.html" target="_blank">http://struts.apache.org/2.x/docs/codebehind-plugin.html</a><br /><br />有了codebehind的支持，那么从Action转到类似jsp，ftl或者vm的view层组件就不需要任何配置，只要符合一定的命名规范，就可以直接进行转向。<br /><br /><strong>ResultCode的识别</strong><br /><br />但是在很多情况下，我们需要的是全方位的Result类型的支持。例如，有的时候我们需要返回JSON Result，有的时候，我们可能需要Redirect到一个新的Action。此时，我们不得不为此增加一些配置，或者借助Annotation来完成。<br /><br />为此，LightURL提供了一种根据ResultCode进行识别的命名方式来匹配你所指定的Result。<br /><br />以JSON Result为例，你可以这么写：<br /><br /><pre name="code" class="java">
package com.demo2do.lighturl.action.user;

import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Downpour
 *
 */
public class Index extends ActionSupport {

	private static final long serialVersionUID = -5017825114664788765L;

	private User user;
	
	/* (non-Javadoc)
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 */
	@Override
	public String execute() throws Exception {
		return "j:user";
	}

        // setters and getters
}
</pre><br /><br />在这里，你可以发现，resultCode变成了j:user。那么此时，LightURL会将这个resultCode识别成：请返回JSON Result，并且JSON的Result的root为user对象。<br /><br />再例如：<br /><br /><pre name="code" class="java">
package com.demo2do.lighturl.action.user;

import com.demo2do.lighturl.entity.User;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Downpour
 *
 */
public class Index extends ActionSupport {

	private static final long serialVersionUID = -5017825114664788765L;

	private User user;
	
	/* (non-Javadoc)
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 */
	@Override
	public String execute() throws Exception {
		return "r:/user/add-user";
	}

        // setters and getters
}
</pre><br /><br />在这里，"r:/user/add-user"会被识别成：请返回Redirect Result。Redirect的URL为/user/add-user。<br /><br />LightURL默认情况下，实现了对Redirect Result和JSON Result的ResultCode识别，并将他们的前缀分别定制为："r:"("redirect:")或者"j:"("json:")。<br /><br />当然，你可以根据你自己的情况，实现你自己的ResultCode的识别程序，你只需要实现com.demo2do.lighturl.result.ResultCodeConfig接口即可。并在struts.properties中指定你希望LightURL进行ResultCode匹配的顺序。<br /><br /><pre name="code" class="java">
lighturl.result.code.config=yourpackage.ResultCodeConfigImpl1,yourpackage.ResultCodeConfigImpl2
</pre><br /><br />这样，LightURL会根据你所指定的顺序，依次进行ResultCode的匹配，直到找到第一个匹配的Result Type为之。<br /><br />当然，默认情况下，LightURL的匹配顺序为：<br /><br />codebehind -> 你自定义的ResultCode识别实现 -> json -> redirect
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/242838" style="color:red;">已有 <strong>20</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/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 16 Sep 2008 17:39:08 +0800</pubDate>
        <link>http://www.javaeye.com/topic/242838</link>
        <guid>http://www.javaeye.com/topic/242838</guid>
      </item>
          <item>
        <title>Ruby on Rails 在国内的使用情况</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lfhaha.javaeye.com">lfhaha</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/245185" style="color:red;">http://www.javaeye.com/topic/245185</a>&nbsp;
          发表时间: 2008年09月21日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          自己一直在做Java相关开发，请问各位Ruby on Rails在国内的使用情况，比如哪些企业、公司在使用，总体开发人员等
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/245185" style="color:red;">已有 <strong>75</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;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 21 Sep 2008 20:54:25 +0800</pubDate>
        <link>http://www.javaeye.com/topic/245185</link>
        <guid>http://www.javaeye.com/topic/245185</guid>
      </item>
          <item>
        <title>初识django, 一起进入python的世界吧</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/238540" style="color:red;">http://www.javaeye.com/topic/238540</a>&nbsp;
          发表时间: 2008年09月08日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: medium">这几天花了点时间看了一下python世界中的django，正如某大所说，掌握另外一门语言是有必要的，同样我也作出了自己的选择。从这几天的学习中，我确实也发现其他语言及其框架等确实有一种与众不同的感觉。下面我把自己这几天看到的东西稍微作了一下总结，本文并不是django的教程，而是ahuaxuan对django的一些自己的理解，可能有些不成熟的地方，希望大家不要吝惜手中的砖头。<br /><br /><br />一 django的orm<br />如果有人问我最喜欢django什么，我会耗不犹豫的告诉你是django的orm，这个想法的产生完全来自于我长时间来积累的对hibernate的“不满”，虽然从理智的角度来看，hibernate做的是非常的正确的，因为它并不是只针对互连网而产生的，它的主要市场应该还是在企业应用上，不过把它用在互联网并非不可以，只不过大家更多的时候会选择ibatis之类，因为不知道hibernate的人总是会说hibernate没有ibatis快（其实我最烦这个，片面的比较是没有意义的）。正是hibernate的目标是打造成java界一个全方位，全能的orm框架，所以的它学习曲线和使用的复杂度日益的提升，要完全掌握好hibernate不是一件容易的事情（不要告诉我你会点crud，知道点lazy load你就掌握好hibernate了），再回头来看django的orm，如果说要把hibernate说清楚需要800页的书，那么要把django的orm说清楚，200页就够了(事实上它的官方文档只有十几页的样子)。下面我举一个我正在做的例子，这里有一个自关联的对象（事实上django的orm是基于model，这点和ror不太一样，有人跟我讲过ror是数据库驱动），这个对象有一个父对象，通常我们的菜单会定义成这样的对象，这样的菜单可以无限级向下扩展：<br /><br /><pre name="code" class="python">class Category(models.Model):
    id = models.AutoField('id', primary_key=True)
    name = models.CharField(maxlength=50)
    code = models.CharField(maxlength=50)
    parentCategory = models.ForeignKey('self', 'id', null=True)
    enable = models.BooleanField()
    
    def __str__(self):
        return self.name
    
    class Admin:
        list_display = ('id', 'name', 'code', 'parentCategory')
</pre><br />Category中又定义的Admin是为django的Admin模块服务的。<br />瞧，我们定义的域模型只需要这些代码就够了，models.Model是父对象，所有的model对象都需要继承这个对象，这个对象提供了很多常用的数据库方法，不过不是基于sql的，还是基于对象的，如同Criteria一样。下面列出常用的一些查询Category的方法。<br />1，<div class="quote_title">引用</div><div class="quote_div">Category.objects.get(id = request.POST['category'])</div><br />查询category by id（从页面上传过来的）<br />2 <pre name="code" class="python">categoryList = Category.objects.filter(code__contains = “a”,enable = True).order_by(“-id”)[0:5]</pre>，按id倒序，查询enable属性为True的,且code中包含a的category,且取前5个,是不是有很强烈的criteria的味道<br />3 <pre name="code" class="python">category.save()</pre>保存或者更新某个category对象（类似saveOrUpdate操作），充血模型，dao消失了。<br /><br />4 <pre name="code" class="python">category.delete()</pre>删除某个category对象,当然delete方法也是支持批量删除，比如<pre name="code" class="python">categorys.delete()</pre><br /><br />5 复杂的查询可以使用extra方法，例如：<br /><pre name="code" class="java">Category.objects.extra(where=['id IN (3, 4, 5, 20)'])</pre>，还可以使用字符替换法,如：<br /><pre name="code" class="java">Category.objects.extra(where=['code=%s'], params=['a'])</pre><br /><br />当然django的orm提供了很多很常用的功能，这里不一一举例了，注意，这里我说的是提供了很多很常用的功能，至于hibenate中比较复杂的映射策略，在django中我并没有看到。但是我反而高兴我没有在django中找到这个功能，因为django本身的定位是快速的互连网开发，它不需要太多的关注这个领域很少出现的东西，这样带来的优点是学习曲线的降低和开发效率的提高。<br /><br />二 django的模板<br />Django的模板可以说是非常的简洁，简洁到我不知道说什么好，简洁到看一下文档就能上手使用，在java中，freemarker和velocity我都用过，最复杂功能最强大的还是freemarker，支持jsp tag的嵌入让我们可以重用很多已经存在的组件，这一点我在之前的文章中也有过比较详细的描述(强强联手，看freemarker和displaytag的结合)，由于了解，才有发言权，django的模板可以说是为互连网应用而诞生的，简洁及快速开发的特点让人情不自禁的喜欢。大多数模板语言的基本语法都是类似的，比如在freemarker中显示值是${}，而在django是{{}}，freemarker中if判断为&lt;#if>&lt;/#if>，而django中是<br /><pre name="code" class="java">{% if msg %}
	Xx
{% else %}
Xx
{% endif%}</pre><br /><br />再看看在django中渲染模板的方法，有两种:<br />第一种<br /><pre name="code" class="python">def preparePublish(request):
    t = loader.get_template(publishInfo)
return HttpResponse(t.render(Context({'categoryList' : None})))</pre><br />第二种<br /><pre name="code" class="python">c = Context({"categoryList":categoryList})
return render_to_response(indexPage, c)</pre><br />render_to_response相当于封装了loader.get_template方法而已,所有的一切看上去都是那么的简单,模板无处不在，今天你模板了吗？<br /><br />	插一句题外话，关于jsp的题外话，不管是ruby，还是c++，还是python，在它们的web框架中都使用了模板，java中也有很多模板，我们最熟悉的是freemarker和velocity。这从一个侧面反映出我们web开发中的一个模式，那就是我们的view基本上是基于模板产生的，而jsp这个东西应该来说是时代的产物，在那个混乱的落后的时代产生的，不过很奇怪的是现在还有这么多人抱着它不放。<br /><br />三 django的form<br />Django有两种form，一种是自己定义form class，还有一种是通过我们定义的model自动form class。<br />由于ahuaxuan只做 了一个信息发布的小例子，所以并不能全面的了解或者理解django中form的所有细节，不过从我涉及到的部分来讲，我对django的从模型创建表单的做法确实感到有比较大的局限性，因为很多时候，model中的数据 并不是从页面上来的，在这种情况下，form对象被构造出来之后，ahuaxuan还没有找到修改form中值的方法。<br />而自定义form类也比较麻烦，就是要写自己的model，这个和我们之前的做法比较不一样，这里的form代表我们java中的value object，model是domain object，在我们的ssh框架中我们通常把value object继承我们的domain object。虽然一堆又一堆的人提出了反对意见，说要把这两个对象分开，因为他们处在不同的层次中，但是从实践经验中，我们可以看到，这样做没有什么不好。而在django中自定义form和model分开的行为可能比较符合一些人的心理。<br />不过自定义forms也有比较让人称道的地方，在form中我们可以自定义验证规则，同时我们可以根据form对象直接生成页面中的内容，不过这一点其实也有比较麻烦的地方，就是如果要改变样式的时候就比较麻烦。不过总的来说django的form还是比较有特点的，而且一定程度上给我们带来了方便。<br /><br /><br />四 django的url转发<br />Django的url转发是基于正则表达式的，有的人叫好，有的人叫差，我就是叫差的那一拨人之一。url转发应该是一个非常清楚，非常明亮的事情，可是用上这个正则表达式匹配的东西之后，我郁闷了，所以我只能回到遥远的过去去绕过这个东东，我不用总可以了吧。<br /><br />从目前目前掌握的知识来看，django的views里的东西其实是controller，为什么叫views？不得而知，不过一直这么沿用下来了，即使是在自然界，很多表面上去不太一样得东西，其实内部的原理是一样的，我就觉得django的views就是struts1.x中的action，为什么这样说呢，让我们来看看两段比较的代码，第一段是django的，第二段是struts1.x的：<br /><pre name="code" class="python">def index(request):
    
    categoryList = Category.objects.filter(enable = True)
    for cate in categoryList:
        informationList = Information.objects.filter(category = cate)[0:5]
        cate.informationList = informationList
        
    c = Context({"categoryList":categoryList})
return render_to_response(indexPage, c)</pre><br /><br /><br /><br />――――――――――分隔线―――――――――――――――<br /><pre name="code" class="python">public ActionForward getSechandIndex(ActionMapping mapping, ActionForm form,
                                         HttpServletRequest request,
                                         HttpServletResponse response)
            throws Exception {
        setBargainIndex(request);
        return mapping.findForward("bargainHome");
    }
</pre><br />从形式上来看，两者出奇的相似，比如说传入的参数等。我们知道python是面向对象的语言，但是事实上它也支持函数编程，如果def定义在class内部，那么就是对象的方法，否则，就可以认为是函数编程了，看看，我们的views里的东西都是函数，views其实是一个模块，这个模块我们可以认为是struts1.x中的action，而views中的函数可以认为是action中的方法。它们是远房亲戚。<br /><br />那么说到这里，曲线救国的线也找到了，就是struts.1x中DispatchAction，我们只要在url后面追加一个methodName就可以指定我们要调用views中的哪个函数了。代码如下：<br /><pre name="code" class="python">def execute(request):
    methodName = request.GET['methodName']
    return getattr(mark.views, methodName)(request)</pre><br /><br />这个execute方法成为了所有的方法的入口（我们在urls.py中只需要这样定义：<pre name="code" class="python">(r'^$', 'inforplatform.bargin.views.execute')）</pre><br /><br />接着在execute方法中判断methodName的值，然后根据这个值找到对应的函数，再调用它，getattr类似于java中的反射，可以让我们动态调用任何我们想调用的函数（只要我们知道函数名的话）<br /><br />这样我们在urls.py中只需要定义很少的值(有几个模块就定义几行就够了)就可以完成我们的项目了，以后维护起来也没有这么麻烦和复杂。<br />一个小小的缺憾是没有自带restful，不过听说有一个插件可以支持。<br /><br />六 admin<br />Django的admin功能号称是django的杀手级特性(killer feature)，这一说可以说是恰如其分，毫不夸张的，从我做的这个例子来看，当我做网站的时候，基本上只需要关注前台页面的展示这部分，后台的功能基本上都自动有了，比如我做的例子是一个二手信息发布平台，category是二手信息的类型，还有一个information类，和category是多对一的关系，那么在后台，category和information的crud就自动生产了，由于category本身是一个自关联，所以在admin中 add category的时候，admin会根据我model的定义，自动要求选择一个parentCategory，而在add information的页面上，admin会要求我选择一个category来完成对一个information的创建，而以前在java中，这些工作都需要自己完成，当然也有很多工具可以自动生产crud，不过这些开源的工具基本上都是针对单个model的，而且生成的代码需要很大修改才能真正的把功能跑起来，最重要的一点是不能自动生成关联关系的管理。当然我也见过有公司做了基于数据库驱动的代码生产器，能生成完整可用的代码和页面，也包括关联关系的处理，不过由于语言特性的区别，在开发的时候我们还是要不停的重启server才能显示出效果来，虽然在技术上，为ssh实现这个功能并不难，但是会消耗不少时间在上面，消耗了很多时间的话，很少就有公司将其贡献出来了。所以个人认为django在这个功能上做得还是非常不错的，尤其这个功能可以节省开发者很多的时间。甚至有些时候，项目可以双线执行，用户通过admin输入数据，程序员开发前台，这样，前台功能做完之后，数据也有了，基本可以测试上线了。在需要快速开发的小项目上，这个特性显得尤其重要，因为django产生得时候就是基于这个场景。<br /><br />当然有时候后台也没有这么简单，不过还好，admin提供了扩展的功能，我们可以自己写扩展的代码，然后集成到admin中去，不过事实上除了能改变admin的模板，我们不能改变任何admin的代码，不过我时常在想，如果admin支持代码自动生成的功能，那岂不是很美妙，我们可以随意的修改后台的功能了，否则我们就需要自己写代码，不如在生成的代码上扩展方便。<br /><br />要使用admin，必须打开django的权限模块，这里简单介绍一下权限模块，django自带了一个权限模块，这个权限模块中的model对于熟悉权限这块的人来说再熟悉不过了，user，group，permission，user和group多对多，group和permission多对多，在acegi中，我们通常这样定义，user，role，resource，这个和django中的权限是一样的，不过在django中默认的permission的粒度是非常的粗了，是基于model的，如果我们要更细的权限模块，那么就需要自己扩展了。<br /><br />总的来说admin给我的惊喜大于失望，虽然有点小小的不满意，但是总体来说还是非常赞的<br /><br />五 部署<br />在这部分开始之前我也想聊聊之前我们一直在讲，而且将来还一直会讲下去的一个话题――状态。<br />之前我们一直在讨论，把用户的状态保存在一个集中的地方，尤其是大规模集群部署的情况下，同样，对于django来说亦是如此，可以说这条金科玉律不只是针对某种针对某个语言，某个框架，它应该是更高层次的一种理念。那么我们可以把状态放到什么地方呢，目前一些流行的选择是DB(内存表，或实体表),memcached，或者cookie，但这几种选择并不是可以随便互换的，比如业务数据较多的情况下，放在cookie中不是很合适，因为有可能超出cookie大小的限制，那么放在memcached中，很遗憾，memcached(使用slab的情况下)中也有它自己的限制，如果状态数据大小跨度较大，那么丢数据的情况有可能发生，ahuaxuan很久之前在测试环境下就碰到过这种情况，由于线上memcached开得较大，所以没有出现这种情况，关于这种事件发生得内部原因在ahuaxuan的另外一篇文章中已经有了非常详细的描述。那么放在DB上呢，显然，DB的压力也是我们需要考虑的问题之一。当然除了这些主流的选择之外，我们其他选择还有很多，比如memcachedb，或者timesten，或者其他等等，但是对于状态这种东西，尤其状态数据比较重要的情况下，我们一定要深入研究并理解状态数据的存储技术，否则可能会遇到我们异想不到的情况，比如很久之前我想破头也不会想到memcached是LRU是针对某个slab的(而且我还要插一句，LRU的时候其实并不是遍历slab中的chunk链表，而且只遍历最开始的50个数据而已，这样做纯粹是为了速度)。<br /><br /><br />目前对django来说基本上有两种部署策略，<br />第一种是利用mod_python将django运行在apache进程中，还有一种是webserver+fastcgi，这两种方式各有优缺点，在mod_python模式中，我们的webserver必须使用apache，apache在webserver这一领域已经独占鳌头很多年了，市场占有率也是远远的超过其他的webserver，不过近几年来，又崛起了几个其他的webserver，其中比较出名的是ligttpd和nginx，它们都以高性能和低内存消耗对apache发出了挑战，而mod_python是apache的插件，使用这种方式就把我们的webserver限定在apache上了，不过还好apache+mod_python也是非常的稳定的方案了。<br /><br />第二种就是webserver＋fastcgi，这里的webserver就可以随意选择了，大多数的webserver对提供了对fastcgi的支持，比如我们耳熟能详的lighttpd和nginx，而且据称在很多情况下，FastCGI能够提供比mod_python更为优越的安全性和效能。针对小型站点，相对于Apache来说FastCGI更为轻量级。据称qq的个人空间就是c++加fastcgi实现的，哦，这样做的优势在哪里呢，c++的处理速度将会非常的快，也就是说每个fastcgi处理一个请求将会非常快速，比如使用python需要50毫秒，c++处理这个请求有可能只需要20毫秒（这个例子未必准确，只是为了说明fastcgi的特性），虽然在开发上c++比较麻烦一点，不过在性能上，c++肯定是no1了，从这个例子上我们可以看到，使用fastcgi速度取决于处理一次请求的速度（废话，哪个不是这样）。<br /><br />我们来看一下使用fastcgi的一般模式：1、WEB服务器收到客户端的页面请求 2、WEB服务器将这个页面请求委派给一个FastCGI 外部进程（WEB服务器于FastCGI之间是通过socket来连接通讯的） 3、FastCGI外部进程得到WEB服务器委派过来的页面请求信息后进行处理，并且将处理结果（动态页面内容）返回给WEB服务器 4、Web服务器将FastCGI返回回来的结果再转送给客户端浏览器。<br />对我们来说第3步是我们最需要关注的，因为第3步的速度严重影响着整个性能。由于fastcgi是基于进程的，所以，我们要根据我们的应用来开启数量合适的fastcgi进程，多开了是对资源的浪费，少开了就影响性能，这个类似我们在tomcat中开启处理请求的thread一样，只不过tomcat中的request handler thread在配置起来显然更加方便，因为我们只要关注线程池中最大的可以容纳的线程数，最大空闲线程数等就行了。<br /><br />当然fastcgi对ahuaxuan这类刚刚跨出java世界的人来说有些不爽的地方，因为基于进程的东东共享数据比较麻烦，比如写一个ip查询的组件，功能是这样的，把ip地址库加载到内存，然后根据客户端的ip使用折半搜索改ip所在的城市，用java做非常的方便，先把几兆的数据加载到内存中，然后每个线程都来请求就可以了。而对于fastcgi来就比较麻烦了，需要把这些数据加载每个fastcgi进程中，无辜浪费掉一堆内存。不过有得必有失，因为每个fastcgi只能同时处理一个请求，所以使用fastcgi就基本不需要考虑多线程的问题了。<br /><br />通过几天时间的学习，确实使我更加了解了python以及django，但是ahuaxuan也知道要掌握<br />一门语言和技术需要的肯定是不止几天而已，几天可以说只是入门,说的不对的地方恳请大家批评指正.<br /></span>
          <br/><br/>
          <span style="color:red;">
            <a href="http://www.javaeye.com/topic/238540" style="color:red;">已有 <strong>39</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/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 08 Sep 2008 11:22:34 +0800</pubDate>
        <link>http://www.javaeye.com/topic/238540</link>
        <guid>http://www.javaeye.com/topic/238540</guid>
      </item>
          <item>
        <title>使用普元EOS 5.3框架1年+，对EOS的内部评估（仅供参考）</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://wmuu.javaeye.com">wmuu</a>&nbsp;
                    链接：<a href="http://www.javaeye.com/topic/244088" style="color:red;">http://www.javaeye.com/topic/244088</a>&nbsp;
          发表时间: 2008年09月19日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="line-height: 160%;"><span style="font-size: 10.5pt; color: #0000ff; line-height: 160%; font-family: &quot;Times New Roman&quot;;">&nbsp;以下仅针对EOS 5.3框架。</span></p>
<p style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">先说下EOS的优点</span></p>
<ul>
<li>
<div style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">能对足够简单，且稳定的需求进行快速开发。</span></div>
</li>
<li>
<div style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">单表维护向导，视图查询。</span></div>
</li>
<li>
<div style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">对小数据量进行报表统计。</span></div>
</li>
</ul>
<p style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">下面是不足</span></p>
<p style="line-height: 160%;"><span style="color: #0000ff; font-family: Times New Roman;">soa主要是针对跨服务器，分布式服务的，鉴于eos的特点，只能这么比较了。</span></p>
<table class="MsoTableGrid" cellspacing="0" border="1" width="595" cellpadding="0" style="width: 446.4pt; border-collapse: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext;">
<tbody>
<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes;">
<td valign="top" width="295" style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 221.4pt; padding-top: 0cm; background-color: transparent; mso-border-alt: solid windowtext .5pt; border: windowtext 1pt solid;">
<p align="center" style="line-height: 160%; text-align: center;"><strong><span style="font-size: 14pt; color: #222222; line-height: 160%; font-family: 黑体;">SOA</span></strong><strong><span style="font-size: 14pt; color: #222222; line-height: 160%; font-family: 黑体;">的主要特征</span></strong><strong></strong></p>
</td>
<td valign="top" width="300" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 225pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt;">
<p align="center" style="line-height: 160%; text-align: center;"><strong><span style="font-size: 14pt; color: #222222; line-height: 160%; font-family: 黑体; mso-hansi-font-family: 宋体; mso-bidi-font-family: 宋体;">EOS</span></strong></p>
</td>
</tr>
<tr style="mso-yfti-irow: 1;">
<td valign="top" width="295" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 221.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">粗粒度的服务接口</span></span></p>
</td>
<td valign="top" width="300" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 225pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">粒度过细，由于设计思路问题不能方便提供原本该由</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">java</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">语言提供的功能如</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">(</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">加减乘除运算</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">)</span><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">。用法上类似汇编。</span></span></p>
</td>
</tr>
<tr style="mso-yfti-irow: 2;">
<td valign="top" width="295" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 221.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">分级</span></span></p>
</td>
<td valign="top" width="300" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 225pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">基本分为</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">jsp</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">页面标签，</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">pr</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">展现逻辑，</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">biz</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">业务逻辑，和</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">bizlet(</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">含数据库操作</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">)</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">。但全部和</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">EOS</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">专有的</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">XML</span><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">总线捆绑。</span></span></p>
</td>
</tr>
<tr style="mso-yfti-irow: 3;">
<td valign="top" width="295" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 221.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">松散耦合</span></span></p>
</td>
<td valign="top" width="300" style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 225pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt;">
<p style="line-height: 160%;"><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">各模块通过</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">XML</span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体;">总线紧耦合。其他主流轻量级框架无法与</span></span><span style="font-size: 10.5pt; color: #222222; line-height: 160%; font-family: &quot;Times New Roman&quot;;">EOS</span><span style="font-family: 宋体;"><span style="font-size: 10.5pt; color: #222