起因:
月初这几天,某台服务器cpu频繁满载告警。
由于该台服务器部署了两个应用,一个web,一个后台。在凌晨先后启停服务后确定是后台应用导致。然后后台应用已经跑了很长时间,基本没有出过问题,怎么突然就出问题了呢?
定位:
联系相关开发人员,是最近有个适配改动了十几行代码。我想应该就是这几行代码导致的。和他一起review了他的代码,然而并没有发现代码有什么明显的改动。
去服务器看看,
使用jps
查看java进程,获取到pid=31793
,通过jmap -histo 31793 > 1.txt
命令将内存中的对象信息输出到文件中,
通过less
查看发现,有内存中有十几万个该对象,正好,这个对象是改动的代码部分,但是实际考虑数据量及结合代码逻辑,不应该产生这么多对象。
使用ps -mp 31793 -o THREAD,tid,time
命令获取java进程中各线程对CPU资源的使用情况:
发现,有3个鬼鬼祟祟的线程tid=31813,31814,31815
占用了大量资源。将tid转换为16进制printf "%x\n" 31813
16进制thread-id:7c45
从当前堆栈信息查看此线程
jstack 31793 > 2.txt
然后在2.txt
文件中搜索7c45
线程。
可以看到,占用大量资源的线程是在调用JSONObject billData = JSONObject.fromObject(bd.getData());
将String转json时占用大量资源。
于是决定使用fastjson或者其他json来解决问题。
换用jackson后:业务恢复,cpu使用率正常。
其他:
本想继续看一看net.sf.json的源码,奈何不是org项目,无奈只能到此。以后技术的选用方面应该向大厂开源的靠拢。
测试了下性能:
10w个简单对象的json反序列化。
sf json:耗时788
fast json:耗时132
差距还是很大的
附测试代码:
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TestSFjson {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 1; i < 100000; i++) {
User user = new User();
user.setId(i);
user.setAge(18);
user.setName("hello" + i);
user.setCreateTime(new Date());
list.add(com.alibaba.fastjson.JSONObject.toJSONString(user));
}
long s = System.currentTimeMillis();
for (String userStr : list) {
JSONObject.fromObject(userStr);
}
System.out.println("sf json:耗时" +(System.currentTimeMillis() - s));
long s2 = System.currentTimeMillis();
for (String userStr : list) {
com.alibaba.fastjson.JSONObject.parseObject(userStr);
}
System.out.println("fast json:耗时" +(System.currentTimeMillis() - s2));
}
}
class User {
private Integer id;
private String name;
private Integer age;
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
来源:CSDN
作者:lazy_lake
链接:https://blog.csdn.net/lazy_lake/article/details/103831146