上一篇博客写了flask模块实现web服务搭建的基本方法以及简单的缓存功能,但是这种缓存随着服务重启便会丢失,也无法满足多个服务共享缓存的需求,因此,我们通过redis来实现web服务的分布式缓存。
import redisclient = redis.StrictRedis(host="***",port="***")cache = Cache(client)
以斐波那契数为例:[fn=f(n-1)+f(n-2)]
我们通过递归构造缓存方法如下:
def get_fib(self, n): if n == 0:return 0, Trueif n == 1:return 1, Trueresult = cache.get_fib(n)if result:return result, Trueresult = self.get_fib(n-1)[0] + self.get_fib(n-2)[0]cache.set_fib(n, result)return result, False
即:如果服务器处理过n,则n以下的结果再以后的调用中皆可以直接返回缓存答案。
第一次求fib(213) cached为false 服务器首次计算
第二次求fib(200) chaend为true 服务器通过缓存直接获取答案
重启服务器进程或其他服务端口不影响缓存提取
API服务扩展
1.MethodView
把参数直接注入到MethodView的构造器中,不再使用request.args,而是将参数直接放进URL里面
app.add_url_rule('/fib/<int:n>', view_func=MathAPI.as_view('fib', cache))class MathAPI(FlaskView):def __init__(self, cache):self.cache = cachedef get(self, n): ……def post(self, n): ……
2.flask-classy
flask默认的MethodView无法在一个类里提供多个不同URL名称的API服务。所以接下来我们引入flask的扩展flask-classy来解决这个问题。
pip install flask-classy
完整代码:
import mathimport redisfrom flask import Flaskfrom flask.json import jsonifyfrom flask_classy import FlaskView, routeapp = Flask(__name__)# pi的cache和fib的cache要分开class Cache(object):def __init__(self, client):self.client = clientdef set_fib(self, n, result):self.client.hset("fibs", str(n), str(result))def get_fib(self, n):result = self.client.hget("fibs", str(n))if not result:returnreturn int(result)def set_pi(self, n, result):self.client.hset("pis", str(n), str(result))def get_pi(self, n):result = self.client.hget("pis", str(n))if not result:returnreturn float(result)client = redis.StrictRedis(host="*",port="*")cache = Cache(client)class MathAPI(FlaskView): @route("/fib/<int:n>")def fib(self, n):result, cached = self.get_fib(n)return jsonify({"cached": cached, "result": result})def get_fib(self, n): if n == 0:return 0, Trueif n == 1:return 1, Trueresult = cache.get_fib(n)if result:return result, Trueresult = self.get_fib(n-1)[0] + self.get_fib(n-2)[0]cache.set_fib(n, result)return result, False @route("/pi/<int:n>")def pi(self, n):#正整数的平方倒数之和求PI n为精度级数result = cache.get_pi(n)if result:return jsonify({"cached": True, "result": result})s = 0.0for i in range(1, n):s += 1.0/i/iresult = math.sqrt(6*s)cache.set_pi(n, result)return jsonify({"cached": False, "result": result})MathAPI.register(app, route_base='/')if __name__ == '__main__':app.run('127.0.0.1', 5000)