1. 免sharding的高并发计数器.
核心思想: 采用memcached作临时存储,定期写入datastore.
incrementCounter
1 def incrementCounter(key, update_interval=10):
2 """Increments a memcached counter.
3 Args:
4 key: The key of a datastore entity that contains the counter.
5 update_interval: Minimum interval between updates.
6 """
7 lock_key = "counter_lock:%s" % (key,)
8 count_key = "counter_value:%s" % (key,)
9 if memcache.add(lock_key, None, time=update_interval):
10 # Time to update the DB
11 count = int(memcache.get(count_key) or 0) + 1
12 def tx():
13 entity = db.get(key)
14 entity.counter += count
15 entity.put()
16 db.run_in_transaction(tx)
17 memcache.delete(count_key)
18 else:
19 # Just update memcache
20 memcache.incr(count_key, initial_value=0)
2.使用model cache给你的GAE应用程序加速
使用很简单,在你的models.py 最上方
import datastore_cache
datastore_cache.DatastoreCachingShim.Install()
3.在memcache之上构建的SessionManager.
4.全文检索(Simple Full Text Search)
测试代码的下载地址:http://github.com/DocSavage/appengine-search
Searchable
class Page(Searchable, db.Model):
author_name = db.StringProperty()
content = db.TextProperty()
myPage = Page(author_name='John Doe', content='My amazing content!')
myPage.put()
# This will enqueue indexing via Task Queue API
myPage.enqueue_indexing(url='/tasks/searchindexing')
# After index is complete, you can run searches
Page.search('search phrase') # -> Returns Page entities
Page.search('stuff', keys_only=True) # -> Returns Page keys
5.用GoogleFileService上传超过10M的大文件.(For Java)
(详细请看: http://code.google.com/p/google-file-service/)
简单地调用 DatastoreUtils.insertGoogleFile().方法就可以存入文件了.
6.脏数据保存
IsDirty
profile = Profile.get_by_key_name('someuser')
for field in ['username', 'password', 'description']:
setattr(profile, field, self.request.get(field, getattr(profile, field)))
profile.age = int(self.request.get('age'), 10)
if profile.dirty:
db.put(profile)
#profile.put(if_dirty=True)
7.通用的翻页器(PagerQuery)
8. CSV Property
CSVProperty
class MyModel(db.Model):
rules = CsvProperty(field_count=3)
new_entity = MyModel()
new_entity.rules = [('foo', 'bar', 'baz'), ('abc', 'def', 'ghi'),('my', 'new', 'property')]
new_entity.put()
9.用memcache来缓存Avatar以减少datastore的API调用.
Code
from google.appengine.ext import webappfrom google.appengine.api import memcache
import timefrom datetime
import datetime
class AvatarHandler(webapp.RequestHandler):
def output_avatar(self):
if self.avatar is None:
self.avatar = Avatar.get_by_key_name('avatar_%s' % self.u)
# store the last modified timestamp to the memcache
memcache.set('avatar_%s_lastmod' % self.u,
int(time.mktime(self.avatar.updated.timetuple())),
60*60)
# set the cache headers
lastmod = self.avatar.updated
fmt = '%a, %d %b %Y %H:%M:%S GMT'
self.response.headers.update({
'Cache-Control': 'max-age=86400',
'Expires': (lastmod + timedelta(days=1)).strftime(fmt),
'Last-Modified': lastmod.strftime(fmt),
'Content-Type': 'image/png'
})
self.response.out.write(self.avatar.content)
def get(self, username):
self.avatar = None
self.u = username
# get the last modified timestamp from memcache
# if the cache is empty (or replaced), look up it from bigtable
lastmod = memcache.get('avatar_%s_lastmod' % self.u)
if lastmod is None:
self.avatar = Avatar.get_by_key_name('avatar_%s' % self.u)
lastmod = int(time.mktime(self.avatar.updated.timetuple()))
else:
lastmod = int(lastmod)
# check if the output is necessary.
if self.request.headers.has_key('If-Modified-Since'):
dt = self.request.headers['If-Modified-Since'].split(';')[0]
since = int(time.mktime(datetime.strptime(dt, '%a, %d %b %Y %H:%M:%S %Z').timetuple()))
if since > lastmod:
self.response.set_status(304)
else:
self.output_avatar()
else:
self.output_avatar()