我为什么放弃迁移Django项目到GAE平台?
- 21 Apr 2009
- Posted in gae
经过四个晚上的折腾,解决种种问题,又遇到种种新问题。自认为具有不一般的忍耐力的我,最终还是决定放弃迁移个人项目到Google App Engine平台!随之,本勾画好的美好幻境都也成为泡影。
故事从上周末开始..
自从上次sky问我要了gchen.cn的源代码之后,心里一直惦记着要把这个项目的程序改进一些后台功能,并计划能够把之前乱糟糟的代码整理一下,好歹下次有机会给第二个人的时候,不会那么没底气啊:-)。GAE虽然之前也有所关注,并了解有着种种流量等限制,但心想对于我这等小网站,流量啥的定不成大问题,Google这个大靠山应该靠得住的!借着刚写过几个Django项目经验的胆, 便开始进入了GAE这个大魔窟。
首先遇到的问题是,迁移Django项目到GAE,怎么保留尽可能多的代码?虽然GAE包含了0.61版本的Django,也能够支持其模板,views,url routing等,但是必须要重新写models,因为GAE不用关系数据库,用的是BigTable和GQL查询。再加上,admin也没有了,flatpages,session组件等都不支持(后来发现有如django-patch之类的开源项目,可以帮助实现一些Django失效的功能,但是研究后发现支持的并不彻底,而且并不想引入太多第三方库,过分依赖其他的代码,对于本小项目,实在没有必要)。于是当机立断,就依赖现有GAE的环境,把代码重新写一遍 - 其实models也只有两个类(如果不计要自己设计flatpages和admin的话),说白了,这么小的项目怎么也写不过1k行Python代码吧!
果然很顺手,搭环境,读GAE的文档,不到一个晚上就把models和第一个view写好了,并试了一下memcache很好用,原先的template也可以直接用,似乎一切很顺利!
接下来开始想怎么把之前的flatpages搞进来,还有那个分页-现在的项目都是Django1.0的代码,paginator的类和0.6可是大不一样,考虑以后还有更多的功能实现,在旧的Django上做开发,这哪成?!于是,开始研究怎么让GAE支持新的Django库。
官方网站倒是给了文档,通过Zipimport来支持1.0的Django库,原因是因为GAE的单个app有1k个文件的限制,剥掉文档、测试等文件,Django1.0.2也有900多个文件,app只用1/10空间,这活谁都不会干!Django1.0半年前都已经release了,现在都不支持,看到有人在论坛说因为这个、因为那个。总算,前后试了好几次,终于能让GAE支持Django1.0.2的库,为了方便后来人,这里记录一下需要注意的地方:
django.zip压缩Django项目下的django目录,并且这个目录是根目录。真绕口,大概文件结构是这样:
├─django │ ├─bin │ │ └─profiling │ ├─conf │ │ ├─app_template │ │ ├─locale … …
其次,入口文件(常用main.py)比较重要,特别是这么几行(我的django.zip在项目根目录):
REXML could not parse this XML/HTML: <pre># Add Django 1.0 archive to the path. django_path = 'django.zip'
to avoid importing in every request
if not django_path in sys.path: # Uninstall Django 0.96. for k in k for k in sys.modules if k.startswith(‘django’): del sys.modulesk sys.path.insert(0, django_path)
Must set this env var before importing any part of Django
os.environ‘DJANGO_SETTINGS_MODULE’ = ‘settings’
Force Django to reload its settings.
from django.conf import settings
http://code.google.com/appengine/kb/commontasks.html#root_urlconf
settings._target = None</pre> 注释里很多是后来发现问题后加上的,希望对你有用。
把现有的分页代码加上,运行的貌似很顺利。
更新到服务器上,运行没有问题。目前为止都是测试数据,怎么拿mysql的备份数据更新到服务器呢?
GAE提供了一个bulk_uploader的方案,偶的神呐,这玩意折腾了我一个晚上都没有搞定。开始发现这产品搞出来有点仓促啊,这工具怎么是人用的啊?!
原理大致是,上传的数据做成csv格式,当然只支持逗号隔离和双引号转义,一个表一个csv文件(这里顺带bs一下微软的excel默认的unicode的csv都不支持)。然后要继承一个loader类,这个类用来上传对应的csv文件,所以这个类里要把csv中的每一列名、类型都标注好,另外当然要用到你的model类。然后把csv和这个loader类作为参数执行bulkloader.py,运气好,你就可以搞定了。我就是运气不好啦,这个py是在GAE目录执行的,引用你的app的model需要设置PYTHONPATH,我直接去改了GAE的源文件把我的model给join进去了,虽然认了,还是遇到其他问题。在新闻组里面也有问bulkuploader的人,不多,大概搞成功的都是新项目吧,迁移的人估计很少!最好,历史数据也算了,对我价值不是十分大,但是开始对GAE有点力不从心了。
临睡前,发现服务器上运行时候页面加载比之前慢不少,一查log,发现每个request都在Zipimport django包!我看文档还算仔细的,想起有个release的一条改进就是解决这个问题啊,google也有很多在说used high amount of CPU已经过去时了。但是很抱歉,我又遇到了!当然,先去查是不是自己的问题,main里面注意到了先判断有没有在path中再导入,应该不成问题。但每次request都会使用cpu2000ms的提醒到现在还是存在(并发多时,却不会出现)。加了几个feed数据之后,接着开始出现timeout的操作。无奈,相对不是大问题,先完成其他功能吧。
Google帐户的集成还是比较方便,省去要处理用户权限问题。顺手加了两个form,虽然没有admin免费的东东,自己写一下编辑数据很快搞定。GAE的后台(http://localhost:8080/_ah/admin)是有简单编辑数据的form的,但是有个textproperty一直用input而不是textarea,导致我的多行文本硬是不能搞进去,所以还得自己写。另外,服务器上有方便的log和性能提示,客户端就没有这么好了,调试起来非常麻烦,用pdb有点不一样,我用下面几句来对GAE中代码调试,有帮助的朋友接住:
import sys
for attr in ('stdin', 'stdout', 'stderr'):
setattr(sys, attr, getattr(sys, '__%s__' % attr))
import pdb
pdb.set_trace() 然后,memcache的管理在客户端老是会出问题,要么flush之后还能继续使用,要么那个timeout不起作用。
最后,总结一下。GAE这个东西是蛮好的,尽管依靠Google多年来从搜索引擎到Gmail到在线office各个领域征服了大量用户群和开发人员,GAE在这个巨人肩膀上具有十分优越的高性能的应用基础架构,和一向简洁实用的开发理念,但是恕我愚见,目前这个平台还很不成熟。容易上手,但是开发效率不高,能够提供高性能的回报,却要放弃传统数据库和一些高级编程技巧,受限于各种流量、并发请求等等。尽管Google量身定做了一系列的收费尺度用于商业,作为新一代开发应用平台,在下次尝试前,一个普通的开发人员期望看到有以下改变:
- 本地的logging、trace机制
- 人性化的数据管理和上传同步工具
- 增强GQL的查询(现在连join也没有,本来一个sql可以搞定,不得不在代码写两个循环来做)
- 尽快同步Django等开源框架
- 开放更多的顶级域名(如:.cn等)