缓存响应插件
缓存插件能根据不同的请求参数来缓存除流式响应以外的任意响应对象。它的使用方法如下:
docs_source_code/docs_source_code/plugin/cache_plugin/flask_with_cache_plugin_demo.py |
---|
| import time
from flask import Flask, Response, make_response
from redis import Redis # type: ignore
from pait.app.flask import pait
from pait.app.flask.plugin.cache_response import CacheRespExtraParam, CacheResponsePlugin
from pait.field import Query
from pait.model.response import HtmlResponseModel
@pait(
response_model_list=[HtmlResponseModel],
post_plugin_list=[CacheResponsePlugin.build(cache_time=10, enable_cache_name_merge_param=True)],
)
def demo(key1: str = Query.i(extra_param_list=[CacheRespExtraParam()]), key2: str = Query.i()) -> Response:
return make_response(str(time.time()), 200)
app = Flask("demo")
CacheResponsePlugin.set_redis_to_app(app, Redis(decode_responses=True))
app.add_url_rule("/api/demo", view_func=demo, methods=["GET"])
if __name__ == "__main__":
app.run(port=8000)
|
docs_source_code/docs_source_code/plugin/cache_plugin/starlette_with_cache_plugin_demo.py |
---|
| import time
from typing import Any
from redis.asyncio import Redis # type: ignore
from starlette.applications import Starlette
from starlette.responses import HTMLResponse
from pait.app.starlette import pait
from pait.app.starlette.plugin.cache_response import CacheRespExtraParam, CacheResponsePlugin
from pait.field import Query
from pait.model.response import HtmlResponseModel
@pait(
response_model_list=[HtmlResponseModel],
post_plugin_list=[CacheResponsePlugin.build(cache_time=10, enable_cache_name_merge_param=True)],
)
async def demo(key1: str = Query.i(extra_param_list=[CacheRespExtraParam()]), key2: str = Query.i()) -> HTMLResponse:
return HTMLResponse(str(time.time()), 200)
app = Starlette()
app.add_route("/api/demo", demo, methods=["GET"])
def before_start(*args: Any, **kwargs: Any) -> None:
CacheResponsePlugin.set_redis_to_app(app, Redis(decode_responses=True))
app.add_event_handler("startup", before_start)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app)
|
docs_source_code/docs_source_code/plugin/cache_plugin/sanic_with_cache_plugin_demo.py |
---|
| import time
from typing import Any
from redis.asyncio import Redis # type: ignore
from sanic import Sanic, response
from pait.app.sanic import pait
from pait.app.sanic.plugin.cache_response import CacheRespExtraParam, CacheResponsePlugin
from pait.field import Query
from pait.model.response import HtmlResponseModel
@pait(
response_model_list=[HtmlResponseModel],
post_plugin_list=[CacheResponsePlugin.build(cache_time=10, enable_cache_name_merge_param=True)],
)
async def demo(
key1: str = Query.i(extra_param_list=[CacheRespExtraParam()]), key2: str = Query.i()
) -> response.HTTPResponse:
return response.html(str(time.time()), 200)
app = Sanic("demo")
app.add_route(demo, "/api/demo", methods=["GET"])
def before_start(*args: Any, **kwargs: Any) -> None:
CacheResponsePlugin.set_redis_to_app(app, Redis(decode_responses=True))
app.before_server_start(before_start)
if __name__ == "__main__":
app.run(port=8000)
|
docs_source_code/docs_source_code/plugin/cache_plugin/tornado_with_cache_plugin_demo.py |
---|
| import time
from redis.asyncio import Redis # type: ignore
from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler
from pait.app.tornado import pait
from pait.app.tornado.plugin.cache_response import CacheRespExtraParam, CacheResponsePlugin
from pait.field import Query
from pait.model.response import HtmlResponseModel
class DemoHandler(RequestHandler):
@pait(
response_model_list=[HtmlResponseModel],
post_plugin_list=[CacheResponsePlugin.build(cache_time=10, enable_cache_name_merge_param=True)],
)
async def get(self, key1: str = Query.i(extra_param_list=[CacheRespExtraParam()]), key2: str = Query.i()) -> None:
self.write(str(time.time()))
app: Application = Application([(r"/api/demo", DemoHandler)])
CacheResponsePlugin.set_redis_to_app(app, Redis(decode_responses=True))
if __name__ == "__main__":
app.listen(8000)
IOLoop.instance().start()
|
代码中的路由函数使用了CachePlugin
,声明了缓存时间为10秒,且缓存名采纳了请求参数的功能。
同时,路由函数中只有key1
参数使用了CacheRespExtraParam
拓展参数,这样一来CachePlugin
只会采纳使用了CacheRespExtraParam
的参数,而不是所有参数。
在运行代码后,执行curl
命令,可以发现请求参数一样时,路由函数返回的内容是一致的:
curl http://127.0.0.1:8000/api/demo\?key1\=1\&key2\=11695627610.021101curl http://127.0.0.1:8000/api/demo\?key1\=1\&key2\=11695627610.021101curl http://127.0.0.1:8000/api/demo\?key1\=2\&key2\=11695627613.0265439
除了cache_time
和enable_cache_name_merge_param
参数外,CachePlugin
还支持其他参数,具体说明如下:
- redis: 指定缓存插件使用的Redis实例,建议通过
CacheResponsePlugin.set_redis_to_app
方法指定Redis实例。
- name: 指定路由函数的缓存Key,如果该值为空,则缓存Key为路由函数名。
- enable_cache_name_merge_param: 如果为True,缓存的Key的构造会包括其他参数值,比如下面的路由函数:
from pait.app.any import pait
from pait.plugin.cache_response import CacheResponsePlugin
from pait.field import Query
@pait(post_plugin_list=[CacheResponsePlugin.build(cache_time=10)])
async def demo(uid: str = Query.i(), name: str = Query.i()) -> None:
pass
当请求的url携带?uid=10086&name=so1n
时,缓存插件生成的缓存Key为demo:10086:so1n
。
但是如果参数uid
使用了CacheRespExtraParam
拓展参数,那么缓存的Key只会包括使用了CacheRespExtraParam
拓展参数的参数值,比如下面的路由函数:
from pait.app.any import pait
from pait.plugin.cache_response import CacheResponsePlugin, CacheRespExtraParam
from pait.field import Query
@pait(post_plugin_list=[CacheResponsePlugin.build(cache_time=10)])
async def demo(uid: str = Query.i(extra_param_list=[CacheRespExtraParam()]), name: str = Query.i()) -> None:
pass
当请求的url中携带?uid=10086&name=so1n
时,缓存插件会认为当前的缓存Key为demo:10086
。
- include_exc: 接收一个可以异常的Tuple,如果路由函数抛出的错误属于Tuple中的一种错误,则会缓存该异常,否则会抛出异常。
- cache_time: 缓存的时间,单位秒。
- timeout: 为了防止高并发场景下的缓存冲突,缓存插件里通过
Reids
锁来防止资源竞争。timeout代表该锁的最长持有时间。
- sleep: 当发现锁被另一个请求持有时,当前请求会休眠指定的时间后再尝试获取锁,如此循环直到获取到对应的锁或者超时。
- blocking_timeout: 指尝试获取锁的最长时间,如果为None,则会一直等待。