google application engine 下应用开发的一些总结.

自从关注google application engine 以来,为了更深入了解这个平台,在gae上设计,开发一个小应用 sharecode . 通过这个应用,总结了使用python,gae 开发的一些特点:

开发效率高

python,django 此类动态语言及其框架开发效率确实比java ,hibernate,spring高出不少, 以sharecode 为例, 从3月初开始构思到3月底基本功能完成, 总共也就3周多一点的时间,如果是在java 下使用hibernate,spring 之类的框架,基本上不可能在这么短时间内完成.总结python,django 下效率高的原因(gae 和普通的django应用差别主要是在model方面),主要有三方面:

  • 层次的简化 : 从model 到view, django 下,尤其是在gae 下,代码的层次比spring,hibernate 下缩减了不少, spring,hibernate 按照严谨的模式, model, dao,service, 一层层上来,django 下model本身就具备了dao 的功能, 不需要再单独开发一套dao代码. model 开发完直接就可以存取.
  • 代码组件的简化 同样是model, django 中就是一个类的定义, 而hibernate 下除了类还要写映射配置,生成ddl等等乱七八糟的东西 ; django 中定义了view(相当于controller)处理http请求,定义了model 模型用于数据建模,但对于中间的逻辑代码自己就可以自由发挥了,不象在spring下需要接口,实现类,配置文件这么多组成部分,django中的逻辑代码可以简单到就是一个module 中的function. 这又大大节省了码字的时间.
  • 编码,测试,调试的时间大大缩短 , 一方面python 是动态语言,编码完成直接刷新浏览器就可以看到更改了,另一方面django,gae的开发服务器启动都非常快速, 相比较java 的服务器,估计只是其几分之一甚至十几分之一的启动时间,这点时间虽然短,但反复积累下来,也很可观了.

datastore有优点也有不足

datastore 我认为可能是整个gae 开发环境中最重要的一部分 , 因为任何应用程序都有持久化存储的需要,而在gae下,datastore是实现持久存储的唯一的手段.

datastore 的优点在于它构建在google 的bigtable 实现基础之上,能够自动分布式存储,伸缩性很好; 另一方面它的编程接口非常简单, 主要用到的就是 get,put,delete, run_in_transaction 这几个函数以及Query,  GqlQuery这两个查询接口对象.但实际使用中发现它有一些弱点和限制:

  • 不支持模糊查询或者说关键字查询 , 一般关系数据库服务器都支持 'like' 查询,并且现在也有和关系数据库集成的全文索引解决方案. 但以google 这么强的搜索功力,直到现在也没把搜索功能放到datastore api中,让人费解(不知道将来是不是准备作为增值服务要收费的 ). 虽然在sdk 源码中有一些'search' 的影子出现,但官方的文档中未有提及. 没有这个特性大大降低了datastore 的使用价值. 现在搜索引擎的流行已经培养了大家关键字查询的使用习惯 ,一个网站不能search 那真是拿不出手.
  • 对事务的支持有限 . gae datastore 有个entity group的概念,属于同一个group的entity在物理位置上存储到一起,在同一个事务中只能操作同一个group内的entity,而在实践当中,无法保证有可能需要运行于同一个事务中的entity都属于同一个group.如果把所有的entity都放到同一个group中,那就损失了datastore 的分布式存储特性和性能(看来鱼和熊掌难以兼得). 所以gae datastore不适合对事务要求高的场合, 例如'企业应用'并不适合.
  • datastore 中无法获得某种entity的数量 . 具体来说如果有一个class A(db.Model). 在运行时是无法得知到底datastore 中存储了多少A 的实例, Query 对象有一个 count 方法可以获得查询数量,但上限是1000. 也就是说如果现在有 10000个 A 的实例,我用 query = A.all()  query.count() 得到的数字是1000. 如果网站是一个内容类型的网站,想知道当前某种内容有多少数量,这就很郁闷了--办不到.
  • datastore 缺乏统计手段 . 在关系数据库中,可以使用sql 的统计函数完成,在datastore中,可能只能自己编程遍历数据实现了,而且gae 有一个单次请求不能超过30秒的限制,所以如果数据量很大,那就很麻烦.

back reference

datastore 中有一个很有用的特性叫做back reference, 具体来说 如果 A 中有一个字段使用 ReferenceProperty 引用了 B, 在B 中自动获得一个 a_set 的字段, 类型是 Query,这个Query对象返回的结果集中包含了所有引用了B的A对象, 这个特性在数据建模时是实现 1:n, m:n 这些关联关系的基础.

 

gae环境的限制太多

举一些例子, 例如

  • 30秒的请求处理时间限制,
  • 不能流输出,gae程序的所有输出都被缓存,等程序执行完毕后,一次性输出到浏览器
  • api 调用参数大小不能超过1M,
  • 通过http传递的内容不能超过10M,
  • 除了http和https 两种协议外,不能以其它方式进行出站通信.

这些限制都或多或少限制了在gae 上可以开发的应用类型.

 

其它的一些需要考虑的问题:

  • datastore 中数据模型的更改实现起来比较麻烦.
  • datastore 中数据的批量导入提供了bulkloader.py 工具,但没有官方的数据备份方案..或许这又是一个非技术因素导致的问题.
  • gae 有一个比较复杂的资源配额方案
  • 国内对appspot.com 的域名解析已经全部被封

 

最近听到消息说google 将会在5月份宣布gae平台支持java, 如果这条消息成为事实,考虑到servlet api 使用的广泛程度,gae支持servlet 和jsp应该是没有问题的. 数据存储很大可能还是 datastore. (估计会有个"jdbc over datastore"之类的官方或者第三方类库).其它还支持哪些api和类库呢,如果用到自己的类库又怎么处理?这些问题都只能等待5月份了.

-----------------------

python入门



第一步:
D:/newtest> manage.py startapp  contact
产生文件
__init__.py
models.py
views.py

第二步:
在contact目录中新建forms.py文件
forms.py内容如下

# -*- coding: UTF-8 -*-
from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField()
    email = forms.EmailField(required=False)
    message = forms.CharField()

第三步:setting.py INSTALLED_APPS 加入应用程序
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'newtest.wiki',
    'newtest.address',
    'newtest.classmate',
    'newtest.ajax',
    'newtest.contact',#这是新加的


第四步:
D:/newtest>python manage.py shell
>>> from address.forms import ContactForm
>>> f = ContactForm()
>>> print f
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_subject" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
>>> print f.as_ul()
<li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></li>
<li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
>>> print f.as_p()
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p>
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
>>> print f.as_d()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'ContactForm' object has no attribute 'as_d'
>>> print f.as_p()
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p>
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
>>> print f['subject']
<input type="text" name="subject" id="id_subject" />
>>> print f['message']
<input type="text" name="message" id="id_message" />
>>> ^Z


D:/newtest> manage.py startapp  contact
Error: [Error 183] : 'D://newtest//..//newtest//contact'

D:/newtest> manage.py startapp  contact

D:/newtest>python manage.py shell
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from contact.forms import ContactForm
>>> f = ContactForm()
>>> f
<contact.forms.ContactForm object at 0x0115FB90>
>>> print f  #或者print f.as_table()结果一样
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_subject" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
>>> print f.as_ul()
#注意到<li>没有
<li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></li>
<li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
>>> print f.as_p()
#注意到<p>没有
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p>
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
>>> print f['subject']
<input type="text" name="subject" id="id_subject" />
>>> print f['message']
<input type="text" name="message" id="id_message" />
>>> print f['email']
<input type="text" name="email" id="id_email" />
>>> f = ContactForm({'subject':'Hello','email':'admin@sohu.com','message':'this is a forms instance'})
>>> f.is_bound
True
>>> f.is_valid()
False
>>> f = ContactForm({'subject':'Hello','message':'Nice site'})
>>> f.is_valid()
False
>>> f['message'].errors
[u'This field is required.']
>>> f['subject'].errors
[]
>>> f['email'].errors
[]
>>> f.errors
{'message': [u'This field is required.']}

>>> f = ContactForm({'subject':'Hello','email':'admin@sohu.com','message':'this is a forms
>>> f.is_valid()
True
>>> f.cleaned_data
{'message': u'this is a forms instance', 'email': u'admin@sohu.com', 'subject': u'Hello'}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值