<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sparkle&#039;s Workshop &#187; Uncategorized</title>
	<atom:link href="http://weavesky.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://weavesky.com</link>
	<description></description>
	<lastBuildDate>Fri, 30 Dec 2011 08:14:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>在Sandy Bridge上安装Snow Leopard</title>
		<link>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/</link>
		<comments>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/#comments</comments>
		<pubDate>Tue, 03 May 2011 13:18:15 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=608</guid>
		<description><![CDATA[把家里的主机从AMD平台转到Intel平台之后，就一直想在上面装一个Snow Leopard来使用，虽然曾经拥有过一台最早的Intel MacBook，不过已经有一段时间没有使用Mac OS了。坦白说，三大操作系统（Windows、Linux、Mac OS）里面，Mac OS同时拥有对程序员良好的*NIX内核，比美Windows的操作界面（甚至更好），可能是最好的开发平台。 Mac的笔记本不算太贵，个人比较推荐，至于台式机部分，Mac mini有点太弱（不过外观相当好），iMac也相当划算（前提是你还没买显示器），我已经有了自己的主机，所以打算在上面装黑苹果。不过，如果你想用Mac OS来开发的话，其实最好买一台真正的Mac，这样可以减少你折腾的时间，把时间花在使用上。 先来说我的机器主要配置： 华擎 H67M + i5 2300 + 华硕 GT240（后加） 如果你不是太新或者太旧的Intel CPU的话，基本上都能支持，因为Mac用过这些CPU，所以AMD比较悲剧了，不过你依然能找到一些被修改过的kernel来使用。Sandy Bridge的CPU属于太新的CPU，虽然最新的MacBook Pro是使用这个CPU，但不知道为什么苹果是给他做了一个单独的10.6.7的更新包，也就是说默认的10.6.7更新包里面所包含的kernel是不支持Sandy Bridge的，有人从专用更新包里面提取了kernel出来，但是不知道为什么在很多主板上，这个kernel不能启动，我的主板就是这样的情况，因此我最后只能使用修改过的kernel。 一般来说，主板和CPU是决定你是否能够启动Snow Leopard的主要因素。不过，决定你的黑苹果是否好用的就是能否找到外设的驱动了，比如说网卡、声卡、显卡等等。目前黑苹果已经很成熟了，能找到很多爱好者写的驱动。我的主板上的外设基本上都被支持，可惜i5 2300的核显暂时还没有解决方案（虽然最新版的MacBook Pro就是使用这个显卡，理论上苹果已经提供了它的驱动，可惜目前还没有办法在黑苹果上使用它），于是上淘宝买了一张GT240，完美支持。 安装方法有几种，一个就是用一些已经打包好的整合碟，里面有破解内核和第三方驱动等，如果你是AMD的CPU最好用这些碟来安装，另一个就是用iBoot+MultiBeast和原版碟来安装，只支持Intel CPU，如果你是Intel CPU的话，推荐用这个方案，装出来的系统比较纯正一点。 网上已经有一些iBoot+MultiBeast的安装方法，大家可以搜索参考一些，这里就不说一些细节，重点是在Sandy Bridge的问题上。到http://www.tonymacx86.com/下载iBoot，必须注意的是必须使用Legacy版，因为Sandy Bridge CPU未被支持的缘故。刻碟启动，然后换Snow Leopard安装碟，安装。装完之后再用iBoot启动，就可以引导硬盘中的系统。 启动成功后，先安装10.6.7更新，不要重启，下载MultiBeast，安装。虽然DSDT的方法是最完美的，不过也很麻烦，需要导出主板等的BIOS来修改。我这里就用EasyBeast的方法来安装，必选EasyBeast、System Utilities，下面的驱动就看自己需要选择。声卡部分，我用ALC8xxHDA（优先选择，不行的话可以尝试VoodooHDA），还需要选上AppleHDA Rollback，这里还需要把自己的声卡ID写进DSDT里面，因为我不用DSDT，所以还需要勾上Non-DSDT HDAEnabler里面相应的声卡型号，显卡部分直接勾上NVEnabler就行了。 接下来是针对Sandy &#8230; <a class="more-link" href="http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>把家里的主机从AMD平台转到Intel平台之后，就一直想在上面装一个Snow Leopard来使用，虽然曾经拥有过一台最早的Intel MacBook，不过已经有一段时间没有使用Mac OS了。坦白说，三大操作系统（Windows、Linux、Mac OS）里面，Mac OS同时拥有对程序员良好的*NIX内核，比美Windows的操作界面（甚至更好），可能是最好的开发平台。</p>
<p>Mac的笔记本不算太贵，个人比较推荐，至于台式机部分，Mac mini有点太弱（不过外观相当好），iMac也相当划算（前提是你还没买显示器），我已经有了自己的主机，所以打算在上面装黑苹果。不过，如果你想用Mac OS来开发的话，其实最好买一台真正的Mac，这样可以减少你折腾的时间，把时间花在使用上。</p>
<p>先来说我的机器主要配置：<br />
华擎 H67M + i5 2300 + 华硕 GT240（后加）</p>
<p>如果你不是太新或者太旧的Intel CPU的话，基本上都能支持，因为Mac用过这些CPU，所以AMD比较悲剧了，不过你依然能找到一些被修改过的kernel来使用。Sandy Bridge的CPU属于太新的CPU，虽然最新的MacBook Pro是使用这个CPU，但不知道为什么苹果是给他做了一个单独的10.6.7的更新包，也就是说默认的10.6.7更新包里面所包含的kernel是不支持Sandy Bridge的，有人从专用更新包里面提取了kernel出来，但是不知道为什么在很多主板上，这个kernel不能启动，我的主板就是这样的情况，因此我最后只能使用修改过的kernel。</p>
<p>一般来说，主板和CPU是决定你是否能够启动Snow Leopard的主要因素。不过，决定你的黑苹果是否好用的就是能否找到外设的驱动了，比如说网卡、声卡、显卡等等。目前黑苹果已经很成熟了，能找到很多爱好者写的驱动。我的主板上的外设基本上都被支持，可惜i5 2300的核显暂时还没有解决方案（虽然最新版的MacBook Pro就是使用这个显卡，理论上苹果已经提供了它的驱动，可惜目前还没有办法在黑苹果上使用它），于是上淘宝买了一张GT240，完美支持。</p>
<p>安装方法有几种，一个就是用一些已经打包好的整合碟，里面有破解内核和第三方驱动等，如果你是AMD的CPU最好用这些碟来安装，另一个就是用iBoot+MultiBeast和原版碟来安装，只支持Intel CPU，如果你是Intel CPU的话，推荐用这个方案，装出来的系统比较纯正一点。</p>
<p>网上已经有一些iBoot+MultiBeast的安装方法，大家可以搜索参考一些，这里就不说一些细节，重点是在Sandy Bridge的问题上。到http://www.tonymacx86.com/下载iBoot，必须注意的是<strong>必须使用Legacy版</strong>，因为Sandy Bridge CPU未被支持的缘故。刻碟启动，然后换Snow Leopard安装碟，安装。装完之后再用iBoot启动，就可以引导硬盘中的系统。</p>
<p>启动成功后，先安装10.6.7更新，不要重启，下载MultiBeast，安装。虽然DSDT的方法是最完美的，不过也很麻烦，需要导出主板等的BIOS来修改。我这里就用EasyBeast的方法来安装，必选EasyBeast、System Utilities，下面的驱动就看自己需要选择。声卡部分，我用ALC8xxHDA（优先选择，不行的话可以尝试VoodooHDA），还需要选上AppleHDA Rollback，这里还需要把自己的声卡ID写进DSDT里面，因为我不用DSDT，所以还需要勾上Non-DSDT HDAEnabler里面相应的声卡型号，显卡部分直接勾上NVEnabler就行了。</p>
<p>接下来是针对Sandy Bridge的处理，官方给出的方法是一个BridgeHelper的软件，其实就是安装最新的MacBook Pro里面的kernel，你可以先试一下这个方案，如果可以启动系统的话，优先选择这个方案。可惜我的主板不行，于是我<strong>从iBoot Legacy里提取了kernel</strong>，替换系统的。</p>
<p>另外，我还遇到一个问题是鼠标的移动会很卡的情况，好像是因为时钟频率不正确的缘故，需要在启动参数里面<strong>增加busratio=28</strong>（28是我的CPU的实际倍频数）</p>
<p>这样，我的黑苹果就装好了。虽然还有些小问题，不过我暂时不打算处理了，能正常使用就行了。</p>
<p>下一步需要处理的问题有<br />
1、休眠。需要相应kernel的sleep enabler。由于我的是台式机，我觉得休眠不是很重要就不处理了。<br />
2、HDMI输出，并且带上声音。是的，黑苹果也能这样。tonymacx86上已经提供了解决方案<br />
3、DSDT，为了让系统属性里面正确显示各种硬件信息<br />
4、真正的Sandy Bridge支持。CPU和显卡</p>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MongoDB介绍</title>
		<link>http://weavesky.com/2010/11/22/mongodb/</link>
		<comments>http://weavesky.com/2010/11/22/mongodb/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 08:59:25 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=603</guid>
		<description><![CDATA[2010-11-20在广州小沙龙的ppt，时间比较匆忙写的比较简单 MongoDB介绍 View more presentations from popeast. Most Commented Posts我与Mercurial架设你的CruiseControl我为什么放弃使用cactipython cmemcache是不是线程安全的python在生产环境可选的memcached lib]]></description>
			<content:encoded><![CDATA[<div id="__ss_5855482" style="width: 425px;">2010-11-20在广州小沙龙的ppt，时间比较匆忙写的比较简单</div>
<div style="width: 425px;"></div>
<div style="width: 425px;"><strong><a title="MongoDB介绍" href="http://www.slideshare.net/popeast/mongodb-5855482">MongoDB介绍</a></strong><object id="__sse5855482" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodb-101121193802-phpapp02&amp;stripped_title=mongodb-5855482&amp;userName=popeast" /><param name="name" value="__sse5855482" /><param name="allowfullscreen" value="true" /><embed id="__sse5855482" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodb-101121193802-phpapp02&amp;stripped_title=mongodb-5855482&amp;userName=popeast" name="__sse5855482" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>
<div id="__ss_5855482" style="width: 425px;">
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/popeast">popeast</a>.</div>
</div>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2010/11/22/mongodb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>python在生产环境可选的memcached lib</title>
		<link>http://weavesky.com/2009/05/15/python-memcached-lib-in-production/</link>
		<comments>http://weavesky.com/2009/05/15/python-memcached-lib-in-production/#comments</comments>
		<pubDate>Fri, 15 May 2009 03:06:56 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=570</guid>
		<description><![CDATA[memcached对动态语言帮助很大，因为动态语言的模式和实际的部署模型，python/php/ruby等不可能像Java那样在JVM内存中开辟一块内存来缓冲数据（而实际上Java这样做也会遇到容量不够，GC，集群等问题）。不过在实际使用中，我发现python memcached lib并没有想象中那么成熟、完整，经过一番研究之后，目前至少能勉强在生产环境中使用。 从memcached官方wiki中可以看到，python还是有不少可以使用的lib的，但是经过测试和比较之后，发现选择的方案也不多。我们还是从比较出名的web框架入手吧，毫无疑问，Django是目前python最好的框架之一，在生产环境使用它的人也比较多，而且它的文档很详细，有一节就是专门提到cache的部分 。Django推荐使用cmemcache，在不能使用cmemcache的情况（例如windows机器），就使用python-memcached。经过我的实际测试，这个或许不是性能最好，版本最新，功能最多的选择，但是是一个很稳靠的选择。 cmemcache封装的是libmemcache，这个类库很久没有更新了，目前libmemcached比较活跃，功能也比较全面。这里值得一提的是Python libmemcached是来自豆瓣贡献的类库，不过因为使用的人不多，所以最终我没有选择。另外还有一个pylibmc也是对libmemcached的封装，这是cmemcache_hash的作者写的类库（稍后会提到cmemcache_hash），很可惜我一直没有编译成功。 但是实际使用cmemcache/python-memcached的组合也是要进行一些封装的，首先有cmemcache不是线程安全的问题 ，另外就是Python libmemcached的hash算法有问题。什么？你从来不用超过1个的memcached服务器？我还是建议你至少用2个memcached服务器吧，至少有backup。 而cmemcache和Python libmemcached的hash算法不一样。这里我们还需要cmemcache_hash，名字可能有少少误导，它的作用是领到Python libmemcached的hash跟cmemcache一致 于是我们的封装代码大概是这样 try: import cmemcache as memcache logger.warn&#40;'load cmemcache'&#41; # although cmemcache might be thread safe # but we still make it thread local # also it can &#8230; <a class="more-link" href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>memcached对动态语言帮助很大，因为动态语言的模式和实际的部署模型，python/php/ruby等不可能像Java那样在JVM内存中开辟一块内存来缓冲数据（而实际上Java这样做也会遇到容量不够，GC，集群等问题）。不过在实际使用中，我发现python memcached lib并没有想象中那么成熟、完整，经过一番研究之后，目前至少能勉强在生产环境中使用。</p>
<p> <a href="http://code.google.com/p/memcached/wiki/Clients">从memcached官方wiki中可以看到</a>，python还是有不少可以使用的lib的，但是经过测试和比较之后，发现选择的方案也不多。我们还是从比较出名的web框架入手吧，毫无疑问，Django是目前python最好的框架之一，在生产环境使用它的人也比较多，而且它的文档很详细，<a href="http://docs.djangoproject.com/en/dev/topics/cache/#memcached">有一节就是专门提到cache的部分</a> 。Django推荐使用cmemcache，在不能使用cmemcache的情况（例如windows机器），就使用python-memcached。经过我的实际测试，这个或许不是性能最好，版本最新，功能最多的选择，但是是一个很稳靠的选择。</p>
<p>cmemcache封装的是libmemcache，这个类库很久没有更新了，目前libmemcached比较活跃，功能也比较全面。<a href="http://code.google.com/p/python-libmemcached">这里值得一提的是Python libmemcached是来自豆瓣贡献的类库</a>，不过因为使用的人不多，所以最终我没有选择。<a href="http://pypi.python.org/pypi/pylibmc">另外还有一个pylibmc也是对libmemcached的封装</a>，这是cmemcache_hash的作者写的类库（稍后会提到cmemcache_hash），很可惜我一直没有编译成功。</p>
<p>但是实际使用cmemcache/python-memcached的组合也是要进行一些封装的，<a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/">首先有cmemcache不是线程安全的问题</a> ，另外就是Python libmemcached的hash算法有问题。什么？你从来不用超过1个的memcached服务器？我还是建议你至少用2个memcached服务器吧，至少有backup。</p>
<p>而cmemcache和Python libmemcached的hash算法不一样。<a href="http://pypi.python.org/pypi/cmemcache_hash">这里我们还需要cmemcache_hash</a>，名字可能有少少误导，它的作用是领到Python libmemcached的hash跟cmemcache一致</p>
<p>于是我们的封装代码大概是这样</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> cmemcache <span style="color: #ff7700;font-weight:bold;">as</span> memcache
    logger.<span style="color: black;">warn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'load cmemcache'</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># although cmemcache might be thread safe</span>
    <span style="color: #808080; font-style: italic;"># but we still make it thread local</span>
    <span style="color: #808080; font-style: italic;"># also it can use separate socket connect in each thread for more performance</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">threading</span> <span style="color: #ff7700;font-weight:bold;">import</span> local
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>, e:
    logger.<span style="color: black;">warn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'cmemcache error: %s'</span>, e<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> memcache
    <span style="color: #ff7700;font-weight:bold;">import</span> cmemcache_hash
    logger.<span style="color: black;">warn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'load python-memcache with cmemcache_hash'</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># python-memcache is already using thread local</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> local<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Memcache<span style="color: black;">&#40;</span>local<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, servers<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._current = memcache.<span style="color: black;">Client</span><span style="color: black;">&#40;</span>servers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> current<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._current</pre></div></div>

<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/" title="python-memcached是不是线程安全的">python-memcached是不是线程安全的</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2009/05/15/python-memcached-lib-in-production/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>python cmemcache是不是线程安全的</title>
		<link>http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/</link>
		<comments>http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/#comments</comments>
		<pubDate>Sat, 14 Feb 2009 03:45:12 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=560</guid>
		<description><![CDATA[答案是，我不确定，但是我更倾向于认为它是线程不安全的 原因在于 1、网上任何讨论，都从未提及过cmemcache所用的libmemcache是线程安全的，也没有提及过cmemcache实现了线程安全，而libmemcached从一开始就强调自己是线程安全的 2、我个人不太熟悉C代码，所以看libmemcache的代码也没有办法判断出来，但是我看到cmemcache的c接口代码在针对socket操作的代码前后使用了Py_BEGIN_ALLOW_THREADS;Py_END_ALLOW_THREADS;进行包围，而这两个宏的作用，是解除GIL，让多线程可以进入相应的代码。天啊，本来我们还期望对socket操作进行加锁，现在竟然还竟然解除GIL。本来因为GIL的存在，可能还有些希望，现在cmemcache为了让socket操作不要阻塞，反而令到自己是线程不安全的。（如有理解错误请指正） 3、python一直习惯的部署模型是单线程多进程，所以线程安全对很多类库来说，并不重要也不考虑。但是现在越来越多的python程序部署使用了多线程的模型（又或者多线程多进程），线程安全问题也凸显出来 综上所属，我的结论是，我不确定是否线程安全的，呵呵，但是我认为要进行线程安全的修正，至少没有坏处 修正方法很简单，直接套用python-memcached的做法（至于这种做法的优劣也在那篇文章有提及到） import cmemcache as memcache from threading import local class Memcache&#40;local&#41;: def __init__&#40;self, servers&#41;: self._current = memcache.Client&#40;servers&#41; def current&#40;self&#41;: return self._current Related Postspython在生产环境可选的memcached libpython-memcached是不是线程安全的]]></description>
			<content:encoded><![CDATA[<p>答案是，我不确定，但是我更倾向于认为它是线程不安全的</p>
<p>原因在于<br />
1、网上任何讨论，都从未提及过cmemcache所用的libmemcache是线程安全的，也没有提及过cmemcache实现了线程安全，而libmemcached从一开始就强调自己是线程安全的<br />
2、我个人不太熟悉C代码，所以看libmemcache的代码也没有办法判断出来，但是我看到cmemcache的c接口代码在针对socket操作的代码前后使用了Py_BEGIN_ALLOW_THREADS;Py_END_ALLOW_THREADS;进行包围，而这两个宏的作用，是解除GIL，让多线程可以进入相应的代码。天啊，本来我们还期望对socket操作进行加锁，现在竟然还竟然解除GIL。本来因为GIL的存在，可能还有些希望，现在cmemcache为了让socket操作不要阻塞，反而令到自己是线程不安全的。（如有理解错误请指正）<br />
3、python一直习惯的部署模型是单线程多进程，所以线程安全对很多类库来说，并不重要也不考虑。但是现在越来越多的python程序部署使用了多线程的模型（又或者多线程多进程），线程安全问题也凸显出来</p>
<p>综上所属，我的结论是，我不确定是否线程安全的，呵呵，但是我认为要进行线程安全的修正，至少没有坏处</p>
<p>修正方法很简单，直接套用<a href="http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/">python-memcached的做法</a>（至于这种做法的优劣也在那篇文章有提及到）</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> cmemcache <span style="color: #ff7700;font-weight:bold;">as</span> memcache
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">threading</span> <span style="color: #ff7700;font-weight:bold;">import</span> local
<span style="color: #ff7700;font-weight:bold;">class</span> Memcache<span style="color: black;">&#40;</span>local<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, servers<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._current = memcache.<span style="color: black;">Client</span><span style="color: black;">&#40;</span>servers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> current<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._current</pre></div></div>

<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li><li><a href="http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/" title="python-memcached是不是线程安全的">python-memcached是不是线程安全的</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>python-memcached是不是线程安全的</title>
		<link>http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/</link>
		<comments>http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 07:16:45 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[thread]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=553</guid>
		<description><![CDATA[答案是肯定的，前提你在使用Python 2.4+和python-memcached 1.36+ 为什么我们需要线程安全的memcached client，因为我们的实际应用一般是多线程的模型，例如cherrypy、twisted，如果python-memcached不是线程安全的话，引起的问题不仅仅是并发修改共享变量这么简单，是外部socket链接的数据流的混乱 python-memcached怎么实现线程安全的呢？查看源代码看到 try: # Only exists in Python 2.4+ from threading import local except ImportError: # TODO: add the pure-python local implementation class local&#40;object&#41;: pass &#160; &#160; class Client&#40;local&#41;: 很取巧的让Client类继承threading.local，也就是Client里面的每一个属性都是跟当前线程绑定的。实现虽然不太优雅，但是很实在 但是别以为这样就可以随便在线程里面用python-memcached了，因为这种thread local的做法，你的应用必须要使用thread pool的模式，而不能不停创建销毁thread，因为每一个新线程的创建，对于就会使用一个全新的Client，也就是一个全新的socket链接，如果不停打开创建销毁thread的话，就会导致不停的创建销毁socket链接，导致性能大量下降。幸好，无论是cherrypy还是twisted，都是使用了thread pool的模式 参考资料： http://code.djangoproject.com/ticket/3701 &#8230; <a class="more-link" href="http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>答案是肯定的，前提你在使用Python 2.4+和python-memcached 1.36+<br />
为什么我们需要线程安全的memcached client，因为我们的实际应用一般是多线程的模型，例如cherrypy、twisted，如果python-memcached不是线程安全的话，引起的问题不仅仅是并发修改共享变量这么简单，是外部socket链接的数据流的混乱<br />
python-memcached怎么实现线程安全的呢？查看源代码看到</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #808080; font-style: italic;"># Only exists in Python 2.4+</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">threading</span> <span style="color: #ff7700;font-weight:bold;">import</span> local
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #808080; font-style: italic;"># TODO:  add the pure-python local implementation</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> local<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Client<span style="color: black;">&#40;</span>local<span style="color: black;">&#41;</span>:</pre></div></div>

<p>很取巧的让Client类继承threading.local，也就是Client里面的每一个属性都是跟当前线程绑定的。实现虽然不太优雅，但是很实在<br />
但是别以为这样就可以随便在线程里面用python-memcached了，因为这种thread local的做法，你的应用必须要使用thread pool的模式，而不能不停创建销毁thread，因为每一个新线程的创建，对于就会使用一个全新的Client，也就是一个全新的socket链接，如果不停打开创建销毁thread的话，就会导致不停的创建销毁socket链接，导致性能大量下降。幸好，无论是cherrypy还是twisted，都是使用了thread pool的模式</p>
<p>参考资料：<br />
<a href="http://code.djangoproject.com/ticket/3701">http://code.djangoproject.com/ticket/3701</a><br />
<a href="http://lists.danga.com/pipermail/memcached/2007-June/004482.html">http://lists.danga.com/pipermail/memcached/2007-June/004482.html</a></p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial和Git的主要区别</title>
		<link>http://weavesky.com/2008/08/17/difference-between-mercurial-git/</link>
		<comments>http://weavesky.com/2008/08/17/difference-between-mercurial-git/#comments</comments>
		<pubDate>Sun, 17 Aug 2008 03:17:58 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=550</guid>
		<description><![CDATA[1、Mercurial用Python开发，Git用C开发，相对来说，Git比较快，但是Mercurial的性能也不差 2、Mercurial对windows平台支持比较好，而且有一个开发中的TortoiseHg，而且NetBeans内置支持，Git主要还是用命令行，而且对windows不太友好 3、Mercurial核心指令只有10个左右，Git核心指令几十个，全部指令更多了，Mercurial比较简单，也容易上手 4、Mercurial一个目录树就是一个分支，需要使用分支就必须clone一份完整的目录树，这样比较浪费空间，而且使用IDE的时候要为新分支开一个新项目，Git支持本地分支，在一个目录树里面开无限个分支，切换非常方便迅速。这个功能也是我慢慢迁移到Git上的主要原因 5、Git内置对SVN的支持，现在也很多人在SVN repo上使用Git，方便自己的分支开发，当然跟别人合作还是会受到SVN本身的限制，Mercurial有一个第三方的hgsvn，最初的版本还有编码问题，现在已经修正了，但是它只能从SVN导入数据到Mercurial，不能把在Mercurial做的提交导入SVN，作者说未来会制作这个功能，这样就限制了hgsvn的使用，只能作为类似备份的性质 Related PostsMercurial续我与Mercurial]]></description>
			<content:encoded><![CDATA[<p>1、Mercurial用Python开发，Git用C开发，相对来说，Git比较快，但是Mercurial的性能也不差<br />
2、Mercurial对windows平台支持比较好，而且有一个开发中的TortoiseHg，而且NetBeans内置支持，Git主要还是用命令行，而且对windows不太友好<br />
3、Mercurial核心指令只有10个左右，Git核心指令几十个，全部指令更多了，Mercurial比较简单，也容易上手<br />
4、Mercurial一个目录树就是一个分支，需要使用分支就必须clone一份完整的目录树，这样比较浪费空间，而且使用IDE的时候要为新分支开一个新项目，Git支持本地分支，在一个目录树里面开无限个分支，切换非常方便迅速。这个功能也是我慢慢迁移到Git上的主要原因<br />
5、Git内置对SVN的支持，现在也很多人在SVN repo上使用Git，方便自己的分支开发，当然跟别人合作还是会受到SVN本身的限制，Mercurial有一个第三方的hgsvn，最初的版本还有编码问题，现在已经修正了，但是它只能从SVN导入数据到Mercurial，不能把在Mercurial做的提交导入SVN，作者说未来会制作这个功能，这样就限制了hgsvn的使用，只能作为类似备份的性质</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/03/19/mercurial-more/" title="Mercurial续">Mercurial续</a></li><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2008/08/17/difference-between-mercurial-git/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>并发相关</title>
		<link>http://weavesky.com/2008/03/26/about-concurrent/</link>
		<comments>http://weavesky.com/2008/03/26/about-concurrent/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 13:40:59 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=540</guid>
		<description><![CDATA[http://www.javaeye.com/post/498557 copy on write array list ConcurrentHashMap ReentrantLock ReentrantReadWriteLock CAS 我都有在用，JDK内置 一直都想写一些关于它们的文章，不过始终太松散，而且我是知道原理然后直接用API而已 我随便说一些 楼主的copy on write模式是可取的，JDK很早就引入copy on write array list来处理Listener部分，在写入非常非常少的情况下，copy on write其实是很好的。至于楼主的实现好不好就不知道了 ConcurrentHashMap用了多个锁来处理，里面有一个一个的bucket来隔离锁，默认就是16个bucket&#038;锁。但是它也有缺点，就是不能保证数据绝对准确，例如他的size就是不准确的。但是它肯定是线程安全的 ReentrantLock是可以代替synchronized的东西，除了写起来比synchronized难稍稍。默认是non-fair模式，比synchronized快很多，如果改成fair就会下降到跟synchronized差不多 ReadWriteLock很简单，read不互斥，write互斥 CAS就是AtomicInteger之类的了，使用了CPU的交换指令，理论上比锁快，但是在高并发的环境一样会下降 你们还是看一下JDK源代码和JavaDoc好过了，你们的讨论本来就有答案的 Most Commented Posts我与Mercurial架设你的CruiseControl我为什么放弃使用cactipython cmemcache是不是线程安全的python在生产环境可选的memcached lib]]></description>
			<content:encoded><![CDATA[<p>http://www.javaeye.com/post/498557</p>
<blockquote><p>
copy on write array list<br />
ConcurrentHashMap<br />
ReentrantLock<br />
ReentrantReadWriteLock<br />
CAS<br />
我都有在用，JDK内置<br />
一直都想写一些关于它们的文章，不过始终太松散，而且我是知道原理然后直接用API而已</p>
<p>我随便说一些<br />
楼主的copy on write模式是可取的，JDK很早就引入copy on write array list来处理Listener部分，在写入非常非常少的情况下，copy on write其实是很好的。至于楼主的实现好不好就不知道了</p>
<p>ConcurrentHashMap用了多个锁来处理，里面有一个一个的bucket来隔离锁，默认就是16个bucket&#038;锁。但是它也有缺点，就是不能保证数据绝对准确，例如他的size就是不准确的。但是它肯定是线程安全的</p>
<p>ReentrantLock是可以代替synchronized的东西，除了写起来比synchronized难稍稍。默认是non-fair模式，比synchronized快很多，如果改成fair就会下降到跟synchronized差不多</p>
<p>ReadWriteLock很简单，read不互斥，write互斥</p>
<p>CAS就是AtomicInteger之类的了，使用了CPU的交换指令，理论上比锁快，但是在高并发的环境一样会下降</p>
<p>你们还是看一下JDK源代码和JavaDoc好过了，你们的讨论本来就有答案的
</p></blockquote>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2008/03/26/about-concurrent/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mercurial续</title>
		<link>http://weavesky.com/2008/03/19/mercurial-more/</link>
		<comments>http://weavesky.com/2008/03/19/mercurial-more/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 15:38:50 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://weavesky.com/2008/03/19/mercurial%e7%bb%ad/</guid>
		<description><![CDATA[上次谈到一些Mercurial的事情，后来因为忙别的事情没有继续写下去。中途跟cyfdecyf通过几次email讨论Mercurial。总体来说，我对Mercurial和分布式版本管理的理解还是比较松散的，比较难形成文章，但还是很希望把我所知道的写出来。 我对分布式版本管理的理解很简单。首先这里假设你有一般版本管理软件的概念（CVS或者SVN）。假设你在家里装了一个SVN服务器，你在家里编写的代码都提交上去。在公司也装了一个SVN，你在公司编写的代码也都提交上去。这里就有两个完全独立的SVN服务器了。分布式版本管理，就是这两个SVN服务器之间可以互相提交，其操作就像你提交上其中一台SVN那样，SVN之间互相提交就会将多个changeset同时提交。而且这两个SVN服务器没有主次之分，这样处理是很容易混乱的，实际上，我们会架设另一个SVN服务器，作为两个SVN的父，两个SVN向父提交changeset。这个行为仅仅是方便我们管理的一个比较好的参考做法，并没有强制。另外，当然SVN服务器是不支持互相提交的，于是我们需要一个分布式版本管理软件。 个人觉得，一台SVN就好像一台MySQL，我们只有一个数据库。而分布式版本管理就好像Master-Master MySQL集群。有经验的朋友就会知道，在集群中使用自增字段是不可取的，就像SVN的changeset id是自增的不能适应分布一样。做MySQL集群很经常会用UUID作为主键，分布式版本管理也使用了类似的机制来保证多个库之间的changeset有唯一的ID不会冲突。这个已经是比较细节的处理问题。这里暂时不打算细节研究具体的机制或者使用方法，先有一个大概的概念，看软件的refrence很快会上手的。 再待续 预告： 权限问题 Mercurial目前的情况 远程模式 在Dreamhost上使用Mercurial Mercurial基本使用 Related PostsMercurial和Git的主要区别我与Mercurial]]></description>
			<content:encoded><![CDATA[<p><a href="http://weavesky.com/2008/01/25/mercurial-and-me/">上次谈到一些Mercurial的事情</a>，后来因为忙别的事情没有继续写下去。中途跟<a href="http://chenyufei.name/blog/">cyfdecyf</a>通过几次email讨论Mercurial。总体来说，我对Mercurial和分布式版本管理的理解还是比较松散的，比较难形成文章，但还是很希望把我所知道的写出来。</p>
<p>我对分布式版本管理的理解很简单。首先这里假设你有一般版本管理软件的概念（CVS或者SVN）。假设你在家里装了一个SVN服务器，你在家里编写的代码都提交上去。在公司也装了一个SVN，你在公司编写的代码也都提交上去。这里就有两个完全独立的SVN服务器了。分布式版本管理，就是这两个SVN服务器之间可以互相提交，其操作就像你提交上其中一台SVN那样，SVN之间互相提交就会将多个changeset同时提交。而且这两个SVN服务器没有主次之分，这样处理是很容易混乱的，实际上，我们会架设另一个SVN服务器，作为两个SVN的父，两个SVN向父提交changeset。这个行为仅仅是方便我们管理的一个比较好的参考做法，并没有强制。另外，当然SVN服务器是不支持互相提交的，于是我们需要一个分布式版本管理软件。</p>
<p>个人觉得，一台SVN就好像一台MySQL，我们只有一个数据库。而分布式版本管理就好像Master-Master MySQL集群。有经验的朋友就会知道，在集群中使用自增字段是不可取的，就像SVN的changeset id是自增的不能适应分布一样。做MySQL集群很经常会用UUID作为主键，分布式版本管理也使用了类似的机制来保证多个库之间的changeset有唯一的ID不会冲突。这个已经是比较细节的处理问题。这里暂时不打算细节研究具体的机制或者使用方法，先有一个大概的概念，看软件的refrence很快会上手的。</p>
<p>再待续</p>
<p>预告：<br />
权限问题<br />
Mercurial目前的情况<br />
远程模式<br />
在Dreamhost上使用Mercurial<br />
Mercurial基本使用</p>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/08/17/difference-between-mercurial-git/" title="Mercurial和Git的主要区别">Mercurial和Git的主要区别</a></li><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2008/03/19/mercurial-more/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>给《程序员》写的MINA文章已经出刊了</title>
		<link>http://weavesky.com/2008/02/26/mina-article-for-magazine/</link>
		<comments>http://weavesky.com/2008/02/26/mina-article-for-magazine/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 14:45:48 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/2008/02/26/%e7%bb%99%e3%80%8a%e7%a8%8b%e5%ba%8f%e5%91%98%e3%80%8b%e5%86%99%e7%9a%84mina%e6%96%87%e7%ab%a0%e5%b7%b2%e7%bb%8f%e5%87%ba%e5%88%8a%e4%ba%86/</guid>
		<description><![CDATA[第一次给杂志写文章，没什么经验，行文一般般,呵呵。不过也是能顺利出刊。 对文章有任何意见和建议,或者讨论MINA,可以在这里留言 迟点我再写一些MINA的心得 Most Commented Posts我与Mercurial架设你的CruiseControl我为什么放弃使用cactipython cmemcache是不是线程安全的python在生产环境可选的memcached lib]]></description>
			<content:encoded><![CDATA[<p>第一次给杂志写文章，没什么经验，行文一般般,呵呵。不过也是能顺利出刊。</p>
<p>对文章有任何意见和建议,或者讨论MINA,可以在这里留言</p>
<p>迟点我再写一些MINA的心得</p>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2008/02/26/mina-article-for-magazine/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>架设你的CruiseControl</title>
		<link>http://weavesky.com/2008/01/28/deploy-cruisecontrol/</link>
		<comments>http://weavesky.com/2008/01/28/deploy-cruisecontrol/#comments</comments>
		<pubDate>Mon, 28 Jan 2008 09:24:30 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/2008/01/28/deploy-cruisecontrol/</guid>
		<description><![CDATA[说实在话，07年最大的感悟就是重新认识了TDD和持续集成的意义，这个下次有机会再说。这次要说的是部署一个持续集成服务器。 持续集成服务器的作用其实很简单，就是check out最新的代码，然后运行指定的script，然后把结果记录下来，还可以将结果（尤其是错误的结果）通过email等手段发给程序员。 事情倒是很简单，但是我们为什么要专门的软件呢，当然你也可以自己写bash script来做这些事情，做着做着你就会发现差不多实现一个CruiseControl出来了，呵呵，无谓重复发明轮子。 常用的持续集成服务器有CruiseControl、Luntbuild 和 Anthill等，相对来说CruiseControl比较老牌，支持度也比较好，不过实际使用的时候还是觉得不太好使（最近又发现了一个软件Hudson，Netbeans在使用） 下面是安装和配置过程，可能有一些细节不是很准确，因为已经是比较早之前安装的 从官方网站下载最新版的CruiseControl 2.7.1，我选用的是exe的版本，因为我的服务器是windows的，相对来说，exe版本有一些预设的参数，配置会简单些 运行安装程序，默认装在C:\Program Files\CruiseControl，可以不改动，而实际的项目文件可以放在其他盘上面的 安装成功之后运行cruisecontrol.bat，就能看到一个dos窗口运行，这个时候访问本机8080端口就可以看到一个示范项目 接下来修改配置文件 打开config.xml，可以看到示范例子的配置，把它都注释掉，不过其实我最后的配置也跟它差不多 直接贴我的配置吧，然后再来解释 &#60;project name=&#34;xxx-xxx&#34;&#62; &#60;listeners&#62; &#60;currentbuildstatuslistener file=&#34;logs/${project.name}/status.txt&#34;/&#62; &#60;/listeners&#62; &#60;bootstrappers&#62; &#60;svnbootstrapper localWorkingCopy=&#34;D:/cc/${project.name}&#34; /&#62; &#60;/bootstrappers&#62; &#60;modificationset quietperiod=&#34;30&#34;&#62; &#60;svn localWorkingCopy=&#34;D:/cc/${project.name}&#34;/&#62; &#60;/modificationset&#62; &#60;schedule interval=&#34;300&#34;&#62; &#60;ant anthome=&#34;apache-ant-1.7.0&#34; buildfile=&#34;D:/cc/${project.name}/build.xml&#34; target=&#34;svnup test&#34; &#8230; <a class="more-link" href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>说实在话，07年最大的感悟就是重新认识了TDD和持续集成的意义，这个下次有机会再说。这次要说的是部署一个持续集成服务器。</p>
<p>持续集成服务器的作用其实很简单，就是check out最新的代码，然后运行指定的script，然后把结果记录下来，还可以将结果（尤其是错误的结果）通过email等手段发给程序员。</p>
<p>事情倒是很简单，但是我们为什么要专门的软件呢，当然你也可以自己写bash script来做这些事情，做着做着你就会发现差不多实现一个CruiseControl出来了，呵呵，无谓重复发明轮子。</p>
<p>常用的持续集成服务器有CruiseControl、Luntbuild 和 Anthill等，相对来说CruiseControl比较老牌，支持度也比较好，不过实际使用的时候还是觉得不太好使（最近又发现了一个软件Hudson，Netbeans在使用）</p>
<p>下面是安装和配置过程，可能有一些细节不是很准确，因为已经是比较早之前安装的</p>
<p>从官方网站下载最新版的CruiseControl 2.7.1，我选用的是exe的版本，因为我的服务器是windows的，相对来说，exe版本有一些预设的参数，配置会简单些</p>
<p>运行安装程序，默认装在C:\Program Files\CruiseControl，可以不改动，而实际的项目文件可以放在其他盘上面的</p>
<p>安装成功之后运行cruisecontrol.bat，就能看到一个dos窗口运行，这个时候访问本机8080端口就可以看到一个示范项目</p>
<p>接下来修改配置文件</p>
<p>打开config.xml，可以看到示范例子的配置，把它都注释掉，不过其实我最后的配置也跟它差不多</p>
<p>直接贴我的配置吧，然后再来解释</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;xxx-xxx&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listeners<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;currentbuildstatuslistener</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;logs/${project.name}/status.txt&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listeners<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bootstrappers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;svnbootstrapper</span> <span style="color: #000066;">localWorkingCopy</span>=<span style="color: #ff0000;">&quot;D:/cc/${project.name}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bootstrappers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modificationset</span> <span style="color: #000066;">quietperiod</span>=<span style="color: #ff0000;">&quot;30&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;svn</span> <span style="color: #000066;">localWorkingCopy</span>=<span style="color: #ff0000;">&quot;D:/cc/${project.name}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modificationset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;schedule</span> <span style="color: #000066;">interval</span>=<span style="color: #ff0000;">&quot;300&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ant</span> <span style="color: #000066;">anthome</span>=<span style="color: #ff0000;">&quot;apache-ant-1.7.0&quot;</span> <span style="color: #000066;">buildfile</span>=<span style="color: #ff0000;">&quot;D:/cc/${project.name}/build.xml&quot;</span></span>
<span style="color: #009900;"><span style="color: #000066;">target</span>=<span style="color: #ff0000;">&quot;svnup test&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/schedule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;log<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;merge</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;D:/cc/${project.name}/target/testresult&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/log<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>首先是项目的名字，这个是必须的，中途可以用${project.name}来引用</p>
<p>listeners是监听事件，这里加了一个构建状态监听。CruiseControl默认把构建状态保存在logs/${project.name}/status.txt下，但是，这仅仅是成功or失败的状态，而没有具体的信息，加上这个配置的话，就能在首页看到是否成功的显示</p>
<p>bootstrappers和modificationset启动监听，其实我已经分不清他们两个的具体作用了（不好意思了，以后再翻一下补上），配置到你的项目目录中，我这里用了D:/cc/${project.name}。另外，你应该预先用svn checkout一份项目在这个位置，因为CruiseControl还要在该目录进行svn update的操作，所以这个目录的svn信息必须完整的，比如有.svn等文件，简单来说，也就是你可以在该目录成功运行“svn update”的命令</p>
<p>schedule里面放的是实际运行的script，很明显，我这里用了ant，调用了它的svnup和test两个target，为什么有个svnup的东西？呵呵待会说</p>
<p>最后是log，这个是用来合并ant输出日志的，如果你在CruiseControl的构建页面里面没有看到任何出错的详细信息，那就可能是没有合并日志，而ant脚本也必须配置成把相应的日志输出到设定的目录</p>
<p>基本的配置就是这样，这里还miss了一个ant的build.xml的内容，待会再介绍它，现在我先来说说CruiseControl的工作流程</p>
<p>CruiseControl通过内置的svn支持，定期检查localWorkingCopy目录的svn状态变化，然后触发构建script，但是，这里有一点必须主意的是，CruiseControl并没有svn update的功能，他仅仅是用内置的svn支持去检查你的目录是否有更新，但是具体的更新是由你来做，于是便有了很奇怪的ant svnup的target，待会你会看到它的内容</p>
<p>说实在话我觉得这种模式非常奇怪。而且如果检查的频率不够的话，svnup的时候，非常有可能update了好几个changeset下来，也就是说构建不是按照changeset分割的，仅仅是按照时间分割的</p>
<p>接下来就是build.xml的内容，我只列出跟CruiseControl相关的部分</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;test&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;testcompile&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;junit</span> <span style="color: #000066;">printsummary</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">fork</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			...
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;batchtest</span> <span style="color: #000066;">todir</span>=<span style="color: #ff0000;">&quot;target/testresult&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;target/test&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;**/*Test.*&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/batchtest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/junit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;svnup&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exec</span> <span style="color: #000066;">executable</span>=<span style="color: #ff0000;">&quot;svn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;up&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exec<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>这里需要主意的是<batchtest todir="target/testresult">，把测试结果输出到目录，然后在CruiseControl合并。另外一个当然是奇怪的svnup</p>
<p>这里有一个问题，如果你用海龟之类的svn client checkout项目，而你的机器上面没有装svn命令行的话，你可能不能使用我这个方法，需要有少少改动。其实就是用ant的svn支持来代替命令行的svn操作，具体可以研究ant的配置手册</p>
<p>基本就是这样了，重启你的CruiseControl，然后提交一些changge上svn，看看有没有结果输出吧</p>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2008/01/28/deploy-cruisecontrol/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

