记C#优化接口速度过程

前提摘要

首先这个项目是接手的前一任先写的项目,接手后,要求对项目一些速度相对较慢的接口进行优化,到第一个速度比较慢的接口后,发现单接口耗时4-8秒,是的,请求同一个接口,在参数不变的情况下,会出现浮动的时长 ,这种,之前我在其他项目里面也遇到过,第一种是因为有其他用户在操作其他比较卡的接口时,或者导出报表时,造成接口卡顿的拥堵 ,这种情况没有办法去排查,只能一一把接口优化好,速度才能提上来**,第二种想到的是检测服务,如果服务跑的时候间隔时间较短**,然后又有大量的查询之类的,可能也会造成整体性能的低下,这种可以排查,检查服务确实有一分钟跑一次的服务,但是,查询不大,按理来说,应该痛点不是在这里

随后对该接口进行优化,首先是对数据库查询类的代码进行优化,将查询语句一一挑出来,之后再放到数据库中去排查查询速度比较慢的查询,但是未发现查询比较慢的查询,于是就只能先把缺掉的索引先补上,在检查数据库查询类的代码的时候,发现这个接口存在多次连接数据库查询数据,大概有20-30次,很明显是个隐患,这个地方肯定会有拖累速度,考虑到重写的话,首先是不熟悉业务流程,第二是可能需要花费大量时间,所以还是争取在不改变原来的逻辑下,去给接口进行优化,所以查询多次的问题就先放一放了,随后我给重点查询的地方添加上了计时,想通过此方法来找出耗时比较明显的查询再针对性的去进行优化

csharp 复制代码
Stopwatch watch = new Stopwatch();
watch.Start();
//代码
watch.Stop();
//获取检测时长1
watch.ElapsedMilliseconds
watch.Start();
//代码
watch.Stop();
//获取检测时长2
watch.ElapsedMilliseconds

通过Stopwatch很快就发现

整个检测时间下来,整个接口跑完,都不到200ms,我觉得很奇怪,既然接口整体完成速度不到200ms,为何返回给postman的速度达到了惊人的几秒钟,此时我怀疑Stopwatch不准确,于是在代码开始前和开始后都加上了datetime.now,但是显示时间也很短

猜测1:计时不准

猜测2:返回json给前端的时候,时间耗费了很长

猜测1没有办法求证,猜测2其实做了那么多项目,其实也没有遇到,而且感觉这个接口返回的json也没有那么离谱,随后就只能抱着试一试的态度,设定了以下几组返回的json,以及他们最终测试的结果

第一种 返回原来的json 结果:几秒

第二种 返回一个字符串 结果:100-200毫秒

第三种 返回原来的json,但是减少一些很长的对象 结果:几秒

第四种 返回的对象再包一层 结果:几秒

第五种 不使用框架的json返回方法,自定义json返回方法 结果:几秒

很显然第二种的出现,让我认为json返回就是接口超时的最大原因,这里我只能去猜测

第一种 这里我只能去猜测是不是服务器的内存不够,造成的返回json时这么慢

第二种 会不会是c#识别到我没有用上面代码中的参数,所以它自己省略了上面一些代码的逻辑,直接就返回了字符串,但是日志记录到了每个节点的计时,而且这个结果跟一直计时的也对的上,那就只能往下求证

然后把返回的json最小化,这时候就用到了json压缩

后端代码
csharp 复制代码
//data为需要转换的数据
public string GetJsonData<T>(T data)
{
    // 序列化数据为JSON
    string json = JsonConvert.SerializeObject(data);
    // 如果需要压缩
    using (var memoryStream = new MemoryStream())
    {
        using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
        using (var streamWriter = new StreamWriter(gzipStream))
        {
            streamWriter.Write(json);
        }
        return Convert.ToBase64String(memoryStream.ToArray());
    }
}
javascript 复制代码
vue
npm install pako
import pako from 'pako'
// b64Data-->传入加密的数据进行解密
function unzip (b64Data) {
  let strData = atob(b64Data)
  // Convert binary string to character-number array
  const charData = strData.split('').map(function (x) { return x.charCodeAt(0) })
  // Turn number array into byte-array
  const binData = new Uint8Array(charData)
  // // unzip
  const data = pako.inflate(binData)
  // Convert gunzipped byteArray back to ascii string:
  strData = String.fromCharCode.apply(null, new Uint16Array(data))
  return strData
}

// 加密
function zip (str) {
  if (typeof str !== 'string') {
    str = JSON.stringify(str)
  }
  const binaryString = pako.gzip(str, { to: 'string' })
  return btoa(binaryString)
}

这种会中文乱码,需要改一下

let strData = atob(拿到的数据)
const charData = strData.split('').map(function (x) { return x.charCodeAt(0) })
const binData = new Uint8Array(charData)
strData = pako.inflate(binData,{to: 'string'})
//转换为json对象
ret.data = JSON.parse(strData);

这样整个压缩就结束了,3.2k的字符大概能压到2.几K,三分之一吧,至于查询速度,丝毫没有减少,那只能再看看,能不能继续减少json中的字符,如果这条路行不通的话

1.后面可能会把查询修改为存储过程

2.重构数据结构,优化查询频率之类的

整个过程下来,其实测试站速度很快,慢的也就是正式站,但是两个服务器的配置不同,这个没法横向比较,测试站数据量也没有正式站多,而且测试站的服务应该不是一直在跑的

破案了

破案了,是上一任小伙伴把一个实体的扩展方法内,返回字段的时候,做了很慢的查询,之前没发现是因为,之前只是查询了这张表,但是没有用这个字段,但是在返回json的时候,返回的是整个实体,导致它会去拿所有的字段,包括扩展类中的那个很慢查询的字段,所以,会导致看起来好像是json返回很慢的感觉,也算是个坑吧

相关推荐
乌啼霜满天249几秒前
JDBC编程---Java
java·开发语言·sql
色空大师13 分钟前
23种设计模式
java·开发语言·设计模式
Bruce小鬼25 分钟前
QT文件基本操作
开发语言·qt
2202_7544215431 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
我只会发热38 分钟前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
懷淰メ1 小时前
PyQt飞机大战游戏(附下载地址)
开发语言·python·qt·游戏·pyqt·游戏开发·pyqt5
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
宁静@星空1 小时前
006-自定义枚举注解
java·开发语言
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
武子康2 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot