项目总结50:Linux服务器上web项目Java项目性能调优
最近上线的电商项目,发现非常卡,用户体验非常差,折腾了好久之后,也逐渐找到原因,并针对原因解决方案,先整理总结。
项目基本情况:
1-使用阿里ECS、OSS等一系列相关服务;
2-用户总量1W+,日活量500+
3-电商项目,有APP、小程序、管理平台三个模块,其中接口150+
4-项目使用SSM框架;
5-项目tomcat服务,数据库Mysql,Redis放在一个同一个服务器上;
问题表现:
1-接口反应非常慢,导致APP和小程序加载失败,根据阿里Druid Monitor分析数据,接口经常需要10秒+请求;
2-使用Navicat打开数据表、查询数据,反应也很慢;
3-使用Linux 服务本地打开数据库,查询数据非常快
4-图片/视频上传非常缓慢
问题分析
根据经验,当前的用户使用量服务应该是完全可以支撑的,所以卡顿是不合理的;需逐步分析
问题排查
第一步:确认阿里云RCS服务器配置是否合理;
服务器原有配置:CPU:2核;内存:16 GiB;带宽:1Mbps; 查看CPU、内存、带宽使用情况,如下:
根据监控结果发现:CPU、内存使用情况都正常,但是带宽使用需求明显超过1Mbps;
处理方案:更新配置,带宽由1Mbps升级到10Mbps,升级后,带宽实用情况再2Mbps左右,使用率由原来的100%降到20%左右,如下:
第二步:数据库和业务服务,分离,使用阿里云RDS服务单独部署服务器;Redis服务也可以单独使用Redis服务器(但目前没有使用,因为项目目前对缓存需求不高)
第三步:使用阿里的SLB负载均衡服务,业务服务器由一台增至两台;
至此,服务器配置和更新结束,已经基本满足当前项目需求,由原来一台ECS服务器包办,更新为两台ECS业务服务器、一台RDS数据库服务器,一台SLB负载均衡服务;
第四步:在SSM框架中引用Redis缓存,针对APP和小程序的读接口,进行缓存,从而减少数据库请求压力;其中在具体落实的时候,碰到了一些问题;
1-Redis缓存的Entity必须实现Serializable;
2-使用Springboot注解式缓存,方通不能调用同一个类中其他被注解缓存的方法;即A、B方法在同一个类,A方法实现了缓存,那么B方法调用A方法,会导致A方法缓存失效;只要将A、B放在不同的类即可;
3-@Cacheable中的key,对应Redis中的key,即value不同的@Cacheable,对应的key的命名规则须不一样,否则会导致缓存冲突;
4-使用了@Cacheable,根据实际业务情况,也应该在对应的相关方法上实现@CacheEvict(清除缓存);
5-SpringBoot集成的Cahe是不支持针对每一个缓存定制有效时间,这个需要自己额外实现;
6-项目考虑后面那会用分布式,没有使用Ehcache(内存型缓存);
7-目前Redis缓存就部署在一台服务器上,没有使用分布式,也没有使用主从复制;
<!-- spring boot 的redis模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
//使用缓存 @Cacheable(value = CacheValueConst.APP_INCOME_OVERVIEW_INFO, key = "#root.caches[0].name+#shopId") public ShopIncomeOverviewVO getIncomeOverviewInfo(Long shopId) throws ServerSqlErrorException { ...... } //清除缓存 @Override @CacheEvict(value = CacheValueConst.APP_INCOME_OVERVIEW_INFO, key = "#root.caches[0].name+#entity.shopId") public void save(FinanceCommissionRecord entity) throws ServerSqlErrorException { ..... }
第五步:优化SQL语句,主要做了以下几点:
1-对数据表中的部分字段折纸索引(这个在项目最开始就逐渐落实了);
2-对于查询SQL,由select * from table,改为select id, name,code... fromtable;即返回需要的字段,不需要的字段不返回;其中对性能做了下对比测试,发现字段返回的数量对相应速度还是很有影响的,如下:
第六步:针对上传文件操作,切换上传方式
使用了阿里的OSS服务;由原来的OSS服务器上传文件,切换成前端OSS直传;区别在于,前者文件要先上传到业务服务器,再上传到OSS服务器,非常吃带宽;后者文件直接前端上传OSS返回URL,文件不经过业务服务器;这个优化对上传大文件(比如视频文件)影响是非常大的;OSS直传如何实现阿里官方文档有非常清晰的描述。
第七步:清理服务器磁盘
跟踪RCS服务器监控发现,服务器磁盘使用是87%;登陆Linux服务器,使用df -h和du -sh *,排查发现Tomcat日志文件catalina.out有28G(服务器一共40G);删除catalina.out文件,并重启Tomcat服务,删除先后的磁盘使用情况如下(断崖式下降):
第八步:考虑到项目即将上线优惠活动和秒杀活动,便开通了弹性伸缩服务ESS;对阶段性的并发进行集中处理;
第九步:对Tomcat进行性能调优(未进行,因为上面几步下来,性能已经极大的得到提升)
总结:
1-其实项目目前性能问题的主要原因是带宽不够(这个是比较低级的问题);
2-考虑项目后面会迭代开发,顺势将缓存、SQL优化、服务器配置等相关的触手可及的优化也做了;
附:
1-阿里云测试分析及调优建议:https://help.aliyun.com/document_detail/29342.html