大家好~我是米洛

我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持。

欢迎关注我的公众号测试开发坑货,获取最新文章教程!

回顾

上一节我们让支持了前置条件复制功能。这一节本来打算给大家讲讲邮件的发送。

但在此之前,我想了一个很严重的问题。

配置

我们的测试平台,后续会接入yapi,接入其他系统。势必会有一个地方去维护这些数据。

包括发件人邮箱,密码等等数据。

但这些数据又通常是全局共享,如果放到db的话,很鸡肋,因为数据只有1条,如果放到redis,有可能数据会丢。

博主也不知道放哪里比较好,最后决定放到一个configuration.json的配置文件里面了。

但是频繁读取文件,总归是不好的。而且我们线上会有许多个worker,还可能会有冲突

想到我们之前拿捏过的redis,这不正是它的用武之地吗?

编写通用cache方法

在此之前,我们先思考一下为啥要写这样的通用缓存办法:

我们获取数据,有2部分,分别为get和set。结合缓存来看,我们可以写出这样的伪代码:

def get_cache():
data = redis.get(key)
if data is not None:
return data
data = get_data()
redis.set(key, data)
return data

就是这么简单的用法,如果key获取到了,我们直接return,如果没获取到,我们更新数据,并把数据写入redis,最后返回data。

那我们修改数据的时候怎么做呢?

def update_cache():
update(data)
redis.delete(key)
  1. 先更新数据源
  2. 删除缓存数据,这样下去获取缓存的时候就会重新获取数据并写入缓存

但大家有没有觉得这个过程很繁琐,而且属于get和set之外的操作,每每有这种操作的时候,我们就可以把它装饰器化。

编写cache装饰器

  • 连接本地redis的方法

    首先我们在config.py配置好redis的连接信息,接着编写client客户端,因为它本身是连接池模式,所以我们一直用这个客户端都没问题。(所以我这里把它设置为了property)

  • 编写RedisHelper

    helper类含有2个装饰器,cache负责读取(get),up_cache负责更新(set)。

class RedisHelper(object):
pity_prefix = "pity"
pity_redis_client = PityRedisManager().client @staticmethod
def get_key(key: str):
return f"{RedisHelper.pity_prefix}:{key}" @staticmethod
def cache(key: str, expired_time=3 * 60):
"""
自动缓存装饰器
:param key: 被缓存的key
:param expired_time: 默认key过期时间
:return:
""" def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
redis_key = RedisHelper.get_key(key)
data = RedisHelper.pity_redis_client.get(redis_key)
# 缓存已存在
if data is not None:
return json.loads(data)
# 获取最新数据
new_data = func(*args, **kwargs)
info = json.dumps(new_data)
RedisHelper.pity_redis_client.set(redis_key, info, ex=expired_time)
return new_data return wrapper return decorator @staticmethod
def up_cache(key: str):
"""
redis缓存key,套了此方法,会自动执行更新数据操作后删除缓存
:param key:
:return:
""" def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
redis_key = RedisHelper.get_key(key)
# 获取最新数据
new_data = func(*args, **kwargs)
# 更新数据,删除缓存
RedisHelper.pity_redis_client.delete(redis_key)
return new_data return wrapper return decorator

这里我们基本上按照之前说的逻辑来做的,以后我们取数据的方法,只需要在方法前面+上cache装饰器,即可自动跟redis打通。(有缓存则取缓存数据,无则取真实数据)

编写配置文件获取方法

我们编写configuration.json到根目录:

import json
import os from app.middleware.RedisManager import RedisHelper
from config import Config class SystemConfiguration(object):
"""
系统配置
""" @staticmethod
@RedisHelper.cache("configuration", 24 * 3600)
def get_config():
try:
filepath = os.path.join(Config.ROOT, "configuration.json")
if not os.path.exists(filepath):
raise Exception("没找到配置文件,请检查configuration文件是否已经被删除")
with open(filepath, mode="r", encoding='utf-8') as f:
return json.load(f)
except Exception as e:
raise Exception(f"获取系统设置失败, {e}") @staticmethod
@RedisHelper.up_cache("configuration")
def update_config(config):
try:
filepath = os.path.join(Config.ROOT, "configuration.json")
if not os.path.exists(filepath):
raise Exception("没找到配置文件,请检查configuration文件是否已经被删除")
with open(filepath, mode="r", encoding='utf-8') as f:
json.dump(config, f)
except Exception as e:
raise Exception(f"更新系统设置失败, {e}")

由于配置文件一般很少更新,所以我们把key的过期时间设为了1天(其实可以更久一点)。

这样,我们调用get_config就可以拿到系统设置啦,里面有咱们很重要的发件人信息。

测试一下

启动程序以后,我们去查询redis中关于configuration的key,就用咱们自己写的客户端:

再测试下过期时间:

今天的内容就到这里,下节正式开启发邮件(报告通知)之旅。

测试平台系列(85) 把redis运用到实战中的更多相关文章

  1. 测试平台系列(79) 编写Redis配置功能(下)

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们提出了优化Dao ...

  2. 测试平台系列(80) 封装Redis客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...

  3. 测试平台系列(81) 编写在线执行Redis功能

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们牛刀小试,编写了 ...

  4. 测试平台系列(83) 前置条件支持Redis语句

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上节我们打了个野,解决了一 ...

  5. 测试平台系列(72) 了解ApScheduler基本用法

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们调研了一下市面上 ...

  6. 测试平台系列(82) 解决APScheduler重复执行的问题

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了在线执行R ...

  7. 测试平台系列(95) 前置条件支持简单的python脚本

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们构思了一下怎么去支 ...

  8. 测试平台系列(55) 引入AceEditor(代码编辑器)

    大家好,我是米洛,求三连!求关注测试开发坑货! 回顾 我们上一节已经写好了左侧数据表目录,今天继续完成sql编辑器的部分. 调研组件 monaco 因为我们的项目用的是React,市面上很多编辑器都是 ...

  9. 测试平台系列(71) Python定时任务方案

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 定时任务 定时任务,顾名思义: ...

随机推荐

  1. 二、Ansible基础之模块篇

    目录 1. Ansible Ad-Hoc 命令 1.1 命令格式 1.2 模块类型 1.3 联机帮助 1.3.1 常用帮助参数 1.4 常用模块 1.4.1 command & shell 模 ...

  2. I-Base62

    I - Base62 PS:一个任意进制转换的大数问题 传送门:Base62 短除法原理: 20(10进制) => 202(3进制) 20 = (2 * 3 ^ 2 + 0 * 3 ^ 1 + ...

  3. 【UE4 C++】 UnrealPak 与 Pak 的制作、挂载、加载

    简介 通过 UnrealPak,可以将资源打包成 Pak 文件 Pak文件是UE4游戏生成的数据包文件. Pak 之前一般先有 Cooked 步骤,将资源烘焙为对应平台支持的资源 一般打包后的项目使用 ...

  4. 【c++ Prime 学习笔记】第2章 变量和基本类型

    2.1 基本内置类型 基本数据类型包含了算术类型(arithmetic type)和空类型(void) 算数类型,包含了字符.整型数.布尔值和浮点数 空类型,不对应具体的值 2.1.1 算术类型 算术 ...

  5. [Git系列] 前言

    Git 简介 Git 是一个重视速度的分布式版本控制和代码管理系统,最初是由 Linus Torvalds 为开发 Linux 内核而设计并开发的,是一款遵循二代 GUN 协议的免费软件.这一教程会向 ...

  6. [敏捷软工团队博客]Beta阶段事后分析

    设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件要解决的问题是:现在的软工课程的作业分布在博客园.GitHub上,没有一个集成多种功能的一体化 ...

  7. [敏捷软工团队博客]The Agiles 团队介绍&团队采访

    项目 内容 课程:北航-2020-春-敏捷软工 博客园班级博客 作业要求 团队作业-团队介绍和采访 团队名称来源 The Agile is The Agile. 敏捷就是敏捷.我们只是敏捷的践行者罢了 ...

  8. Linux中检查字符串是否为合法IP地址的shell脚本

    #!/bin/bash #判断IP地址是否为有效IP CHKECK_IP () { CHECK_STEP1=`echo $1 | awk -F"." '{print NF}'` i ...

  9. Linux 文本三剑客之 sed

    Linux 系统中一切皆文件. 文件是个文本.可以读.可以写,如果是二进制文件,还能执行. 在使用Linux的时候,大都是要和各式各样文件打交道.熟悉文本的读取.编辑.筛选就是linux系统管理员的必 ...

  10. 你们不要再吵了! Java只有值传递..

    写在前边 上次聊到Java8新特性 lambda时,有小伙伴在评论区提及到了lambda对于局部变量的引用,补充着博客的时候,知识点一发散就有了这篇对于值传递还是引用传递的思考.关于这个问题为何会有如 ...