性能优化方案总结




前言:

这是我个人的一些开发(JAVA\WEB)经验总结,不一定是很好的,也不一定是适合你现有的工作内容。写出来的目的,是想跟大家一起探讨软件系统性能优化的解决方法。希望大家能指出其间的问题和不足之处,相互学习,一起进步。多谢!

目前只是写了优化方案的骨架,具体优化执行,由于有很多的方式方法,大家需要的话,可以百度一下,我这里只是抛砖引玉。后续我也会把自己的具体执行方法总结出来,陆续的增加,与大家一起探讨。


       性能优化,是每个系统从设计的技术发展,都必须进行系统的重构、升级、优化等过程。这些都可以广义的定义为“性能优化”。

我这里从系统的垂直结构和横向结构两个方面来分别讨论一下性能的优化方案。

一、垂直结构优化

垂直结构优化,主要是根据系统架构中的分层结构来进行各个层次的优化。


1. 前端优化

前端优化,一般都是WEB端或APP端的优化,这里以WEB优化为例。

WEB端的优化,主要方案有:产品设计优化、前后端分离优化、页面缓存优化、前端服务器优化、前端代码重构等

1)产品设计优化

好的产品设计,会给前端开发甚至后端开发,降低一定的技术难度;比如:

统一的设计风格:统一的设计风格,是指相同或相似的功能,业务设计及界面设计,也要统一,这样会让前端和后端,在代码结构设计上,减少对象设计及业务实现结构化。因为相同的设计风格,代码结构(前后端)可以组件化,这样在代码实现的时候,不同的业务,只要根据组件,填写相应的业务内容即可,这就大大的较少了代码量。

复杂逻辑简单化:对于复杂的业务逻辑,在允许的情况下,尽量分拆步骤,让其简单化,并一步一处理,通过简单的多次交互,来降低后端代码的实现难度。

一事一处理:跟前面的一步一处理是一回事,是指前端在处理完一件事情后,如果可以提交,就尽量提交结果,不要多个步骤一起提交,这样会增加前端及后端的处理难度,而且可能会给系统处理带来难以预料的且不必要的坑。

2) 前后端分离

早期的前端是ASP\JSP,一般是跟后端程序混在一起,所以只能部署在一起的;就算后来有了前端组件(比如jQuery、extjs、YUI、bootstrap、VUE等),很多人图方便,也是跟后端程序部署在一起的;所以可以对前端和后端分开部署服务,这样可以分担压力,加快页面的反应速度;一般前后的分离部署,WEB部分的服务采用NGINX,后台JAVA部分一般使用tomcat服务。


3)前端代码重构

很多时候,项目或产品,都是在产品经理火急火燎的催促下完成的,没有完善的产品设计,也没有规范的技术文档设计,甚至没有经过详细的测试,这样就上线使用了。这肯定是存在问题的,所以需要对代码进行重构,包括前端代码的重构。

前端代码重构,必须在对产品设计重新整理的情况下进行,否则重构是不彻底甚至是失败的;同样,代码重构,必须有较完善的技术设计文档(讨论、重复的讨论后的文档)作依据。

前端代码除了依据产品设计梳理逻辑外,更多的是要尽量较少代码的重复度,也就是说相同或类似的功能,代码尽量是一套方法。举个简单的例子,我们前端对后端的请求接口,可以参考这样设计:1、数据组装的方法;2、发送方法、3、解析返回数据的方法;同时可以对这三个方法再进行细分子方法(不同的子方法,面对不同的场景)。经过这样的设计,就可以覆盖我们绝大多数的请求接口,代码逻辑也比较清晰,可读性也不差,维护或扩展也方便。

前端代码重构,也要尽量组件化,把常用的页面、子页面、按钮等,做成公共的模块,不同场景的业务,只要传递不同的参数及数据就可以实现不同的展示。


4)页面缓存优化

可以对页面一些不经常变化的文件,或页面中不经常变化的部分,进行【静态缓存】优化或【局部静态缓存】优化。这样可以减少加载页面文件或页面内容的时间,从而提高反应速度。缓存优化方法,方案很多,根据不同的场景,解决方案也会不一样,请自行在百度上搜一下,我这里就不具体描述了。


5)前端服务器优化

这个是建立在前端服务分离的基础上,比如常用的前端服务工具NGINX,这样就可以对NGINX进行相关的配置优化(网上有很多优化方案,这里就不描述了)

2. 后端优化

后端(以JAVA为例)优化,这里指对后端程序进行优化。

后台的优化,对于复杂的平台来说,需要从顶层设计上对框架进行优化,这里会用到一些设计模式概念,要分门别类的处理不同的事物逻辑,要设计不同功能的父类。比如公共的界面数据处理及放回模块,公共的DTO父类,公共的Mapper父类,公共的接口父类,抽象父类等;这个涉及比较深奥,我也是懂一些皮毛,这里就不详细描述了,因为需要根据不同的场景来分别述说。

对于现在的一些框架来说,都已经对层次分得比较清楚了,比如:应用层、业务逻辑层、接口及接口实现层、缓存及数据层等,我们不需要再做什么其他层次上的优化了。

JAVA后端的优化,也必须依据业务逻辑来展开,依据不同的业务,对代码进行梳理和封装,也跟前端一样,尽量多用公共方法来处理类似的问题。

下面总结自己碰到过的需要优化的场景及经验:

1)批量处理

要尽量的多使用批量数据存取方法,减少对数据库的访问;

比如在一个循环中,每次都需要通过ID值去数据库中获取某个值,如果这样的话,这个循环有多大,就会访问多少次数据库,一旦达到极限,数据库就会出现性能问题;这样可以一次性通过ID获取出这些值,再根据ID去内存中对比即可,这样就大大的较少了数据库的压力;

又比如:一些MQ消息处理,如果需要存储到数据库,如果每来一个消息,就进行一次存库操作,一旦消息密集过大,数据库压力也会增加,这里可以适当考虑在消息延迟时间允许的情况下,用集合(list,hash,array等)缓存起来,等达到规定的时间或规定的记录数后,批量保存信息到数据库。

2)多线程处理

对于不需要同步处理业务,可以采用多线程机制来同时进行,这样可以大大的提高业务处理能力。比如:MQ消息接收处理;MQ消息发送处理等,都可以采用线程池来处理。

3)数据库优化

因为前面的批量处理及多线程处理,对数据库的处理能力要求大大提升,所以对数据库的优化工作也要相应的处理(后面描述)

4)后端服务器优化

一般的后台服务器,以tomcat为主,对其的优化,主要是配置方面的,可以网上搜索一下,根据实际情况进行配置。一般就是对Server.xml(引擎、连接数等参数)优化和Catalina(JVM虚拟机参数)的优化。

3. 缓存优化

     系统性能的优化,是从上到下贯穿的,缓存的优化,也是其中很重要的部分,是对性能优化起到支撑作用的。

缓存优化,包括内存缓存、第三方缓存工具(比如redis等)、文件缓存服务器等

对于上面的批量存取、多线程等的优化,就可以用到内存缓存,比如把批量的数据,缓存在集合对象中,或者把把大存储的文件缓存在内存中,方便程序快速获取,从而节省时间,提高性能;

以redis为例,第三方缓存,在当前的系统架构中,也是存在着很重要的性能优化战术地位(redis优化,内容比较多,后续增加专门的优化说明)。

增加缓存服务器,也是方便大量文件存取的一个节约时间的方法,当前很多云服务都有专门的文件服务器,就是提供这种解决方案的;我们也可以本地化部署一个文件服务器,专门来存放图片或文件,这样的性能效果会更好一些。

4. 数据库优化

增加数据库(以MySQL为例)的配置优化,也能帮助提升系统的性能。 比如优化数据库数据库引擎,增加数据库连接数、全局缓存、查询缓存、日志缓存、连接池缓存等,对于批量操作、多线程操作等,都能起到很好的性能优化效果。具体如何配置,网上百度一下,方案很多,后续我也会专门做个MySQL优化说明。

数据库优化,还涉及到表的优化,比如增加索引、视图、存储过程等。


二、横向结构优化

横向结构优化,我个人认为就是我们经常说的框架设计优化、微服务优化、分布式部署优化。如果在上面的垂直结构优化的基础上也无法完全的解决系统的性能问题,就要对系统的整个框架进行一些分析并拆分了,比如重构框架或重构主要模块等。

架构设计优化常用的方法有:分拆模块,微服务化,重点模块服务化等。

下面是我对框架的一些划分设计(仅供参考)

对系统微服务化,其实就是根据实际情况,把一些特定功能的模块分离出来,独立成一个子系统,专门处理自己子系统的业务,并为其他子系统提供接口及数据支持。

现在一些大的平台或系统,都有几个特殊的子系统,比如用户中心、APP服务中心、设备通讯服务中心、客服中心等。

1. 子系统划分

用户子系统

专门处理用户相关的业务逻辑及数据

用户在一个系统中,是核心的,同时也是麻烦的,因为任何系统中的业务及数据,都跟用户有关系。因此从性能及业务逻辑考虑,都是可以独立成服务的。

APP应用子系统

专门处理手机应用端的业务逻辑及数据;

很多手机端的应用,是面向C端用户的,所以无论业务逻辑及并发数量上,都是重点要考虑的,独立服务无可厚非;

设备通信子系统

处理设备相关的通信及业务处理;

 在物联网的平台系统中,设备通信是个重要的模块,考虑到数据的实时性及并发现,独立成系统也是必要的。

平台服务子系统

处理平台常用业务逻辑及数据,并根据需要,可以进一步分拆模块,优化服务;

客服支持子系统

如果系统是面向C端的,就必须考虑用户体验,因此客服系统必不可少;

客服中心主要处理客服相关的业务及数据;用来收集用户问题、展示解决问题的方案或文案;既可以智能的解决一些常用的客户问题,也能降低电话客服的压力。

交易中心、清分结算中心

处理与订单、金融相关的业务逻辑及数据;

 对于商城来说,交易订单和金额都是重要的事件,能处理得越快越准越好;

报警、消息中心:处理报警、消息相关的业务及信息处理;

  报警和消息,是任何系统都要考虑的,她能及时的把用户需要的提醒送到用户手上,对于要求高的平台系统来说,独立服务也是必须的;


这些子系统都是因为特殊的功能或业务逻辑分离开来的,以减轻整个平台系统的处理压力,并方便后续业务发展的延续。

2. 子系统划分方法

对于如何拆分子系统,我主要从两个方面来考虑:

业务逻辑:

相同的业务逻辑的功能尽量放在同一个子系统,方便数据存储及处理。比如上面的用户子系统,就专门处理用户相关的业务,包括用户管理、用户鉴权、用户数据等业务。

性能考虑:

性能相关的模块,一般都是并发量大或数据库大的功能模块。比如用户访问、订单交易及支付等。比如上面的交易中心,这个是对性能要求非常高的模块,独立出来后,可以根据性能要求的不断增大,不断的扩展集群服务,以保证正常的交易活动。

微服务的框架,对数据处理要求也是比较高的,因此,缓存服务器也是必不可少的。前面我们提到的缓存优化及文件服务器优化等,也是必不可少的优化方法。


三、其他性能优化方案

1. 数据分类处理

微服务中,数据库的处理,也是要好好设计和考虑的,比如什么时候该用关系型数据库,什么时候该用NoSQL数据库。我一般是把一些常规业务逻辑的数据,存在关系型数据库中(比如Mysql),一些日志型数据,存储在NoSQL数据库中(比如ES、mongodb),涉及到大量的文件型数据,写到大数据库中(比如Hadoop、spark等)

2.  分表分库处理

如果数据量大,肯定要考虑分表或分库操作。分库分表后,数据的同步、事务等也就必须考虑了。数据同步,方法很多,可以自己写代码同步,比如可以通过多数据源配置,同时对不同数据库的表插入相同的数据;也可以借鉴第三方插件来同步,象Mysql就可以通过映射表方法来同步数据。

3. 集群化处理

如果当个服务,无法支撑系统的访问要求,那就要考虑对相关子服务进行集群部署了。比如我们的web前端,可以采用nginx集群方案,JAVA后端可以采用tomcat集群方案,redis、MySQL等本身也有各自集群方案。


4. MQ解耦处理

通过MQ(message queue,消息队列)中间件来解决一些消息收发,较少对数据库或其他服务的直接访问,以此来达到解耦及性能优化,也是一种很好的系统优化方案。