Wednesday, 29 March 2006

xlp223、pylons、BLOG

通过Blog,“认识”了xlp223,共同的话题就是Pylons。因为时差的关系,xlp223差不多总是在半夜12点左右,MSN过来一个Smile,然后开始对Pylons说东道西。

由于大家都有Blog的原因,有些主题在交流之后,就会出现在自己的Blog上。看看各自的Blog,感觉上有点类似于“92共识”的味道,一个主题,各自表述。有意思!

这不,关于分布式SCGI,xlp223又在那里说开了。

Flup之分布式SCGI服务

前一篇里,提到“从配置的形式上看,SCGI是可以进行分布式部署的,Web Server和Web App不必在同一台机器上”。昨晚,被xlp223抓住,尽管有些困,也不得不跟着学习一下,结果xlp223试验成功了。在缺省配置下,Paster是将SCGI限制为只能本地访问。如果要从外部访问SCGI Service,需要在Pylons配置文件中增加allowedServers选项。

...
[server:main]
use = egg:PasteScript#flup_scgi_thread
host = 127.0.0.1
port = 5001
allowedServers = 192.168.0.1
...

这里192.168.0.1是Web Server的IP地址,允许该地址访问SCGI Service。

接下来考虑到的是Web Server和Web App多对多映射的问题,即一个Web Server连接多个Web App,而一个Web App又对多个Web Server提供服务。

一个Web Server连接多个Web App,对于mod_scgi的SCGIMount这种redirect方式,显然是没有问题的,只要将不同的Web App分别mount到不同的路径就行了。

一个Web App对多个Web Server提供服务,对于现有的flup 0.5来讲,是采用限制IP的方法。Flup提供给Paste的接口,在PasteScript-0.5-py2.4.egg/paste/script/flup_server.py中,形式如下,

...
def run_scgi_thread(wsgi_app, global_conf,
scriptName='', host='localhost', port='4000',
allowedServers='127.0.0.1'):
...

allowedServers的缺省值是'127.0.0.1',只对本机开放。如不限制IP,Paste就必须将allowedServers设成None。同时,如果在配置文件中列出了IP地址,run_scgi_thread函数会自动转换成一个list。这一点比较有用,可以接受多个IP地址。

在flup-0.5-py2.4.egg/flup/server/scgi_base.py中,class BaseSCGIServer的_isClientAllowed是测试到访的IP地址是否是允许的IP。注意这一行代码:

    ret = self._allowedServers is None or addr[0] in self._allowedServers

对于allowedServers为None的情况,允许。后半句是test IP是否在allowedServers list里面。

所以,如果要一个Web App对多个Web Server,只要在配置文件里把允许的IP地址都列上就行了。尽管这里不支持192.168.0.*或192.168.0.0/24这样的形式,但在实际应用中也没有多少影响,毕竟这里的“多”也不会太多。

对分布式部署来讲,一个重要的东西是动态负载平衡(load-balancing),这一点在Flup的SCGI上,目前还不知道如何实现。xlp223讲,文档上说AJP可以,不知道是怎么玩的。

Saturday, 25 March 2006

SCGI on Windows

原来也曾尝试过在Windows下面安装SCGI,失败。原始的SCGI for Python中间包含了一个C程序,是针对OpenBSD/FreeBSD的,其中关于socket的头文件里的一些底层结构和函数,自然是针对Unix-like系统的。其结果是,在Windows下面,不管是VC6(for Python 2.3),还是VC7(for Python 2.4),都是无法编译通过。这需要参照Windows SDK进行改编。文件并不大,不过要同时参考Unix和Windows的相关细节,还是需要花些时间的。

xlp223在其blog上的一篇文章,是个很好的发现。Pylons App透过Flup提供SCGI Service,Flup自身实现了SCGI协议,以及FastCGI和AJP,且还有多线程和多进程之分。使用Flup,就不需要编译独立的SCGI。这一点太重要了,突破了以往惯性思维的误区。

好了,现在可以在Windows里轻松架设Lighttpd+SCGI for Pylons了。Pylons应用的配置,和以前在Linux下的一样。Lighttpd for Windows已经包含了SCGI模块。Lighttpd的配置,需要修改C:\lighttpd\etc\lighttpd.conf文件。

server.modules              = (
...
"mod_scgi",
...
)
...
scgi.server = ( "/pyapp" => ((
"host" => "127.0.0.1",
"port" => 5001,
"check-local" => "disable"
)) )
scgi.debug=0

这里的host和port对应着Pylons App的相应设置,Pylons App中包含了prefix = /pyapp选项。

从配置的形式上看,SCGI是可以进行分布式部署的,Web Server和Web App不必在同一台机器上。在这种情况下,Pylons App配置中,[server:main]下的host就不能为127.0.0.1。一旦这样设置了,外部访问不到,Web Server就连不过去了。也不必非要用实际IP地址,设成0.0.0.0就行了。

Thursday, 16 March 2006

Pylons 0.8

Pylons终于发布了一个正式的版本-0.8。正如发布文告中提到的,Pylons本身综合了其它框架的思想和特点,而Pylons的一些底层组件,也被融合到其它的框架之中。Pylons比较注重建立一个良好的自身架构。目前所欠缺的是,缺乏类似于其它框架的admin tools。

发布了正式版本,就不需要从SVN上Check Out了。躲在proxy后面的机器,现在也可以安装Pylons了。

这是安装以后新增的egg列表,来看看Pylons 0.8到底融合了那些东西。

pylons-0.8-py2.4.egg
nose-0.8.7.1-py2.4.egg
webhelpers-0.1-py2.4.egg
wsgiutils-0.7-py2.4.egg
simplejson-1.1-py2.4.egg
pastescript-0.5-py2.4.egg
pastedeploy-0.5-py2.4.egg
paste-0.5-py2.4.egg
myghty-1.0.1-py2.4.egg
routes-1.3-py2.4.egg
cheetah-1.0-py2.4.egg

除了Pylons本身,还有10个eggs跟着一起来了,哈哈!

Friday, 10 March 2006

Blogger Error

我现在怀疑自己最近的手气,似乎比较特别。今天在打开Blog的时候,看不到图片。View Image,又得到一页出错信息。Google,这最后的神话,看来也快撑不住了。

忽然之间,有个idea,开辟一个blog,专门介绍各种error message,那样一定很好玩。不过,...,这样是不是很无聊?不过,...,或许收集得多了,还能发财,也未可知。算了,还是我出主意,留给别人去实践吧。

Thursday, 9 March 2006

Gmail Error


今天使用Gmail,得到了这样的结果。真是难的一见,cut下来,留个“纪念”。正所谓,智者千虑,终有一失。

人总是免不了mistake,程序中免不了bug,电脑里免不了Error,窗口上免不了Blue Screen。

写完这个消息,Gmail已经恢复正常了。哈哈!

Wednesday, 8 March 2006

Paste HTTP Server

以前说过,coLinux serve Pylons,响应速度慢。还以为是coLinux的问题,今天有mail也提到,Paste在不同机器之间访问速度慢的问题。按照Ben的建议,把config.ini中[server:main]

use = egg:Paste#http

改成

use = egg:PasteScript#wsgiutils

速度立即正常了。Paste#http或许在HTTP协议的实现上有些特殊,不能及时响应吧。又看了看Myghty的样板,那里就是用的wsgiutils。答案早就有,就是不注意。

从另外一个角度来看待这个事情,Paste速度慢的问题,已经有比较长的一段时间了,现在才有人提出来。估计大部分人是通过和Apache进行组合,解决了速度问题。其它的因素,只能说使用Paste的人还不够多,Pylons的人那就更少了。

Tuesday, 7 March 2006

Ubuntu Dapper

今天例行公事地Update了一下Ubuntu,顺便翻了翻Dapper的软件列表,有libapache-mod-scgi (1.9-1)lighttpd (1.4.9-1),这样搭配Apache或Lighttpd来玩Pylons就方便多了。按照计划,Ubuntu Dapper会在四月二十日发布。期待中。

在更新Python Egg之后,启动Pylons App的时候,遇到了PasteScript版本有问题。在/usr/local/bin/paster中更正了PasteScript版本号之后,恢复正常。当然,又测试了一回prefix,现在可以说是99.9%的没有问题了。剩余的0.1%是,加了prefix之后,localhost:5000/还可以看到缺省页。如果和Apache连用,自然是不存在这个问题的,呵呵!

Monday, 6 March 2006

Pylons的prefix选项

Pylons现在提供了prefix选项。利用此选项,可以将Pylons应用的URL整体Shift到sub-path中,这样在前面提到的问题,就轻松化解了。目前该选项,还不是十分完美,需要对middleware.py做一点Hack才行。

Hack以后的middleware.py如下:

...
import re
class PrefixWrapper(object):
def __init__(self, app, prefix):
self.app = app
self.prefix = prefix
self.re_prefix = re.compile(self.prefix + '(.*)')

def __call__(self, environ, start_response):
environ['PATH_INFO'] = re.sub(self.re_prefix, r'\1', environ['PATH_INFO'])
if not environ['PATH_INFO']: environ['PATH_INFO'] = '/'
return self.app(environ, start_response)

def make_app(global_conf, **app_conf):
if not app_conf.has_key('prefix') or app_conf['prefix'] == '/':
app_conf['prefix'] = ''
...
# @@@ Static Files in public directory @@@
staticapp = StaticURLParser(config.paths['static_files'])
staticapp = PrefixWrapper(staticapp, app_conf['prefix'])
...

只要在配置文件config.ini的[app:main]中,增加prefix = /pyapp即可。Pylons应用的/就变成了localhost:5000/pyapp。Apache中SCGIMount指向/pyapp,通过SCGI访问Pylons应用也就没有问题了。

为了在Myghty的模板中应用prefix,可以在middleware.py中设置g.prefix = app_conf['prefix'],这样在myt文件中就可以通过<% g.prefix %>输出prefix。

Saturday, 4 March 2006

Apache 2 + SCGI 拾遗

mod_scgi中使用的SCGIMount设置方式,看起来非常眼熟,让我想起了mod_jk。印象中,Apache 2 + Tomcat也是用在mod_jk中设置 JkMount的方式。事实上,两者的工作模式也很相似,都是运行各自独立的Service(Server),通过桥接器连接到Apache上。

前一篇Blog中提到,“libapache2-mod-scgi至少要是1.7.0以上的”,这主要是因为SCGI的接口变化。SCGI从1.5开始实现SCGIMount,1.7版又Fix了一个与此有关的Bug,因此应使用1.7以上版本的SCGI。如果一定要用早先的版本,那只有使用SCGIServer和SCGIHandler了。

前面说了,“在Ubuntu系统下,Breezy的libapache2-mod-scgi也还是1.2-1版本,Dapper的才是1.9-1”,如果现在要使用Dapper上的1.9-1,简单的hack办法,可以先安装1.2-1,然后下载1.9-1版本,用1.9-1版本deb中的mod_scgi.so和scgi.load覆盖旧版本,或许能行。SCGI本身还是通过easy_install,获得最新的1.10版SCGI。

如果觉得Hack的方法不好,那就只好自己编译了,可以看看这里。在编译之前,还需安装apache2-threaded-dev,编译所使用的工具apxs,包含在此包中。注意,在编译mod_scgi的这篇Blog中,build and install下面的指令,三个命令混到一行里了,实际应该是

# cd scgi-1.7/apache2
# apxs2 -i -c mod_scgi.c
# a2enmod scgi

手动编译之后,还需要在/etc/apache2/mods-available目录下,自己建立scgi.load和scgi.conf文件,然后才能a2enmod scgi。

前篇仅仅是试验性的,对开发而言,能用就行了。关于如何配置Virtual Host,详细的情况请参考1234。Windows版本的mod_scgi在这里下载。

Setup Apache 2 + SCGI for Pylons(Paste Enabled) Web Application

我的Pylons试验平台是coLinux(Debian-3.0r2)。对于coLinux来讲,本机访问Pylons应用,没有问题,但从外部访问速度较慢,而访问Apache 2的速度却正常,原因未明。因此,通过Apache来访问Pylons应用,似乎是理想的解决办法。刚好xlp223也说到这事,就试试如何用Apache 2和SCGI来访问Pylons应用。

首先,需要为Pylons安装SCGI服务器,

$ sudo easy_install flup

接着,修改Pylons应用的配置文件scgi.ini,(缺省是development.ini,复制成scgi.ini)

...
[server:main]
use = egg:PasteScript#flup_scgi_thread
host = 127.0.0.1
port = 5001
...

请注意,egg:PasteScript#flup_scgi_thread,#号后面实际上不是注解,它是通知Paste用flup以多线程的方式提供SCGI Service。具体请看Paste的文档。这里,SCGI的端口是5001,只能本机访问。

使用如下命令启动或终止SCGI服务,

$ paster serve scgi.ini start (启动)
$ paster serve scgi.ini stop (终止)
$ paster serve scgi.ini status (状态检查)

也可以让SCGI以daemon模式运行,

$ paster serve --daemon scgi.ini
$ paster serve --stop-daemon scgi.ini

如果希望在开机的时候启动SCGI Service的话,请参考Paste的文档或其它Service,编写Service启动脚本。这里不再详述。

现在,Pylons应用已经可以运行在SCGI模式下了。但直接访问SCGI端口是没有结果的,还需要通过Apache来桥接过去。我使用的是Apache 2。如果要桥接SCGI服务,就必须安装mod_scgi模快。

$ sudo apt-get install libapache2-mod-scgi

会自动安装mod_scgi for Apache2。如果还没有安装Apache 2的话,Debian系统也会一并安装的。

需要特别指出的是,Debian稳定版中的libapache2-mod-scgi,版本是1.2-1,而我们需要的libapache2-mod-scgi至少要是1.7.0以上的,所以只有从unstable的pool中安装1.9-1版本的libapache2-mod-scgi。如何安装unstable的软件,需要如此这般这般...

在安装好合适版本的mod-scgi之后,剩下的工作就是配置Apache了。在/etc/apache2/mods-available目录下,可以发现文件scgi.load,其内容就是Load mod_scgi到Apache。还需要在该目录下建立scgi.conf文件,

$ sudo nano scgi.conf
< IfModule mod_scgi.c >
SCGIMount / 127.0.0.1:5001
< /IfModule >

这样,Apache的根就被指向了SCGI服务的5001端口,所有对/的访问,都将转向127.0.0.1:5001。

Debian系统下,还需要激活mod_scgi模块,

sudo /usr/sbin/a2enmod scgi

会在/etc/apache2/mods-enabled中建立scgi.load和scgi.conf的链接。重新启动Apache 2

$ sudo /etc/init.d/apache2 restart

现在就可以通过Apache2访问Pylons应用了。尽管配置简单了些,Apache 2 + SCGI还是正常工作了,速度也没有问题。

必须指出,上述配置还有应该注意的问题。scgi.conf中,把/指向了SCGI,这样Apache就不能进行其它服务了,而通常我们是给Pylons应用分配一个子路径,如/www.abc.com/myapp。如果用/myapp代替上述的/,就会发现,Pylons应用/下的东西访问不到了。Apache是把完整的URL传递给了SCGI,Pylons应用在进行URL解析的时候,不会认为是访问自己的/,而是以为访问/myapp子目录下的内容,所以实际输出的是Pylons应用/myapp下的东西。Pylons应用/下的内容,将永远访问不到。

解决上述问题的途径,可以有两个。一是,象网上大部分材料所做的那样,在Apache中使用Virtual Host,这样两个/就统一起来了;另外的办法是,修改Pylons应用的Mapping部分,将/myapp部分包含进去,以/myapp为基准。

前面虽然说的是SCGI访问Pylons,实际上对Paste Enabled的Web Application都是有效的。

另外,在Ubuntu系统下,Breezy的libapache2-mod-scgi也还是1.2-1版本,Dapper的才是1.9-1。还好,Dapper正式版离我们不远了。