1. 程式人生 > >python——Web服務開發(二)分散式快取

python——Web服務開發(二)分散式快取

上一篇部落格寫了flask模組實現web服務搭建的基本方法以及簡單的快取功能,但是這種快取隨著服務重啟便會丟失,也無法滿足多個服務共享快取的需求,因此,我們通過redis來實現web服務的分散式快取。

import redis
client = redis.StrictRedis(host="***",port="***")
cache = Cache(client)

以斐波那契數為例:[fn=f(n-1)+f(n-2)]

我們通過遞迴構造快取方法如下:

def get_fib(self, n): 
        if n == 0:
            return 0, True
        if n == 1:
            return 1, True
        result = cache.get_fib(n)
        if result:
            return result, True
        result = 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 = cache

    def get(self, n):
  	……
    def post(self, n):
	……

2.flask-classy

flask預設的MethodView無法在一個類裡提供多個不同URL名稱的API服務。所以接下來我們引入flask的擴充套件flask-classy來解決這個問題。

pip install flask-classy

完整程式碼:

import math
import redis

from flask import Flask
from flask.json import jsonify
from flask_classy import FlaskView, route  

app = Flask(__name__)

# pi的cache和fib的cache要分開
class Cache(object):
    
    def __init__(self, client):
        self.client = client

    def 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:
            return
        return 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:
            return
        return 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, True
        if n == 1:
            return 1, True
        result = cache.get_fib(n)
        if result:
            return result, True
        result = 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.0
        for i in range(1, n):
            s += 1.0/i/i
        result = 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)