如何部署高可用性和高可伸缩性的网站?这是一个很复杂的问题,到目前为止,我还没有实际的经验,都是自己学习和思考得到的一点结果。
前段时间,长沙一个公司做了一个彩票投注的网站,上海那边的公司就想直接拿过去用,不想再重新开发一套系统。问题是开发人员多数都有一个毛病,认为别人做的不如自己做的,上海就有这样一个,他说给我一个月时间,我就可以做出比这个更好的网站。除去有关业务有关市场的东西不谈,这位兄弟说的话的确很难让人相信,业务人员不信,我觉得他更是没弄明白部署一个生产的网站所包含的工作,显然,他认为,部署一个网站就是写完代码,然后copy到服务器上就可以了。 事情比他想象的复杂的多,如果这个网站是一个intranet的应用,可能还好说些,但是这是一个面向彩民的网站,实现一年销售2亿的网站,在部署这样一个网站的时候,可用性和伸缩性是不能不考虑的问题。在最终得到的生产环境中,网站代码可能只是很小的一部分, 你需要集群,需要cache,需要分部文件系统dfs,需要负载均衡,需要数据库集群,以及配套的一对硬件,要把这些理清楚,如果只懂java,jsp是远远不够的。
我没有实际参与部署过这种为海量用户服务的网站,心里很忐忑,一旦我们运营的网站出现这样那样 的问题怎么办? 所幸找到了一个很好的案例,这个案例不仅仅是从软件设计上说如何支持可伸缩性,而是完整的介绍了整个网站的部署,它就是livejournal,一个很早开始blog服务的网站,这是一个有8百多万用户,每秒处理2000次点击的网站。
开发livejournal的这群人值得称赞,他们分享了网站开发和部署过程中的很多心得,并且开源了他们自己开发的很多支持网站运营的工具,其中最著名的大概就应该是memcache了,这个cache系统已经在很多大型网站得到了应用,可以从这里下载他们的一个演示文档。下面按照整个部署涉及到的环节说说我的体会。
1.perlbal
一个livejournal自己开发的reverse proxy,用来进行负载均衡(big-ip好象也是用来做负载均衡,但是没搞清楚和perlbal的关系)
2. mogilefs
一个livejournal自己开发的分布式文件系统(DFS, distributed file system),分布式文件系统又包括一些不同的类型,主要是看他们解决的问题,有的用来支持高并发任务,有的使用来支持高可用性,而mofilefs是同时支持高并发和高可用性两个特性,而且支持任何本地文件系统。 问题是为什么我们要用分布式文件系统??它应该是用来处理系统产生的数据文件,最直观的大概就是系统生成的日志了,在集群环境下,如果没有dfs,那么每台主机都会产生单独的分离的日志文件,如果采用dfs,那么所有集群中的应用可以向同一个文件输出日志,而且便于维护。(老实说,这个我没有弄太清楚)
dfs与raid的关系也需要提一下,一般来说raid只是硬盘的阵列,如果部署raid的主机崩溃,那么raid也没用了,除非是有san(store area networ)支持的raid,可以跨主机。 而dfs由于本身是分布式的,是跨主机的,不存在这个问题。
3. web server cluster
这个集群是基本的,相信了解集群的人都应该知道web server的集群是最基本的
4. memcache
一个livejournal开发的分布式缓存系统,目前的应用非常广泛,可以在多台主机启动多个memcache服务,它们会自动协作,对应用程序来说就好象只有一个memcache服务。可以存储任何形式的内容(需要做深入研究)
但是对什么内容进行缓存呢?
首先要是被经常读取的内容,而这些内容可以通过查看数据库的日志,比如那些对象查询的最多等等。mysql提供了slow log的功能。
5. mysql cluster
数据库集群这块是对我影响最大的。以前一直认为是要采用大型数据库的本身支持的集群(想来应该非常昂贵),不然是实在想不出还有什么集群方式,而且既然有数据库集群,那么前面是不是也要有一个load balancer? 不过这个load balancer应该是数据库服务器本身提供,就相当于有一个逻辑数据库,应用程序面向的是这个逻辑数据库,不需要知道后端的集群有多少数据库实例,这个逻辑数据库负责组装数据,分布请求,负载均衡。。。不过,这的确应该是一个昂贵的解决方案。
后来,了解了sharding,是一种数据库分区的概念,包含水平和垂直两种shard方式(集群也包括水平和垂直两种,垂直的就是单个应用,但是起先是运行在普通的web server中,后来是运行在小型机中,而水平集群就是采用便宜的web server阵列,每个主机都部署一个应用),水平就是将一个表的列进行拆分,可能数据量大的,或者不经常使用的列拆分到一个独立的表; 垂直就是按照一个规则将表中的数据进行分区,避免一个表中的数据过大,常见的是用户表(user),比如规则是按照id的奇偶来决定将user存入哪个表,那么可能在数据库中就存在usre_odd, user_even两个表,它们的表模式一模一样,但是一个用来保存id为奇数的用户,一个用来保存id为偶数的用户。shard需要进行额外的编码,但是会带来巨大的性能提升。
一般来说采用sharding就可以不用昂贵的数据库集群方案,而且后来想到的一个问题是,数据库服务器一般会采用raid,raid本身就提供了高速的io,以及数据冗余,所以我更加倾向与raid+sharding的方案了。
当时livejournal的方案显然更复杂,除了sharding之外,mysql也做了集群,并且每个用户组都有一个数据库集群,想来只有存在海量用户的系统需要这样,实在很壮观阿。 但是从它讨论的master-salve这种数据库集群方式中,我又想通了不少问题,所以在我原来raid+sharding的方案上,我又增加一个slave,也做一个数据库集群,但是slave不一定需要raid,看具体的应用,我是想在进行统计报表的时候就可以使用slave的数据,而不需要访问master,master处理在线数据,提供实时服务,嘿嘿。。。。如果slave也需要处理在线作业,那么也可以在slave上配置raid, 当然也可以象livejournal一样,master提供读写,而slave只提供读。
数据库这库学问太深,还有很多其他的方面,我也只想了这么多,想到哪里写到哪里。。。
参考资料:
Django Master Class: http://toys.jacobian.org/presentations/2007/oscon/tutorial/
Database sharding unraveled: http://lifescaler.com/2008/04/database-sharding-unraveled-part-i/
Scalability Best Practices: Lessons from eBay: http://www.infoq.com/articles/ebay-scalability-best-practices
Scaling Your Java EE Applications: http://www.theserverside.com/tt/articles/article.tss?l=ScalingYourJavaEEApplications
Friday, August 29, 2008
Wednesday, July 09, 2008
什么是好的构建工具?
从我开始接触到linux的时候,我就知道一个叫做makefile的东西,不过从来不敢改,不敢动,因为对linux不熟悉,对c语言不熟悉。后来据说因为makefile对平台依赖性太强,又除了一个autoconfig,那些都是linux+c的东西。
再到后来就是ant了,很多项目中也都采用了ant,非常灵活,可以说只有想不到没有做不到。但是也的确存在一个问题,在大型项目中,维护ant的构建脚本本身也会变成一个沉重的负担,需要有专门的人来负责。我曾经在一个erp公司做过,其中包含很多子项目,ant脚本到处都是,而且彼此引用,光是看那些脚本,就看到的我目瞪口呆:ant这么强大,ant这么复杂。
没有在具体的项目中应用过maven,只是想要看看为什么有了ant,人们还需要maven。 ant和maven在某种意义上是两个完全相反的东西,你可以随心所以的使用ant,编写各种插件,脚本,让它来适应你的习惯,你的哲学,但是maven,如果你想要舒服的使用maven,最好就是适应它的哲学,适应它的习惯,不然,可能不是那么好驾驭。 maven一个很重要的哲学就是‘惯例比配置更重要’,我很赞同,使用惯例我们可以减少大量的配置文件,也就减少大量的脚本,减少维护的工作。 此外,maven标准化了项目的构建工作,的确,几乎所有的项目都包含这样一个构建流程:编译,测试,打包,部署。 在ant中,每个项目都需要从头开始(其实不一定,我在使用ant的时候就借鉴了interface的思想,定义了一些标准的target,保证所有的项目这些都有同样的ant target,完成同样的任务,虽然实现可以不一样。。。。毕竟,这不是工具本身支持的,需要人们手工来做,需要相关人员的理解,共识)。
对maven还不是太熟悉,但是觉得不如ant那么容易上手,pom的结构太复杂,也有可能导致一大堆xml配置文件。 maven有一个完美的思想和比较蹩脚的实现,maven1出来的时候大受好评,但是等到maven2,人们开始越来越多的抱怨它。 mavne的依赖管理是先对于ant最出色的特性(现在ant可以和ivy接合来实现包的依赖管理),但是现在看来人们正是对这块不满意,不是说包依赖管理不好,而是这个功能实现的不好,经常会导致构建的失败。人们可能莫名其妙的发现,上一次好好好的成功的构建,在没有人们变动的情况下,怎么现在就构建失败了,其实很可能是包仓库中某个依赖变化了,而修正这个问题据说是一场噩梦。
maven是比ant更高级的构建工具,虽然有那么多问题,但是目前来看,maven还是首选,至少最流行的spring项目就是采用maven构建的。
此外,有一个ruby开发的java项目构建工具,名字叫buildr,也成为了apache的incubutor项目,但是对于很多java开发人员来讲,部署一个ruby应用可能不是那么简单,其他远不如copy一份ant或者maven那么简单。
再到后来就是ant了,很多项目中也都采用了ant,非常灵活,可以说只有想不到没有做不到。但是也的确存在一个问题,在大型项目中,维护ant的构建脚本本身也会变成一个沉重的负担,需要有专门的人来负责。我曾经在一个erp公司做过,其中包含很多子项目,ant脚本到处都是,而且彼此引用,光是看那些脚本,就看到的我目瞪口呆:ant这么强大,ant这么复杂。
没有在具体的项目中应用过maven,只是想要看看为什么有了ant,人们还需要maven。 ant和maven在某种意义上是两个完全相反的东西,你可以随心所以的使用ant,编写各种插件,脚本,让它来适应你的习惯,你的哲学,但是maven,如果你想要舒服的使用maven,最好就是适应它的哲学,适应它的习惯,不然,可能不是那么好驾驭。 maven一个很重要的哲学就是‘惯例比配置更重要’,我很赞同,使用惯例我们可以减少大量的配置文件,也就减少大量的脚本,减少维护的工作。 此外,maven标准化了项目的构建工作,的确,几乎所有的项目都包含这样一个构建流程:编译,测试,打包,部署。 在ant中,每个项目都需要从头开始(其实不一定,我在使用ant的时候就借鉴了interface的思想,定义了一些标准的target,保证所有的项目这些都有同样的ant target,完成同样的任务,虽然实现可以不一样。。。。毕竟,这不是工具本身支持的,需要人们手工来做,需要相关人员的理解,共识)。
对maven还不是太熟悉,但是觉得不如ant那么容易上手,pom的结构太复杂,也有可能导致一大堆xml配置文件。 maven有一个完美的思想和比较蹩脚的实现,maven1出来的时候大受好评,但是等到maven2,人们开始越来越多的抱怨它。 mavne的依赖管理是先对于ant最出色的特性(现在ant可以和ivy接合来实现包的依赖管理),但是现在看来人们正是对这块不满意,不是说包依赖管理不好,而是这个功能实现的不好,经常会导致构建的失败。人们可能莫名其妙的发现,上一次好好好的成功的构建,在没有人们变动的情况下,怎么现在就构建失败了,其实很可能是包仓库中某个依赖变化了,而修正这个问题据说是一场噩梦。
maven是比ant更高级的构建工具,虽然有那么多问题,但是目前来看,maven还是首选,至少最流行的spring项目就是采用maven构建的。
此外,有一个ruby开发的java项目构建工具,名字叫buildr,也成为了apache的incubutor项目,但是对于很多java开发人员来讲,部署一个ruby应用可能不是那么简单,其他远不如copy一份ant或者maven那么简单。
使用diff和patch来制作补丁
首先说明使用diff和patch一般使用来处理文本文件的,对于开源项目,这两个工具是很好的帮手,比如linux的内核发布就包含很多patch,这样你不用每次都下载完整的源代码包,只需要下载目标版本和你已有版本之间的patch。
我会通过一个实际的操作示例来说明这两个工具的使用。有一个项目,名字叫testproject,已经发布了两个版本,2.2.0和2.2.1,其中上海生产环境部署了2.2.0,深圳开发中心已经发布了新版的2.2.1,现在生产环境需要升级到2.2.1,因为新版本修复了重要的bug。 方法有很多种,这里我们说明使用diff和patch的方式。
* 首先在当前工作目录下(假设为/home/jack/),从subversion上export两个版本。
> svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode 2.2.0
>svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode 2.2.1
* 执行diff
>diff -Nur 2.2.0 2.2.1 >220-221.patch
上面的命令会生成一个patch文件,其中-N表示如果目标目录不包含源目录中的文件,那么认为目标目录存在一个内容为空的同名文件。 -u表示生成统一的有上下文的patch文件(后面再说patch格式)。 -r表示递归处理,在处理目录的时候需要这个参数。
* 接下来,我们开始使用patch
>cp 220_221.patch 2.2.0
>cd 2.2.0
>patch -p1<220_221.patch>rm 220_221.patch
>cd ..
>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到这次得到的220-221_new.patch是空文件,这就说明现在2.2.0的源代码已经被升级到2.2.1了。
* 好了,现在我们可以将这个patch文件从深圳发到上海,然后上海更新源代码,再次编译,测试,打包,部署....
===========================
subverion的diff
===========================
接下来我要试试patch能不能处理subversion的diff得到的patch文件。
* 生成subversion的diff文件,在当前工作目录下(假设为/home/jack/).
> svn diff http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode > diff.patch
>cp diff.patch 2.2.0
>patch -p0rm diff.patch
>cd ..
>>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到,220-221_new.patch文件为空,说明2.2.0已经升级到2.2.1了。
这里使用diff命令和使用‘svn diff’得到的patch文件格式有点不一样,使用diff得到的为:
diff -Nur 2.2.0/build.properties 2.2.1/build.properties
--- 2.2.0/build.properties 2008-04-30 15:09:14.000000000 +0800
+++ 2.2.1/build.properties 2008-06-27 15:39:36.000000000 +0800
@@ -8,7 +8,7 @@
#--------------------------------------------#
project.name=CentralPool
#DO NOT modify below setting.
-app.version=2.2.0
+app.version=2.2.1
app.vendor=Shenzhen Helper Science & Technology Co., Ltd.
builder.name=${project.name} Team
diff -Nur 2.2.0/CHANGELOG.txt 2.2.1/CHANGELOG.txt
--- 2.2.0/CHANGELOG.txt 2008-04-08 17:02:58.000000000 +0800
+++ 2.2.1/CHANGELOG.txt 2008-06-27 15:39:36.000000000 +0800
@@ -1,16 +1,16 @@
-CENTRALPOOL PROJECT CHANGELOG
+CENTRALPOOL PROJECT CHANGELOG
--------------------------------------
ChangeLog定义了当前版本相对于上一个版本之间系统发生的变更. 这些变更包括修正的bug, 系统新增的
功能,或者系统添加的补丁等等.
而使用‘svn diff’得到的patch文件为:
Index: sub-core/src/com/hengpeng/ante/game/GameFactory.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.1/sourcecode) (revision 241)
@@ -51,6 +51,9 @@
case Game.GAME_TYPE_SSC:
return new SSCGame(gameData);
+
+ case Game.GAME_TYPE_NUMLOTTO:
+ return new NumLottoGame(gameData);
default:
throw new HPException(AnteException.ErroCode_NoGame,
Index: sub-core/src/com/hengpeng/ante/game/Game.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.1/sourcecode) (revision 241)
@@ -75,7 +75,13 @@
*/
public static final int GAME_TYPE_SSC = 9;
+ /**
+ * 东方6+1玩法 {@value}
+ * @value 9
+ */
+ public static final int GAME_TYPE_NUMLOTTO = 10;
+
// GAME DEFINITION
public static final int GAME336 = 11;
public static final int GAME155 = 23;
幸运的是patch命令都可以处理,实际上两种都是正确的格式。
diff和patch在linux操作系统中是自带的,但是进入windows环境就没有那么容易了。不过好在有一个gunwin32的开源项目(gunwin32.sourceforge.net),gnu下的diff和patch都可以运行在window上了。
我会通过一个实际的操作示例来说明这两个工具的使用。有一个项目,名字叫testproject,已经发布了两个版本,2.2.0和2.2.1,其中上海生产环境部署了2.2.0,深圳开发中心已经发布了新版的2.2.1,现在生产环境需要升级到2.2.1,因为新版本修复了重要的bug。 方法有很多种,这里我们说明使用diff和patch的方式。
* 首先在当前工作目录下(假设为/home/jack/),从subversion上export两个版本。
> svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode 2.2.0
>svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode 2.2.1
* 执行diff
>diff -Nur 2.2.0 2.2.1 >220-221.patch
上面的命令会生成一个patch文件,其中-N表示如果目标目录不包含源目录中的文件,那么认为目标目录存在一个内容为空的同名文件。 -u表示生成统一的有上下文的patch文件(后面再说patch格式)。 -r表示递归处理,在处理目录的时候需要这个参数。
* 接下来,我们开始使用patch
>cp 220_221.patch 2.2.0
>cd 2.2.0
>patch -p1<220_221.patch>rm 220_221.patch
>cd ..
>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到这次得到的220-221_new.patch是空文件,这就说明现在2.2.0的源代码已经被升级到2.2.1了。
* 好了,现在我们可以将这个patch文件从深圳发到上海,然后上海更新源代码,再次编译,测试,打包,部署....
===========================
subverion的diff
===========================
接下来我要试试patch能不能处理subversion的diff得到的patch文件。
* 生成subversion的diff文件,在当前工作目录下(假设为/home/jack/).
> svn diff http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode > diff.patch
>cp diff.patch 2.2.0
>patch -p0
>cd ..
>>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到,220-221_new.patch文件为空,说明2.2.0已经升级到2.2.1了。
这里使用diff命令和使用‘svn diff’得到的patch文件格式有点不一样,使用diff得到的为:
diff -Nur 2.2.0/build.properties 2.2.1/build.properties
--- 2.2.0/build.properties 2008-04-30 15:09:14.000000000 +0800
+++ 2.2.1/build.properties 2008-06-27 15:39:36.000000000 +0800
@@ -8,7 +8,7 @@
#--------------------------------------------#
project.name=CentralPool
#DO NOT modify below setting.
-app.version=2.2.0
+app.version=2.2.1
app.vendor=Shenzhen Helper Science & Technology Co., Ltd.
builder.name=${project.name} Team
diff -Nur 2.2.0/CHANGELOG.txt 2.2.1/CHANGELOG.txt
--- 2.2.0/CHANGELOG.txt 2008-04-08 17:02:58.000000000 +0800
+++ 2.2.1/CHANGELOG.txt 2008-06-27 15:39:36.000000000 +0800
@@ -1,16 +1,16 @@
-CENTRALPOOL PROJECT CHANGELOG
+CENTRALPOOL PROJECT CHANGELOG
--------------------------------------
ChangeLog定义了当前版本相对于上一个版本之间系统发生的变更. 这些变更包括修正的bug, 系统新增的
功能,或者系统添加的补丁等等.
而使用‘svn diff’得到的patch文件为:
Index: sub-core/src/com/hengpeng/ante/game/GameFactory.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.1/sourcecode) (revision 241)
@@ -51,6 +51,9 @@
case Game.GAME_TYPE_SSC:
return new SSCGame(gameData);
+
+ case Game.GAME_TYPE_NUMLOTTO:
+ return new NumLottoGame(gameData);
default:
throw new HPException(AnteException.ErroCode_NoGame,
Index: sub-core/src/com/hengpeng/ante/game/Game.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.1/sourcecode) (revision 241)
@@ -75,7 +75,13 @@
*/
public static final int GAME_TYPE_SSC = 9;
+ /**
+ * 东方6+1玩法 {@value}
+ * @value 9
+ */
+ public static final int GAME_TYPE_NUMLOTTO = 10;
+
// GAME DEFINITION
public static final int GAME336 = 11;
public static final int GAME155 = 23;

diff和patch在linux操作系统中是自带的,但是进入windows环境就没有那么容易了。不过好在有一个gunwin32的开源项目(gunwin32.sourceforge.net),gnu下的diff和patch都可以运行在window上了。
Thursday, June 19, 2008
RedHat Ubuntu python Mysql MySQLdb mantis+subversion
这几天搞subversion+mantis整合的事情,折腾的一天,目前貌似前进了一步,至少可能遇到的问题应该都被解决了。 将版本控制系统和缺陷管理系统整合起来是一件很值得的事情,通过整合,可以将需求和最终的实现形成一条可追踪的线, 而不是一些离散的软件开发活动。 我们可以分析用例,进行概要设计,并且将软件实现分解成较少工作量的任务,这些东西可以通过在缺陷管理系统中file一个总体的bug,说明要实现的是什么东西,然后每个分解的任务file一个bug,这些bug依赖于那个描述总体的bug。这种方式扩展了缺陷管理系统的概念,应该把它叫做制品管理系统,因为在这个系统中不再只有bug这一个概念,还包括了feature,enhancement,task等。 :(,觉得表达的有些混乱。
下面说说整个整合的过程。
一开始从网上找了文档,有专门说subversion和mantis怎么整合的,看了看,觉得大概没问题,因为我以前也在linux下配过不少东西,mysql, bugzilla,subversion,apache等,所以想事情应该不会太困难。
事实是实际的开发环境和文档中讲的不一样,几乎所有的文档中说的都是mantis和subversion都运行在linux上,这样subversion可以通过ssh来无交互地直接执行mantis机器上的命令。问题是,我们的mantis是跑在window上的。 妈妈的,我尝试在window上装了个windosshd,然后从linux下可以通过密码的方式访问mantis的机器,但是rsa(不需要输入密码)就怎么也不行,openssh本身不太懂。实在搞不定,后来想就直接在subversion的机器上用python来访问mantis的mysql数据库得了,这也行的通,何况我最近一直学习python,正好小试牛刀。
python访问mysql需要MySQLdb的库,我需要在subversion那台机器上安装这个库。 因为我一直用ubuntu,所以直接‘sudo apt-get install mysql-server', 居然提示我没有这个命令,有点昏。后来一查,subversion的机器是redhat enterprise linux4.4的,只好去MySQLdb的网站下载targz的包。 这个包是需要编译的,但是编译过程中总是提示找不到mysql头文件(mysql_config.h),这样看来我需要安装mysql了。
跑到mysql的网站上下载了redhat enterprise linux4的mysql4.1.22的rpm包,结果安装这个包的过程中总是提示文件冲突,烦死了,而且rpm包里面并没有要求的mysql_config.h文件。在后来我就下载了一个mysql的linux下的通用包,48M,这次好了,这个包里面是完整的mysql-server的目录,哈哈,看来要爽一回。
进入MySQLdb的安装目录,需要修改site.cfg文件,设定mysql_config到下载的这个mysql-server目录,即$mysql_server_home/bin, 这次执行python setup.py build就成功了。
mysql_config 是mysql的一个工具,可以查看mysql的很多编译安装信息,所以很多需要mysql头文件来编译的项目都会使用这个工具。在ubuntu下,这个工具要单独安装。
在控制台执行命令:
$python
>>> import MySQLdb
没有报错,安装成功,接下来就是写python代码了
--------------------------------
现在又碰到了中文编码的问题,由于svn提交的时候指定中文消息,这些消息被mantis显示出来的时候全是乱码。后来总算找到办法了,原来需要进行'中文'.decode('utf-8').encode('gbk'),但是subversion那台机器上的python是2.3的,没有中文解码包,需要安装python-cjkcodecs。 python2.4就自带这个包了。妈的!
下面说说整个整合的过程。
一开始从网上找了文档,有专门说subversion和mantis怎么整合的,看了看,觉得大概没问题,因为我以前也在linux下配过不少东西,mysql, bugzilla,subversion,apache等,所以想事情应该不会太困难。
事实是实际的开发环境和文档中讲的不一样,几乎所有的文档中说的都是mantis和subversion都运行在linux上,这样subversion可以通过ssh来无交互地直接执行mantis机器上的命令。问题是,我们的mantis是跑在window上的。 妈妈的,我尝试在window上装了个windosshd,然后从linux下可以通过密码的方式访问mantis的机器,但是rsa(不需要输入密码)就怎么也不行,openssh本身不太懂。实在搞不定,后来想就直接在subversion的机器上用python来访问mantis的mysql数据库得了,这也行的通,何况我最近一直学习python,正好小试牛刀。
python访问mysql需要MySQLdb的库,我需要在subversion那台机器上安装这个库。 因为我一直用ubuntu,所以直接‘sudo apt-get install mysql-server', 居然提示我没有这个命令,有点昏。后来一查,subversion的机器是redhat enterprise linux4.4的,只好去MySQLdb的网站下载targz的包。 这个包是需要编译的,但是编译过程中总是提示找不到mysql头文件(mysql_config.h),这样看来我需要安装mysql了。
跑到mysql的网站上下载了redhat enterprise linux4的mysql4.1.22的rpm包,结果安装这个包的过程中总是提示文件冲突,烦死了,而且rpm包里面并没有要求的mysql_config.h文件。在后来我就下载了一个mysql的linux下的通用包,48M,这次好了,这个包里面是完整的mysql-server的目录,哈哈,看来要爽一回。
进入MySQLdb的安装目录,需要修改site.cfg文件,设定mysql_config到下载的这个mysql-server目录,即$mysql_server_home/bin, 这次执行python setup.py build就成功了。
mysql_config 是mysql的一个工具,可以查看mysql的很多编译安装信息,所以很多需要mysql头文件来编译的项目都会使用这个工具。在ubuntu下,这个工具要单独安装。
在控制台执行命令:
$python
>>> import MySQLdb
没有报错,安装成功,接下来就是写python代码了
--------------------------------
现在又碰到了中文编码的问题,由于svn提交的时候指定中文消息,这些消息被mantis显示出来的时候全是乱码。后来总算找到办法了,原来需要进行'中文'.decode('utf-8').encode('gbk'),但是subversion那台机器上的python是2.3的,没有中文解码包,需要安装python-cjkcodecs。 python2.4就自带这个包了。妈的!
Thursday, May 22, 2008
MoinMoin......
这些天在做一个Research,就是接下来的一个项目的技术选型,最终这些东西都汇总到一个openoffice的文档中。但是我越来越不喜欢这种写文档的方式,首先这些office的文档都是二进制的,对搜索引擎不友好,更重要的是,我觉得写文档和软件开发一定程度上是由共性的,就是说是一个迭代和增量的过程,需要不断的反馈,需要集体的协作。我想要的写文档的方式应该是多个人一起完成初稿,然后所有的相关人员都可以来浏览,来编辑,来提意见,就是wikipedia的方式,当然一个专职的文档维护人员(或者一个维护委员会)是必须的,由他来最终确定哪些修改是好的,哪些意见是应该被抛弃的。最后,文档应该是公开的,易于查看,相关文档应该彼此链接,不应该藏在svn的某个深深的角落。
WikiWiki可以解决这个问题,我觉得可以一个主要编写人员首先列出提纲,然后每个部分都有专业的人员来编写,而这个文档随时任何相关人员都可以查看,可以提意见,最终依靠集体的力量完成文档。传统的方式都是一个人完成文档,然后组织大家一起来讨论,然后继续修改,继续讨论。这种方式的效率不高,这要求审核人员必须在特定的时间段里去阅读文档,进行讨论,而审核人员到底付出多大的精力去阅读这篇文档很重要。就目前的经历来看,审核人员通常都不会在这件事情上花多少力气,所以审核的质量非常低。通过wiki的方式,大家可以更深刻的参与到文档的编写工作中来,每个人都随时可以查看文档的进度,可以添加注释,可以直接修改。
下面就说说wiki系统的安装,因为我决心要学习python,所以专门找了一个python的wiki系统,MoinMoin,很多大型网站都采用了这个wiki系统,尤其开源网站,它们更有动力采用wiki来促进社区的交流。
操作系统:Ubuntu 7.10 Desktop, linux kernel 2.6.22-14-generic
Python : 2.5.1
WebServer: lighttpd 1.4.18 (ssl)
MoinMoin: 1.6.3
::安装过程可以查看MoinMoin发布包中自带的Install.html
1. 确认python和lighttpd都已经安装成功。 一般来说ubuntu系统已经自带了python,而安装lighttpd也非常简单,执行'sudo apt-get install lighttpd'就可以了。
>>>python setup.py install --prefix='/usr/local' --record=install.log
其中, --prefix表示安装目标目录,如果不指定,那么会安装到默认目录,通常是/usr/lib/python2.5/site-pakcage/moin和/usr/share/moin; --record表示安装日志,可以从中看出哪些文件被copy到哪个目录了。
NOTE:更多信息可以参考moinmoin的install.html
3. ....关于moin的配置请参考moinmon的install.html
4. 配置FasgCGI。如果CGI方式,那么每个请求相应的cgi文件都会被重新load,这样会极大的影响的性能, 而FastCGI方式只需要在第一次请求的时候load脚本,然后这些脚本就会被缓存下来,这样可以大大提高性能,此外,FasgCGI是一个单独运行的网关进程,就算webserver崩溃也不会影响到它。在多核的环境下,FastCGI是个不错的选择。mod_python是运行在webserver中的一个线程,在超线程的环境下可能表现更好。lighttpd不支持mod_python。
lighttpd是一个高性能的,轻型的(相较与apache),高度模块化的webserver,它需要在配置文件lighttpd.conf中指定装载fcgi模块,并且配置fcgi相应的参数。
note: 可以参考install.html中的'deploying in lighttpd'
5.这里反过来再提一下MoinMoin的配置。我的MoinMoin是安装到默认目录,即/usr/lib/python2.5/site-package/moin和/usr/share/moin,前面一个目录放置的是moinmoin的python源代码, /usr/share/moin放置的是模板代码(html,img,css等)和数据文件(保存用户数据,比如page, comments,user等)。然后我又把/usr/share/moin中的data, underlay,wikiconfig.py, moin.fcg复制到/opt/mylib/moin目录,这个目录叫做MoinMoin的一个实例。就是说你可以同时运行多个实例,它们分别有自己的名称空间,彼此不会影响,但是共用htdocs。
此外,需要注意的是权限问题,由于lighttpd是以www-data的用户运行,而fastcgi程也是它启动的,即fastcgi server也是以www-data的用户运行的,那么www-data必须具有/opt/mylib/moin目录读写执行权限。 总之要注意权限问题。但是如果fastcgi是通过手动单独在外面启动的,那么启动这个进程的用户必须具有读写执行/opt/mylib/moin的权限,这样的话,它是独立与lighttpd的权限系统之外的,可以另外设置权限规则。
WikiWiki可以解决这个问题,我觉得可以一个主要编写人员首先列出提纲,然后每个部分都有专业的人员来编写,而这个文档随时任何相关人员都可以查看,可以提意见,最终依靠集体的力量完成文档。传统的方式都是一个人完成文档,然后组织大家一起来讨论,然后继续修改,继续讨论。这种方式的效率不高,这要求审核人员必须在特定的时间段里去阅读文档,进行讨论,而审核人员到底付出多大的精力去阅读这篇文档很重要。就目前的经历来看,审核人员通常都不会在这件事情上花多少力气,所以审核的质量非常低。通过wiki的方式,大家可以更深刻的参与到文档的编写工作中来,每个人都随时可以查看文档的进度,可以添加注释,可以直接修改。
下面就说说wiki系统的安装,因为我决心要学习python,所以专门找了一个python的wiki系统,MoinMoin,很多大型网站都采用了这个wiki系统,尤其开源网站,它们更有动力采用wiki来促进社区的交流。
操作系统:Ubuntu 7.10 Desktop, linux kernel 2.6.22-14-generic
Python : 2.5.1
WebServer: lighttpd 1.4.18 (ssl)
MoinMoin: 1.6.3
::安装过程可以查看MoinMoin发布包中自带的Install.html
1. 确认python和lighttpd都已经安装成功。 一般来说ubuntu系统已经自带了python,而安装lighttpd也非常简单,执行'sudo apt-get install lighttpd'就可以了。
- 在控制台执行'python', 出现python提示符'>>>'就表示python已经安装成功了。
- 执行'lighttpd -D -f /etc/lighttpd/lighttpd.conf', 然后在浏览器中访问'http://localhost',看到html页面就表示lighttpd安装成功了。
>>>python setup.py install --prefix='/usr/local' --record=install.log
其中, --prefix表示安装目标目录,如果不指定,那么会安装到默认目录,通常是/usr/lib/python2.5/site-pakcage/moin和/usr/share/moin; --record表示安装日志,可以从中看出哪些文件被copy到哪个目录了。
NOTE:更多信息可以参考moinmoin的install.html
3. ....关于moin的配置请参考moinmon的install.html
4. 配置FasgCGI。如果CGI方式,那么每个请求相应的cgi文件都会被重新load,这样会极大的影响的性能, 而FastCGI方式只需要在第一次请求的时候load脚本,然后这些脚本就会被缓存下来,这样可以大大提高性能,此外,FasgCGI是一个单独运行的网关进程,就算webserver崩溃也不会影响到它。在多核的环境下,FastCGI是个不错的选择。mod_python是运行在webserver中的一个线程,在超线程的环境下可能表现更好。lighttpd不支持mod_python。
lighttpd是一个高性能的,轻型的(相较与apache),高度模块化的webserver,它需要在配置文件lighttpd.conf中指定装载fcgi模块,并且配置fcgi相应的参数。
note: 可以参考install.html中的'deploying in lighttpd'
- 设定装入fcgi模块:
server.modules = (
"mod_access",
"mod_rewrite", # <--- IMPORTANT! "mod_status", "mod_fastcgi", # <--- IMPORTANT! "mod_accesslog", "mod_redirect", "mod_auth", "mod_expire", ) - 配置fasgcgi模块,
$HTTP["host"] =~ "^127.0.0.1" {
url.rewrite-once = (
"^/robots.txt" => "/robots.txt",
"^/favicon.ico" => "/favicon.ico",
"^/moin_static163/(.*)" => "/$1", #所有的media文件url都是以moin_static163开头的
"^/(.*)" => "/wiki-engine/$1" #除了media文件和robots,favicon外的请求都送到fastcgi server
)
server.document-root = "/usr/share/moin/htdocs/"
#url以wiki-engine开始的都送到fastcgi。 url会被rewrite模块重写,可以看前面的定义url.rewrite-once
$HTTP["url"] =~ "^/wiki-engine/" {
fastcgi.server = ( "/wiki-engine" =>
(( "docroot" => "/",
"min-procs" => 10,
"max-procs" => 10,
"max-load-per-proc" => 2,
# allocate successive port numbers for each process, starting with "port"
"bin-path" => "/opt/mylib/moin-1.6.3/moin.fcg", #如果由lighttpd来启动fastcgi,那么需要指定这个值
"host" => "127.0.0.1",
"port" => 3060,
"check-local" => "disable",
))
)
}
}
5.这里反过来再提一下MoinMoin的配置。我的MoinMoin是安装到默认目录,即/usr/lib/python2.5/site-package/moin和/usr/share/moin,前面一个目录放置的是moinmoin的python源代码, /usr/share/moin放置的是模板代码(html,img,css等)和数据文件(保存用户数据,比如page, comments,user等)。然后我又把/usr/share/moin中的data, underlay,wikiconfig.py, moin.fcg复制到/opt/mylib/moin目录,这个目录叫做MoinMoin的一个实例。就是说你可以同时运行多个实例,它们分别有自己的名称空间,彼此不会影响,但是共用htdocs。
此外,需要注意的是权限问题,由于lighttpd是以www-data的用户运行,而fastcgi程也是它启动的,即fastcgi server也是以www-data的用户运行的,那么www-data必须具有/opt/mylib/moin目录读写执行权限。 总之要注意权限问题。但是如果fastcgi是通过手动单独在外面启动的,那么启动这个进程的用户必须具有读写执行/opt/mylib/moin的权限,这样的话,它是独立与lighttpd的权限系统之外的,可以另外设置权限规则。
Subscribe to:
Posts (Atom)