在Google App Engine中使用304 Not Modified状态码来提速

标签:Google App Engine, Python

最近用GAE做了个图像上传的站点,为了提升速度,我在服务器端采用了缓存技术,但这并未榨干GAE的最后一点能量。
实际上,由于我的图片是不会改变内容的,所以如果强制让客户端浏览器也缓存的话,就能减少很多流量,且不用访问缓存和数据库了。

碰巧今天看了下HTTP头的技术资料,以及《新增缓存机制 - HTTP Caching》,摘抄一些关于缓存的:
对于现代的主流浏览器而言,如果客户端收到的Response中包含Last-Modified,那么下次Request的时候就会在Request Header中包含If-Modified-Since字段,值就是上次服务器发送的Last-Modified。
此时,服务器可以将If-Modified-Since字段与文件的实际修改时间进行比较。如果有更新,则返回更新的数据;否则只需返回304 Not Modified状态码,客户端就会直接采用缓存中的文件。这就大大减少了服务器的吞吐量,也节省了彼此传输所耗的时间。

在GAE中实现这个技术非常简单,给个示例代码片段:
class GetImage(webapp.RequestHandler):
  def get(self, filename):
    #查找是否有If-Modified-Since字段,由于我不会改内容,所以无需比较时间
    if self.request.headers.get('If-Modified-Since'):
      self.error(304) #返回304状态码
      return

    #从缓存和数据库中取图像的过程省略

    if image.content:
      #发送HTTP头,这些时间可以自己设置,我是设为10年
      self.response.headers['Content-Type'] = 'image/' + image.type
      self.response.headers['Last-Modified'] = 'Thu, 19 Feb 2009 16:00:07 GMT'
      self.response.headers['Expires'] = 'Tue, 19 Feb 2009 00:10:33 GMT'
      self.response.headers['Cache-Control'] = 'public, max-age=315360000'
      self.response.out.write(image.content)
    else:
      logging.error('No such image: %s.' % filename)
      self.error(404)
注意一点,实际上4和5开头的状态码才属于错误,304并不属于错误。
我为了简单而直接使用了RequestHandler.error方法,你也可以用RequestHandler.set_status方法,或放在RequestHandler.response.headers中。

如果要判断时间,可以用《在Python下转换时间格式》一文中提到的方法。

此外,GAE默认为静态文件提供了600秒的缓存时间,并且对于text类型的文件会用gzip压缩输出。你可以更改app.yaml中的expiration配置,来改变缓存时间。

0条评论 你不来一发么↓

    想说点什么呢?