? ? ? ?环境:win/linux下 Python3+Tornado 6
? ? ? ?阅读本文需要技术:Redis
? ? ? ?难度: ?
????????长期以来,tornado框架的使用者多数是做的前后端分离,完全没有html模板热更新的需要。但是如果遇到条件限制,只能单机运行且单机性能不佳的情况下,就被迫不能做前后端分离了。
? ? ? ? 一般情况下,我们在tornado框架的web程序中修改完了html文件后(内容修改),需要重启web程序来让修改生效。这样是十分低效且繁琐的,特别是生产环境需要临时变更,业务重启的那几秒都可能造成不小的损失,给用户带来不好的体验。
? ? ? ? 于是,我翻阅了tornado官方文档中,和模板系统相关的文档。文档中对于tornado的模板系统的加载器是这样描述的
如图所示,加载器会在模板首次加载后进行缓存,这样做可以提高性能和响应速度。
????????既然是叫“缓存”那么就一定会有办法可以刷新或者清空这个缓存,这下事情就好办了,继续阅读文档就可以发现reset()方法
????????文档中的描述就是使用reset()可以重置缓存,之后我去?tornado.web.RequestHandler这个类(也就是我们使用过程中继承的类)里面查找reset()用法,发现了意外的东西。
????????如图所示,?RequestHandler类的execute方法内使用了reset(),但是我并不打算去研究这个execute方法是如何触发的,图中红框可以看到,它直接对RequestHandler类下的模板加载器进行了操作,取出的loader(加载器)中可以调用到reset方法。
? ? ? ? 而我们使用tornado框架编写响应类时,也会继承RequestHandler类,于是乎,我们在自己的t代码中应该也可以直接调用到reset(),我们不妨尝试一下
class UserLogin(tornado.web.RequestHandler):
# 用户登录页面(你自己的业务代码)
def get(self):
...
for loader in self._template_loaders.values():
print(loader.namespace)
loader.reset()
...
????????在您的get或post方法内添加以上get方法内代码后启动程序,查看页面,在不关闭web程序的情况下修改html文件并保存,再次查看页面。不出意外的话您会和我一样,看到页面上发生了变化。
? ? ? ? 通过简单的测试,我们发现这个方法是可行的,那么我们接下来需要做的就是根据具体业务需求和场景,设置不同的热更条件,我这里基于Redis实现了一个简单的文件修改后热更新逻辑,在普通业务量的系统中应该是够用的了。
class user_login(tornado.web.RequestHandler):
# 用户登录页面
def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
pass
def get(self):
...
# //模板热更新[开始]//
# 官方技术参考1:https://tornado-zh.readthedocs.io/zh/latest/template.html#tornado.template.BaseLoader.reset
# 官方技术参考2:https://tornado-zh.readthedocs.io/zh/latest/_modules/tornado/template.html#BaseLoader.reset
# 该写法存在性能问题,因为每次请求页面都会去读取文件获取文件的修改时间,仅在部分页面实验性的使用,业务量大的请自行优化
templates_name = 'qijian_login'
t_time = MainRedis.get(f'template_file_{templates_name}')
# MainRedis为一个实例化并且建立好连接的redis实例MainRedis = redis.Redis(host=redis_config['host'], port=redis_config['port'], decode_responses=True)
if t_time is None:
t_time = '0'
n_time = str(os.path.getmtime(f'templates/{templates_name}.html'))
if t_time != n_time:
print("模板热更新")
# print(t_time)
# print(n_time)
# 下方代码会将加载器内所有的模板缓存进行更新
for loader in self._template_loaders.values():
print(loader.namespace)
loader.reset()
MainRedis.setex(f'template_file_{templates_name}', 86400, n_time) # 缓存24小时
# //模板热更新[结束]//
? ? ? ? 上面的代码较为基础,实际使用过程中还请根据自己的实际业务需求进行修改.
? ? ? ? 文章如有遗漏或错误的地方还望指正,最后,希望各位可以给我点一点大拇指并关注。
|