性能监控:
CPU 密集型/ IO 密集型:当前应用是浪费CPU(大量的计算) 比较多还是IO(网络IO,磁盘读写(数据库读数据…)) 比较多
性能监控主要是来监控JVM 的工作。
主要优化的地方是运行时数据区:
使用jdk 自带的工具:jvisualvm来检测jvm 内存中的变化。
使用JMeter 对一下两个接口进行压力测试
中间件:nginx, tomcat 对性能的影响
nginx 浪费的是cpu,对内存使用并不多。nginx 大多是计算型的,因为它只需要把请求转发给别人处理,所以内存占用并不多
对网关GateWay 进行压测:
发现Eden 区只有32M,并且发生Minor GC 次数很多。所以可以通过提升Eden 区的大小来减少Minor GC 的次数,也就减少了GC 时间,吞吐量就上升了。
不仅请求后端,后端要开很多线程去开数据库;连静态资源的渲染都要向tomcat 发送请求开启几个线程来获取这些资源。
静态资源优化:开启thymeleaf 缓存(当项目上线才这么做,在开发是还是关闭缓存)
日志优化:
日志级别只打印错误日志,其他都不打印
数据库优化:
给后端要操作数据库的字段都加上索引:
压测内容:
中间件优化是次要的,我们代码流程才是主要优化流程。代码优化从扩大Eden 区开始(减少GC 次数和花费总时间)。
首页的所有资源获取主要耗费的是静态资源的获取,所以需要用到nginx 动静分离。
给nginx 下创建一个static 文件夹,专门用来放页面的静态资源
如何让页面能访问到里面的内容呢? 可以参照之前ik 分词器的路径:ip地址/es/fenci.txt。
这个es 文件夹在html 下面,es 是如何找到这个文件夹的呢?
是因为default.conf 中配置了一个root 路径。所以我们就可以参照这个写法,给/static/ 路径也配置一个root 路径
在 guilmall.conf中配置,因为这个文件是用来处理gulimall 的请求的。
记得把页面的所有静态请求资源都加上/static/
以上就完成了:nginx 负责返回静态数据,tomcat 负责返回动态数据。
当压测时,将线程数调整至200,发现old 区非常快就爆满了。而且Eden 区也爆满。频繁的GC
调整堆内存空间:
-Xms: 最小堆内存 -Xmx: 最大堆内存。 -Xmn: Eden 区大小
优化三级分类数据获取:
在查询三级分类数据时嵌套调用多次数据库,这非常浪费性能
优化方法1:
将数据库的多次查询变为一次
@Override
public Map<String, List<Catelog2Vo>> getCatalogJson() {
/**
* 1.将数据库的多次查询变为一次
*/
//一次性直接将category 的数据都获取出来
List<CategoryEntity> selectList = baseMapper.selectList(null);
//1.查出所有1级分类
List<CategoryEntity> level1Categories = getParent_cid(selectList,0L);
//2.封装数据
Map<String, List<Catelog2Vo>> parent_cid = level1Categories.stream().collect(Collectors.toMap(k -> {
return k.getCatId().toString();
}, v -> {
//1. 每一个的一级分类,查到属于这个一级分类的二级分类
List<CategoryEntity> categoryEntities = getParent_cid(selectList,v.getCatId());
List<Catelog2Vo> catelog2Vos = null;
//要把categoryEntities 这个对象封装成我们编写的VO 对象:Catelog2Vo
if (categoryEntities != null) {
catelog2Vos = categoryEntities.stream().map(l2 -> {
Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName());
//根据2 级分类查找3 级分类数据
List<CategoryEntity> level3Catelog = getParent_cid(selectList,l2.getCatId());
if (level3Catelog != null){
//将level3Catelog 封装成Catelog3Vo
List<Catelog2Vo.Cateloa3Vo> cateloa3Vos = level3Catelog.stream().map(l3 -> {
Catelog2Vo.Cateloa3Vo cateloa3Vo = new Catelog2Vo.Cateloa3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());
return cateloa3Vo;
}).collect(Collectors.toList());
catelog2Vo.setCatalog3List(cateloa3Vos);
}
return catelog2Vo;
}).collect(Collectors.toList());
}
return catelog2Vos;
}));
return parent_cid;
}
//把”根据parent_cid 来查找子分类数据“ 的方法抽取成一个公共方法
private List<CategoryEntity> getParent_cid(List<CategoryEntity> selectList,Long parent_cid) {
List<CategoryEntity> collect = selectList.stream().filter(item -> {
return item.getParentCid() == parent_cid;
}).collect(Collectors.toList());
return collect;
}
调节最大堆内存: