问题出现: 视频剪辑超时
1。检查系统日志
发现这个报错信息,导致接口访问超时获取数据失败。
2。经过对网上信息梳理,发现这个超时是在用域名访问nginx时候,有一个send_timeout超时时间,超过这个时间nginx将连接断开了。代码会报错
(如果有遇到相同问题的同学,并且正好是域名访问接口报错,可以直接更改配置,调整超时时间。 但同样也要反思,这个接口响应这么久真的没问题吗?)
3。由于这个请求的数据大小只有2M,大概四千条数据,响应不应该这么慢,然后开始debug查询问题。
4。看图
这个是httpUtil的一个工具类,可以看到这行代码是有问题的。
原因:
使用+拼接字符串的实现原理,基于jdk1.8
下面一段代码。把他生成的字节码进行反编译,看看结果。
String testJoin = "testJoin";
String introduce = "测试数据拼接";
String result =
testJoin + "," + introduce;
反编译后的内容如下,反编译工具为jad。
String
testJoin= "testJoin";
String introduce = "\u6BCF\u65E5\u66F4\u65B0Java\u76F8\u5173\u6280\u672F\u6587\u7AE0";
String
result= (new StringBuilder()).append(testJoin).append(",").append(introduce).toString();
通过查看反编译以后的代码,可以发现,原来字符串常量在拼接过程中,是将String转成了StringBuilder后,使用其append方法进行处理的。
改动代码为如下:
这样处理数据的时候就非常快,问题看似已经解决。
问题扩展:
我这里经过测试,发现只有请求我写的新系统时候,才会发生这种响应慢的问题。然后继续打断点调试。
发现同一个json数据结构体,其他系统在这里只需要遍历一次就可以。
自我反思:
为什么只需要遍历一次? 数据传输的时候是一行? 为什么我的是多行? 同样是json体为什么我的就需要遍历多次?
排查继续:
检查使用的JSON序列化工具,发现其他系统用的是jackson,而我使用的是fastjson。
将这个配置注释掉,再次调用接口发现循环遍历的时候变成了一次。
继续反思:
springBoot项目中返回数据的时候我用到了@ResponseBody, 这个注解是用的那个JSON序列化工具?
这里就开始查询源码,自我debug过程不再论述,网上源码讲解很多,直接贴出来给大家参考。
https://www.cnblogs.com/HHR-SUN/p/11639801.html
https://www.jianshu.com/p/2f633cb817f5
核心点就是spring MVC有HttpMessageConverter这个消息转换器,我们的请求与返回数据的响应都经过这里,经过debug发现@ResponseBody默认采用的是jackson。
难道和这个序列化有关系?
这个关键是HTTP获取流,还没有对此进行反序列化等操作。然后在一个接口中直接用fastjson转换了一下结果,发现数据返回并没有问题,也是遍历一次就可以。
最后:
上面引用了fastjson的时候做了一下配置,怀疑是某个配置造成。(这个 配置文件直接拷贝其他项目,具体配置并不了解。自己坑自己)
查找各配置含义:
怀疑是这个格式化原因,将其注释掉,再次调用接口,发现问题解决。
扩展:
下面数据为格式化后的样子,比格式化前数据大了18%左右
总结
问题的排查必须要有从点到面的思考方式,解决问题的方式有很多,但是问题的出现可能是连锁反应,直有从头到尾,不错过任何细节才能发现真正的原因