使用Flask-Caching扩展为Flask web程序页面做缓存,用以缩短同一页面的加载时间。缓存后端使用Redis服务。
当使用缓存时,用户第一次访问某一页面服务器会执行视图函数中的数据库查询、函数计算、模板渲染等工作,并将渲染后的页面数据以键值对的形式存储在Redis中,对于视图函数默认的键格式为view/<request.path>
。当用户再次访问同一个页面时,服务器将会直接将Redis中保存的页面数据值返回给客户端,而不必再次执行视图函数中的代码,从而缩短页面加载时间,提升用户体验。
页面缓存适用于用户需要经常访问、包含大量数据库查询或函数计算,但是数据却不经常变动的页面。因为数据即使变动了,在不清除就缓存且缓存未到期的情况下,用户只能看到旧的页面数据。
windows开发环境:
Redis服务部署在Ubuntu18.04虚拟机中,版本为6.2.6。服务器IP为192.168.73.130
Flask-Caching扩展为Flask web程序提供了便捷的缓存支持,开发者只需要实例化Cache类
后,为视图函数附加对应的装饰器,就也可以方便的为视图函数添加缓存支持。常用的装饰器有:
view/request.path
,可以自行指定Flask-Caching连接Redis服务,需要借助python的redis-py包,所以使用前先要安装pip install redis
.
在环境变量中设置redis服务器对应的信息:
CACHE_REDIS_HOST = '192.168.73.130'
CACHE_REDIS_PORT = '6379'
CACHE_REDIS_PASSWORD = 'your password'
CACHE_REDIS_DB = '0'
为了方便,也可以直接使用redis连接的URL:
CACHE_REDIS_URL = 'redis://:<your password>@192.168.73.130:6379/0'
最后的0表示使用redis的0号数据库保存数据(redis默认有16个数据库0-15)
import os
import time
from flask import Flask, render_template, url_for, redirect, request
from flask_caching import Cache
from flask_debugtoolbar import DebugToolbarExtension
app = Flask(__name__)
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev#secret_key')
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
# redis cache backend
cache = Cache(app, config={'CACHE_TYPE': 'RedisCache', 'CACHE_REDIS_URL': os.getenv('CACHE_REDIS_URL')})
toolbar = DebugToolbarExtension(app)
# views
@app.route('/')
def index():
return render_template('index.html')
@app.route('/foo')
def foo():
"""不使用缓存"""
time.sleep(1)
return render_template('foo.html')
@app.route('/bar')
@cache.cached(timeout=10 * 60)
def bar():
time.sleep(1)
return render_template('bar.html')
@app.route('/baz')
@cache.cached(timeout=60 * 60)
def baz():
time.sleep(1)
return render_template('baz.html')
@app.route('/qux')
@cache.cached(query_string=True)
def qux():
time.sleep(1)
page = request.args.get('page', 1, type=int)
return render_template('qux.html', page=page)
启动程序,访问使用缓存的页面,在重载后通过DebugToolbar查看加载时间可以发现时间明显缩短。
@app.route('/update/bar')
def update_bar():
"""为bar端点清除缓存"""
cache.delete('view/%s' % url_for('bar'))
flash('Cached data for bar have been deleted.')
return redirect(url_for('index'))
@app.route('/update/baz')
def update_baz():
cache.delete('view/%s' % url_for('baz'))
flash('Cached data for baz have been deleted.')
return redirect(url_for('index'))
@app.route('/update/all')
def update_all():
"""清除所有缓存"""
cache.clear()
flash('All cached data deleted.')
return redirect(url_for('index'))
连接redis数据库时,程序报错Redis运行在保护模式。
Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the lookback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the --portected-mode no option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.
在提示信息中,已经告诉了我们如何解决这个问题,如果是单纯地进行测试,可以直接将保护模式关闭,然后重启服务即可。
如果想更安全一点,可以先使用redis-cli客户端进入服务,使用config set requirepass <password>
命令为redis设置密码;然后将配置文件/etc/redis/redis.conf
中的protected-mode
设为yes,同时将bind
选项配置为redis服务器的网卡地址(这里是192.168.73.130),然后重启服务systemctl restart redis-server
。
之后使用redis-cli时先使用auth <password>
命令登录;使用url连接时,使用redis://:<password>@ip:port/<database>
进行连接。
《Python Web开发实战:入门、进阶与原理解析》 李辉