使AJAX可缓存——基于flask
主流浏览器都有缓存机制,主要基于HTTP协议定义的缓存策略。对于一定时间内不发生变动的文档缓存起来,对于下次请求,就可以直接返回缓存的结果。使用缓存有以下好处:
1、减少冗余的数据传输,节省网络流量成本
2、减少加载时间,客户能够快速加载页面
3、减少对服务端的压力,避免过载
我们一般会为静态文件,如图片,脚本,样式表等设置缓存,这样客户端在下次请求时可以减少不必要的网络请求。实际上,我们可以把它用在所有组件上,包括Ajax响应,只要可以确认结果不经常变动,就可以使用缓存策略。
AJAX
AJAX (Asynchronous JavaScript and XML)表示异步的javascript和XML,实际上,现在最著名的是JSON。Ajax可分为主动请求和被动请求。被动请求指为了将来使用而预先发起的,提前加载一些用户可能用到的数据,来提高用户体验。主动请求,指基于用户当前的操作而发起的请求。
虽然AJAX是异步请求,但是对于主动请求,用户任然需要等待响应。即便是被动请求可以让用户感受不到等待,但是仍然会有请求,产生流量,对服务端产生压力。
HTTP缓存策略
HTTP协议通过Header来控制缓存的,包括请求和响应,这里只讲响应的缓存机制。响应缓存主要通过Expires头和Cache-control头来控制。下面按优先级由高到列出一些常见的缓存策略,:
- Cache-Control:no-store 不要缓存这个文档
- Cache-Control:no-cache 保存文档,但是需要与服务端再验证才能使用
- Cache-control:max-age 缓存最长保存时间,单位是秒
- Expires:日期 根据日期判断过期,由于客户端和服务器日期可能不同步,不推荐使用
缓存过期检测
为了防止使用了过期的数据,必须要为缓存设置过期时间,当缓存过期时,需要向服务器请求新的数据。但实际上,虽然缓存过期了,但是服务器的数文档并没有变动,并不需要返回整个文档。因此客户端可以让服务端在改变文档的情况下才发送整个文档。这种特殊请求就是有条件的请求。条件请求一般使用Last-Modified/If-Modified-Since 和 Etag/If-None-Match。
Last-Modified表示文档的最后修改日期,当缓存过期了,客户端向服务器发送If-Modified-Since:Last-Modified的值进行条件请求,当服务端在这段时间没有修改文档,那么就返回不包含主体的304响应,否则就返回新的文档。
ETag 则是一个唯一文件标识符,每次文件修改后都会生成一个新的 ETag,因此也可以根据Etag的值来判断文档有没有更新。和最后修改时间检测类似。
如果响应首部仅包含Last-Modified,就使用If-Modified-Since验证,如果仅包含ETag,那么使用If-None-Match来验证。如果两者都提供了,那么客户端就应该同时发送两种验证。
基于Flask的缓存响应
def make_cache_control_response(json_data): #json_data可能来自数据库或者服务端缓存(如redis等),也可能是新生成的json数据 resp = make_response() resp.headers['Content-Type'] = 'application/json' resp.cache_control.max_age = 600 #最长缓存600秒 if json_data.get('from_cache'): #来自服务端缓存 del json_data['from_cache'] last_modified = json_data.get('cache_time', 0) if last_modified: del json_data['cache_time'] resp.last_modified = datetime.fromtimestamp(last_modified) #添加Last-Moditified头 if not resp.last_modified: resp.last_modified = datetime.now() if request.if_modified_since and request.if_modified_since >= resp.last_modified: #如果是条件请求,并且缓存未过期,返回304响应 return resp, 304 resp.data = json.dumps(json_data) return resp, 200