Archive

Archive for the ‘Uncategorized’ Category

python在生产环境可选的memcached lib

May 15th, 2009 Sparkle 7 comments

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('load cmemcache')
    # although cmemcache might be thread safe
    # but we still make it thread local
    # also it can use separate socket connect in each thread for more performance
    from threading import local
except ImportError, e:
    logger.warn('cmemcache error: %s', e)
    import memcache
    import cmemcache_hash
    logger.warn('load python-memcache with cmemcache_hash')
    # python-memcache is already using thread local
    class local():
        pass
 
class Memcache(local):
    def __init__(self, servers):
        self._current = memcache.Client(servers)
    def current(self):
        return self._current
Categories: Uncategorized Tags: ,

python cmemcache是不是线程安全的

February 14th, 2009 Sparkle 6 comments

答案是,我不确定,但是我更倾向于认为它是线程不安全的

原因在于
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(local):
    def __init__(self, servers):
        self._current = memcache.Client(servers)
    def current(self):
        return self._current
Categories: Uncategorized Tags: ,

python-memcached是不是线程安全的

January 22nd, 2009 Sparkle No comments

答案是肯定的,前提你在使用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(object):
        pass
 
 
class Client(local):

很取巧的让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
http://lists.danga.com/pipermail/memcached/2007-June/004482.html

Categories: Uncategorized Tags: , ,

Mercurial和Git的主要区别

August 17th, 2008 Sparkle 6 comments

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的使用,只能作为类似备份的性质

Categories: Uncategorized Tags: ,

并发相关

March 26th, 2008 Sparkle 1 comment

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&锁。但是它也有缺点,就是不能保证数据绝对准确,例如他的size就是不准确的。但是它肯定是线程安全的

ReentrantLock是可以代替synchronized的东西,除了写起来比synchronized难稍稍。默认是non-fair模式,比synchronized快很多,如果改成fair就会下降到跟synchronized差不多

ReadWriteLock很简单,read不互斥,write互斥

CAS就是AtomicInteger之类的了,使用了CPU的交换指令,理论上比锁快,但是在高并发的环境一样会下降

你们还是看一下JDK源代码和JavaDoc好过了,你们的讨论本来就有答案的

Categories: Uncategorized Tags:

Mercurial续

March 19th, 2008 Sparkle 1 comment

上次谈到一些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基本使用

Categories: Uncategorized Tags:

给《程序员》写的MINA文章已经出刊了

February 26th, 2008 Sparkle 5 comments

第一次给杂志写文章,没什么经验,行文一般般,呵呵。不过也是能顺利出刊。

对文章有任何意见和建议,或者讨论MINA,可以在这里留言

迟点我再写一些MINA的心得

Categories: Uncategorized Tags:

架设你的CruiseControl

January 28th, 2008 Sparkle 7 comments

说实在话,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,可以看到示范例子的配置,把它都注释掉,不过其实我最后的配置也跟它差不多

直接贴我的配置吧,然后再来解释

<project name="xxx-xxx">
        <listeners>
            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
        </listeners>
        <bootstrappers>
            <svnbootstrapper localWorkingCopy="D:/cc/${project.name}" />
        </bootstrappers>
        <modificationset quietperiod="30">
		<svn localWorkingCopy="D:/cc/${project.name}"/>
        </modificationset>
        <schedule interval="300">
            <ant anthome="apache-ant-1.7.0" buildfile="D:/cc/${project.name}/build.xml"
target="svnup test" />
        </schedule>
        <log>
		<merge dir="D:/cc/${project.name}/target/testresult"/>
        </log>
</project>

首先是项目的名字,这个是必须的,中途可以用${project.name}来引用

listeners是监听事件,这里加了一个构建状态监听。CruiseControl默认把构建状态保存在logs/${project.name}/status.txt下,但是,这仅仅是成功or失败的状态,而没有具体的信息,加上这个配置的话,就能在首页看到是否成功的显示

bootstrappers和modificationset启动监听,其实我已经分不清他们两个的具体作用了(不好意思了,以后再翻一下补上),配置到你的项目目录中,我这里用了D:/cc/${project.name}。另外,你应该预先用svn checkout一份项目在这个位置,因为CruiseControl还要在该目录进行svn update的操作,所以这个目录的svn信息必须完整的,比如有.svn等文件,简单来说,也就是你可以在该目录成功运行“svn update”的命令

schedule里面放的是实际运行的script,很明显,我这里用了ant,调用了它的svnup和test两个target,为什么有个svnup的东西?呵呵待会说

最后是log,这个是用来合并ant输出日志的,如果你在CruiseControl的构建页面里面没有看到任何出错的详细信息,那就可能是没有合并日志,而ant脚本也必须配置成把相应的日志输出到设定的目录

基本的配置就是这样,这里还miss了一个ant的build.xml的内容,待会再介绍它,现在我先来说说CruiseControl的工作流程

CruiseControl通过内置的svn支持,定期检查localWorkingCopy目录的svn状态变化,然后触发构建script,但是,这里有一点必须主意的是,CruiseControl并没有svn update的功能,他仅仅是用内置的svn支持去检查你的目录是否有更新,但是具体的更新是由你来做,于是便有了很奇怪的ant svnup的target,待会你会看到它的内容

说实在话我觉得这种模式非常奇怪。而且如果检查的频率不够的话,svnup的时候,非常有可能update了好几个changeset下来,也就是说构建不是按照changeset分割的,仅仅是按照时间分割的

接下来就是build.xml的内容,我只列出跟CruiseControl相关的部分

<target name="test" depends="testcompile">
	<junit printsummary="true" fork="true">
		<classpath>
			...
		</classpath>
		<batchtest todir="target/testresult">
			<fileset dir="target/test">
				<include name="**/*Test.*" />
			</fileset>
		</batchtest>
	</junit>
</target>
<target name="svnup">
	<exec executable="svn">
		<arg line="up" />
	</exec>
</target>

这里需要主意的是,把测试结果输出到目录,然后在CruiseControl合并。另外一个当然是奇怪的svnup

这里有一个问题,如果你用海龟之类的svn client checkout项目,而你的机器上面没有装svn命令行的话,你可能不能使用我这个方法,需要有少少改动。其实就是用ant的svn支持来代替命令行的svn操作,具体可以研究ant的配置手册

基本就是这样了,重启你的CruiseControl,然后提交一些changge上svn,看看有没有结果输出吧

Categories: Uncategorized Tags:

优化你的Eclipse VM参数

January 26th, 2008 Sparkle No comments

最近dzone在讨论eclipse的VM参数
引用了一篇2004年的帖子

Here are the best options that I’ve found so far for my 2-processor Windows machine running JDK5.0 and Eclipse3.1:

-vmargs -XX:+UseParallelGC

2004年就用两个CPU都颇奢侈了吧

我现在的机器是双核+2G内存,于是我修改了一下eclipse的VM参数

打开eclipse.ini

修改或加入如下内容

-vmargs
-Xmx512m
-XX:+UseParallelGC

Categories: Uncategorized Tags:

我与Mercurial

January 25th, 2008 Sparkle 4 comments

最初知道 Mercurial这个工具其实是因为去年6月份看了cyfdecyf的一篇blog分布式版本管理工具:git & mercurial(作者搬迁了blog,新地址是这里).然后断断续续有在使用,一直想把一些经验写出来.最近刚好遇到云风在研究分布式版本管理,还是动手把一些经验写下来吧

一直一来都是用CVS,然后是SVN来做版本管理,最初认识分布式版本管理,是一个叫SVK的工具,是一个台湾人的作品,本身基于SVN,令到SVN可以分布式工作.当时觉得安装非常麻烦就没有研究下去了,而且本身对这样的功能需求也不大.后来Linus因为不满现有版本管理软件的问题,自己花了两个星期写了一个分布式版本管理Git,现在Linux kernel等源代码已经完全工作在Git的管理之上了.但是Git本身非常晦涩难懂,而且只能在Linux下运行,我本身也主要用Windows来工作,因此也没有深入研究.

直至看到 cyfdecyf的文章,这篇文章有坚定我研究分布式版本管理的信心.集中式版本管理的缺陷, cyfdecyf和云风都有描述了一些例子,我认为那些例子都很典型.如果所有开发人员都在一个房间里面,集中式版本管理是最好的,最明显的例子就是公司的开发,大家都能直接访问到服务器,网络不会中断.这种情况下,使用分布式版本管理反而增加了复杂性.但是,如果开发人员不是在同一个房间,甚至在不同的国家.当然你也可以在Internet上假设一个SVN服务器.但是,开发人员不一定有网络,或者网络不一定很好.而每次提交,或者同步,都要花上好几分钟或者更长时间,这非常影响开发.又或者你只是私人的项目,而你有没有能力假设公开的SVN服务器.而且我只是一个人,为什么每次都要提交到外边的服务器.当然也可以在自己的机器上面架设一个SVN,但是如果你有两台以上的机器就会觉得很麻烦了.

所有的这些场景,其实你需要一个分布式版本管理.cyfdecyf的文章最后在选择Git的代替品,定了用Mercurial.那我也从Mercurial开始吧.不过Mercurial的中文资料非常少,我始终不理解分布式版本管理的原理.最后,非常搞笑的情况是,我其实是看了Git的一份中文资料才真正明白的,也推荐大家从Git的中文资料入手.

待续…

Categories: Uncategorized Tags: