Google App Engine 对 module 的缓存时间
在 GAE 的文档中提到:import 进来的 module 会被缓存,并用一个例子演示:多次执行 Request Handler 脚本的时候,被 import 进来的模块中的代码不会反复执行。
### mymodule.py
counter = 0
def increment():
global counter
counter += 1
return counter
### myhandler.py
import mymodule
print "Content-Type: text/plain"
print ""
print "My number: " + str(mymodule.increment())
在这个例子中,虽然 mymodule.py 中第一句就是 counter = 0,但是下面的 myhandler 在调用的时候并不会反复执行这一句,因为mymodule 这个模块被缓存了,下次执行 myhandler 的时候直接从缓存中加载了 mymodule 以及其中的变量 counter。
但是,问题来了,我能不能依赖这个缓存机制,用来长期存储存一些全局变量呢?比如网站计数器。答案是不能。为了测试一个模块能被缓存多久而不会重新加载,我在代码的三个模块文件中第一句都加了一个 logging 语句:logging.info("module XXX reloaded"),下面是7月15日的观测结果:
- I 07-15 11:42PM 52.480 module theme reloaded
- I 07-15 11:42PM 52.483 module config reloaded
- I 07-15 11:42PM 52.562 module memcache reloaded
- I 07-15 07:54PM 07.536 module theme reloaded
- I 07-15 07:54PM 07.539 module config reloaded
- I 07-15 04:43PM 44.40 module memcache reloaded
- I 07-15 04:43PM 11.720 module theme reloaded
- I 07-15 04:43PM 11.723 module config reloaded
- I 07-15 12:57PM 55.851 module theme reloaded
- I 07-15 12:57PM 55.855 module config reloaded
- I 07-15 12:57PM 55.935 module memcache reloaded
- I 07-15 12:20PM 12.906 module theme reloaded
- I 07-15 12:20PM 12.910 module config reloaded
- I 07-15 12:20PM 12.995 module memcache reloaded
- I 07-15 11:16AM 11.12 module memcache reloaded
- I 07-15 11:16AM 04.596 module theme reloaded
- I 07-15 11:16AM 04.599 module config reloaded
- I 07-15 09:16AM 22.9 module theme reloaded
- I 07-15 09:16AM 22.12 module config reloaded
- I 07-15 09:16AM 22.93 module memcache reloaded
- I 07-15 08:08AM 32.22 module theme reloaded
- I 07-15 08:08AM 32.25 module config reloaded
- I 07-15 08:08AM 32.102 module memcache reloaded
- I 07-15 06:17AM 05.237 module theme reloaded
- I 07-15 06:17AM 05.240 module config reloaded
- I 07-15 06:17AM 05.327 module memcache reloaded
- I 07-15 02:46AM 44.344 module theme reloaded
- I 07-15 02:46AM 44.347 module config reloaded
- I 07-15 02:46AM 44.445 module memcache reloaded
可以看出,logging 语句会每隔一段时间执行一次,也就是说,模块会被重新加载一次,时间长短不等,有可能1小时,也有可能4-5个多小时。。。回到最初的例子,那就是:一旦重新加载,counter 就会再次变成0。
另外,用 appcfg.py update 更新了网站之后,也会被重新加载。
在使用 MemCache 的时候,我用了一个全局变量来存放一些东西(比如 post,commet)的上次修改时间,用来判断 MemCache 中的对象是否过期,但是当时不知道 module 的缓存会在几小时内过期导致那个变量清空,所以现在 MemCache 对象的最长生存时间只有几个小时。。。不过这已经让 CPU 的使用量大大下降了。
前两天把代码改了一下,把全局变量放在了数据库中,模块重新加载的时候就从数据库中重新读取,然后稍微重构了一下 MemCache 的使用方法,但是重构之后又遇到了另外一个问题。(简单地说就是,往 MemCache 中存放 str/unicode 之外的对象,可能导致取不出来,这个问题似乎同样和模块的缓存失效期限有关)
令人高兴的是,昨天,Guido 说已经把这个 bug 修复了,不过我还是打算再观察两天,等真的不出问题了再把代码更新过来。