共计 3767 个字符,预计需要花费 10 分钟才能阅读完成。
背景
好久没写文章了,寂静了大半年
持续性朝气蓬勃,间歇性癫痫发生
天天来大姨爹,在迷茫、焦虑中度过每一天
不得不抵赖,其实本人就是个废物
作为一名低级前端工程师
最近解决了一个十几年的祖传老接口
它继承了所有至尊级复杂度逻辑
传说中调用一次就能让 cpu 负载飙升 90% 的日天服务
专治各种不服与老年痴呆
咱们观赏一下这个接口的耗时
均匀调用工夫在 3s 以上
导致页面呈现重大的转菊花
通过各种深度分析与专业人士答疑
最初得出结论是:放弃医疗
鲁迅在《狂人日记》里曾说过:“能战胜我的,只有女人和酒精,而不是 bug
”
每当身处光明之时
这句话总能让我看到光
所以这次要硬起来
我决定做一个 node 代理层
用上面三个办法进行优化:
按需加载 -> graphQL
数据缓存 -> redis
轮询更新 -> schedule
代码地址:github
按需加载 -> graphQL
天秀老接口存在一个问题,咱们每次申请 1000 条数据,返回的数组中,每一条数据都有上百个字段,其实咱们前端只用到其中的 10 个字段而已。
如何从一百多个字段中,抽取任意 n 个字段,这就用到 graphQL。
graphQL 按需加载数据只须要三步:
- 定义数据池 root
- 形容数据池中数据结构 schema
- 自定义查问数据 query
定义数据池
咱们针对屌丝谋求女神的场景,定义一个数据池,如下:
// 数据池
var root = {
girls: [{
id: 1,
name: '女神一',
iphone: 12345678910,
weixin: 'xixixixi',
height: 175,
school: '剑桥大学',
wheel: [{name: '备胎 1 号', money: '24 万元'}, {name: '备胎 2 号', money: '26 万元'}]
},
{
id: 2,
name: '女神二',
iphone: 12345678910,
weixin: 'hahahahah',
height: 168,
school: '哈佛大学',
wheel: [{name: '备胎 3 号', money: '80 万元'}, {name: '备胎 4 号', money: '200 万元'}]
}]
}
外面有两个女神的所有信息,包含女神的名字、手机、微信、身高、学校、备胎汇合等信息。
接下来咱们就要对这些数据结构进行形容。
形容数据池中数据结构
const {buildSchema} = require('graphql');
// 形容数据结构 schema
var schema = buildSchema(`
type Wheel {
name: String,
age: Int
}
type Info {
id: Int
name: String
iphone: Int
weixin: String
height: Int
school: String
wheel: [Wheel]
}
type Query {girls: [Info]
}
`);
下面这段代码就是女神信息的 schema。
首先咱们用 type Query
定义了一个对女神信息的查问,外面蕴含了很多女孩 girls 的信息Info
,这些信息是一堆数组,所以是[Info]
咱们在 type Info
中形容了一个女孩的所有信息的维度,包含了名字(name)、手机(iphone)、微信(weixin)、身高(height)、学校(school)、备胎汇合(wheel)
定义查问规定
失去女神的信息形容 (schema) 后,就能够自定义获取女神的各种信息组合了。
比方我想和女神意识,只须要拿到她的名字 (name) 和微信号(weixin)。查问规定代码如下:
const {graphql} = require('graphql');
// 定义查问内容
const query = `
{
girls {
name
weixin
}
}
`;
// 查问数据
const result = await graphql(schema, query, root)
筛选后果如下:
又比方我想进一步和女神倒退,我须要拿到她备胎信息,查问一下她备胎们 (wheel) 的家产 (money) 别离是多少,剖析一下本人能不能获取优先择偶权。查问规定代码如下:
const {graphql} = require('graphql');
// 定义查问内容
const query = `
{
girls {
name
wheel {money}
}
}
`;
// 查问数据
const result = await graphql(schema, query, root)
筛选后果如下:
咱们通过女神的例子,展示了如何通过 graphQL 按需加载数据。
映射到咱们业务具体场景中,天秀接口返回的每条数据都蕴含 100 个字段,咱们配置 schema,获取其中的 10 个字段,这样就防止了剩下 90 个不必要字段的传输。
graphQL 还有另一个益处就是能够灵便配置,这个接口须要 10 个字段,另一个接口要 5 个字段,第 n 个接口须要另外 x 个字段
依照传统的做法咱们要做出 n 个接口能力满足,当初只须要一个接口配置不同 schema 就能满足所有状况了。
感悟
在生活中,咱们舔狗真的很短少 graphQL 按需加载的思维
渣男渣女,各取所需
你的真情在名媛背后不值一提
咱们要学会投其所好
上来就亮车钥匙,没有车就秀才艺
今晚我有一条祖传的染色体想与您分享一下
行就行,不行就换下一个
直奔主题,简略粗犷
缓存 -> redis
第二个优化伎俩,应用 redis 缓存
天秀老接口外部调用了另外三个老接口,而且是串行调用,极其耗时耗资源,秀到你头皮发麻
咱们用 redis 来缓存天秀接口的聚合数据,下次再调用天秀接口,间接从缓存中获取数据即可,防止高耗时的简单调用,简化后代码如下:
const redis = require("redis");
const {promisify} = require("util");
// 链接 redis 服务
const client = redis.createClient(6379, '127.0.0.1');
// promise 化 redis 办法,以便用 async/await
const getAsync = promisify(client.get).bind(client);
const setAsync = promisify(client.set).bind(client);
async function list() {
// 先获取缓存中数据,没有缓存就去拉取天秀接口
let result = await getAsync("缓存");
if (!result) {
// 拉接口
const data = await 天秀接口();
result = data;
// 设置缓存数据
await setAsync("缓存", data)
}
return result;
}
list();
先通过 getAsync
来读取 redis 缓存中的数据,如果有数据,间接返回,绕过接口调用,如果没有数据,就会调用天秀接口,而后 setAsync
更新到缓存中,以便下次调用。因为 redis 存储的是字符串,所以在设置缓存的时候,须要加上JSON.stringify(data)
,为了便于大家了解,我就不加了,会把具体细节代码放在 github 中。
将数据放在 redis 缓存里有几个益处
能够实现多接口复用、多机共享缓存
这就是传说中的 云备胎
谋求一个女神的成功率是 1%
同时谋求 100 个女神,那你获取到一个女神的概率就是 100%
鲁迅《狂人日记》里曾说过:“舔一个是舔狗,舔一百个你就是战狼
”
你是想当舔狗还是当战狼?
来吧,缓存用起来,redis 用起来
轮询更新 -> schedule
最初一个优化伎俩:轮询更新 -> schedule
女神的备胎用久了,会定时换一批备胎,让新鲜血液进来,发现新的高兴
缓存也一样,须要定时更新,放弃与数据源的一致性,代码如下:
const schedule = require('node-schedule');
// 每个小时更新一次缓存
schedule.scheduleJob('* * 0 * * *', async () => {const data = await 天秀接口();
// 设置 redis 缓存数据
await setAsync("缓存", data)
});
咱们用 node-schedule
这个库来轮询更新缓存,* * 0 * * *
这个的意思就是设置每个小时的第 0 分钟就开始执行缓存更新逻辑,将获取到的数据更新到缓存中,这样其余接口和机器在调用缓存的时候,就能获取到最新数据,这就是共享缓存和轮询更新的益处。
早年我在当舔狗的时候,就将轮询机制施展到酣畅淋漓
每天向白名单里的女神,定时轮询发消息
有限循环 云跪舔
三件套:
- “啊宝贝,最近有没有想我”
- “啊宝贝早安安”
- “宝贝晚安,么么哒”
尽管女神仍然看不上我
但依然时刻筹备着为女神服务!
结尾
通过以上三个办法优化后
接口申请耗时从 3s 降到了 860ms
这些代码都是在业务中由繁化简后抽离出的逻辑
实在的业务场景远比这要简单:分段式数据存储、主从同步 读写拆散、高并发同步策略等等
每一个模块都艰涩难懂
就如同每一个女神都遥不可及
屌丝战败了所有 bug,唯独战败不了她的心
受伤了只能在深夜里单独买醉
但每当梦到女神关上我做的页面
被极致晦涩的体验惊艳到
在精力低潮中享受灵魂升华
那一刻
我感觉我又行了
(完)
代码地址:github
FFCreator 是咱们团队做的一个轻量、灵便的短视频加工库。您只须要增加几张图片或文字,就能够疾速生成一个相似抖音的酷炫短视频。github 地址:https://github.com/tnfe/FFCreator 欢送小伙伴 star。