关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。

关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

大早上被叫醒!

前几天周末,大早上的时候,太阳才刚出来,我突然被老大电话叫醒了,并通知我速速进入飞书会议,说是服务器发生了警报,出现了严重事故。

关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

进到会议才发现是我们的后端有一个接口,让监控直接红色了。由于这一块代码我比较熟,所以老大让我紧急定位并处理一下这个严重的问题~

定位问题

所以本全干工程师就开始了后端接口的问题定位~

关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

初步定位

首先说说这个接口的背景,这个接口是提供给用户用作导入用的,用户在做导入的时候,有可能导入的数据超级大,所以会不会是因为导入的数据量太大了,所以导致此接口直接崩掉呢?

但是老大查了日志后跟我说,这个用户在以前也导入过这么大的数据量,但是那时候都没啥问题的啊~

所以我觉得这应该不是用户行为造成的,而是什么新功能造成的这个BUG~于是我看了涉及到此接口的最近的提交,发现确实是有一个新功能在最近上线了,是涉及到 json-schema 的

简单认识 json-schema

什么是 json-schema 呢?给大家举个小例子,让大家简单认识一下吧,比如下方的三个属性

  • name
  • age
  • cars

他们都有对应的数据类型,他们需要通过 json-schema 来寻找到自己对应的类型

// jsonschema
const schema = {
  name: {
    $ref: 1
  },
  age: {
    $ref: 2
  },
  cars: {
    $ref: 3
  }
}

// jsonschema合集
const schemaDefination = {
  1: {
    type: 'string'
  },
  2: {
    type: 'number'
  },
  3: {
    $ref: 4
  },
  4: {
    type: 'array'
  }
}

// 得出结果
const result = build(schema, schemaDefination)
console.log(result)
// {
//   name: 'string',
//   age: 'number',
//   cars: 'array'
// }

继续定位问题

回到这个 BUG 上,我继续定位。其实刚刚上面的例子是很简单的例子,但是其实在这个功能里,数据量和负责度远远没这么简单,我们刚刚看到的 schemaDefination 其实就是所有 jsonschema 的引用的结合

// 实际上可能有几百个
const schema1 = {
  $ref: 1
}
const schema2 = {
  $ref: 2
}
const schema3 = {
  $ref: 3
}

const schemaDefination = gen(schema1, schema2, schema3)
console.log(schemaDefination)
// 实际上可能有几百个
// {
//   1: {
//     type: 'string'
//   },
//   2: {
//     type: 'number'
//   },
//   3: {
//     type: 'array'
//   }
// }

也就是一开始会先根据所有 schema 去生成一个引用的集合 schemaDefination,而这个集合可能有几百个,数据量挺大

最终定位

然后到最终的时候 schema 结合 schemaDefination 去生成结果,我感觉就是在这一步导致了 BUG

// 得出结果
// 可能要 build 几百次
const result1 = build(schema1, schemaDefination)
const result2 = build(schema2, schemaDefination)
const result3 = build(schema3, schemaDefination)

为什么我觉得是这一步出问题呢?我们刚刚说了 schemaDefination 是所有 schema 的引用集合,数据量很大,你每次 build 的时候 schema 传的是一个 schema,但是你 schemaDefination 传的是集合!!!

正常来说应该是传 schema 时只需要传对应的 schemaDefination 即可,比如

// 合理的
const result1 = build({
  $ref: 1
}, {
  1: {
    type: 'string'
  }
})

// 不合理的
const result1 = build({
  $ref: 1
}, {
  1: {
    type: 'string'
  },
  2: {
    type: 'number'
  },
  3: {
    type: 'array'
  }
})

而我们现在就是处于不合理的情况,于是我特地看了 build 这个函数的内部实现,发现有 对象序列化处理 的代码,想一下下面的模拟代码

const obj = { 几百个数据 }
while(i < 300) {
  JSON.stringfy(obj)
  i++
}

这样的代码会给服务器造成非常大的压力,甚至把接口给搞崩!!!

解决问题,性能提升几百倍!

上面其实我已经分析出问题所在了:传 schema 的时候不要传整个 Defination集合!,所以我们只需要传入所需的 defination, 那么性能是不是可以优化几百倍!!!

解决手段

所以我们只需要写一个函数,过滤出所需要的 defination 即可,例如

// 找出所有被 ref 的数据模型
const filter = (
  schema,
  schemaDefinitions,
) => {
  // 进行过滤操作
}

// jsonschema
const schema = {
  name: {
    $ref: 1
  }
}

// jsonschema合集
const schemaDefination = {
  1: {
    type: 'string'
  },
  2: {
    type: 'number'
  },
  3: {
    $ref: 4
  },
  4: {
    type: 'array'
  }
}

// 过滤
const defination = filter(schema, schemaDefination)
console.log(defination)
//{
//  1: {
//    type: 'string'
//  },
//}

所以只需要在 build 的时候传入过滤后的 defination 即可!

const result1 = build(schema1, filter(schema1, schemaDefination))
const result2 = build(schema2, filter(schema2, schemaDefination))
const result3 = build(schema3, filter(schema3, schemaDefination))

测试无误,继续睡觉!

然后拿到一份用户的数据,在测试环境测了一下,没有发生之前那个 BUG 了!合并代码!打包上线!继续睡觉!

关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

结语 & 加学习群 & 摸鱼群

我是林三心

  • 一个待过小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司的作死型前端选手;
  • 一个偏前端的全干工程师;
  • 一个不正经的掘金作者;
  • 一个逗比的B站up主;
  • 一个不帅的小红书博主;
  • 一个喜欢打铁的篮球菜鸟;
  • 一个喜欢历史的乏味少年;
  • 一个喜欢rap的五音不全弱鸡

如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 –> 摸鱼沸点

关于“凌晨服务器告警!我被动把性能优化了2000%”这件事~

原文链接:https://juejin.cn/post/7238973821801594935 作者:Sunshine_Lin

(0)
上一篇 2023年5月30日 上午11:14
下一篇 2023年5月31日 上午10:05

相关推荐

发表评论

登录后才能评论