您的位置:首页 > 移动开发

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

2011-01-19 13:34 351 查看
自从关注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'}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: