问题背景
随着软件开发技术架构的不断演进,采用诸如TSF微服务框架开发微服务已经成为一种趋势,然而随着客户业务流量的不断提升,微服务也会遇到性能上的瓶颈,对于系统如果做到高效、稳定保障系统平稳支撑业务增长,是我们需要面对的技术难题。 性能优化需要解决如下问题:
- 降低业务成本。
- 提升系统的稳定性。
- 提升用户的体验。
性能是驱动应用结构演进的主要动力之一,本文会通过应用结构的变化揭示性能是如何在不同阶段、以不同的结构驱动应用结构朝着下一个结构演进的。通过应用结构的发展也可以揭示,如何不做过度的设计,在应用尽量简化且不浪费企业资源的情况下支撑企业业务的发展。
性能优化的最佳实践步骤
性能优化的2种模式
性能优化有两种模式,纵观性能优化案例,性能优化整体上可以分为两类:单应用优化和多应用全链路优化。
- 单体应用优化:关注单系统瓶颈,通过解决单系统瓶颈提升性能。
- 多应用全链路优化:通过改造链路结构和配比进行整体性能的优化。
一、单体应用优化实践
1、确定性能瓶颈。
性能压测:通过工具、人工等方式量化运行时的性能情况。
业务/代码梳理:通过代码走读发现资源消耗热点,通过统计代码对资源的操作量化代码对资源的消耗(比如一个业务操作会进行多少次数据库调用,进行多少次服务运算等方式)。
一般来说,我们性能分析工具都是以 Java 环境为例,压测时通常使用 JMeter 及 LoadRunner 发起压力测试并收集压测指标,使用 nmon 来检测 Linux 的性能情况。nmon 是一种在 AIX 与各种 Linux 操作系统上被广泛使用的监控与分析工具。除此之外,压测时通常观察的内容及其所使用的工具如下:
1)、内存的使用情况:可以使用free、MAT、GC日志、vmstat。
2)、IO的情况:iostat。
3)、网络情况:netstat。
4)、热点代码:JProfiler、BTrace、JStack、JStat。
5)、CPU的情况:调用Linux的top命令。
2、常见的优化手段及模式
1)、动静分离:动态数据与静态页面数据的分离。
2)、异步化:使用异步化,减少主流程中非关键业务逻辑。
3)、并行化,使用多现场并发处理,缩短处理时长。
4)、内存优化:减少对象所占用的内存空间,简单创建对象的数量,优化数据结构。
5)、去重复运算:优化业务逻辑,或者使用缓存。
6)、 减少数据库操作:使用分布式缓存,提升数据读写效率,杜绝数据库慢查询、死锁等。
7)、缩短数据库事务:可以考虑使用短事务、异步化、最终一致性等方式。
8)、精简代码逻辑:去除冗余代码,诸如重复判断的代码。
9)、精简日志操作:要关注日志大小,注意 I/O 上的瓶颈。日志太多,说明生成的 String 也会很多,会增加 GC 的负担。
二、多个应用全链路优化实践
单应用时代对此问题的第一个常见解决办法是使用缓存(偏向应用级别的缓存)。为了防止所有的数据读写都集中在数据库上进行,首先想到的就是通过缓存减少对数据库的压力,比如将配置数据全部加载到缓存(某些场景可以使用类似 LRU 的缓存)中
单应用时代解决此问题的第二个办法是使用独立缓存服务(集中式缓存,如 MemCache),
单应用集中式部署后的数据库瓶颈如下图所示
单应用集中式部署后的数据库瓶颈的解决办法是对数据库进行拆分及读写分离。
为了应对更大范围的请求量,需要进行服务化拆分,由此进入多应用分布式服务化时代,这里可以采用服务化方式将原来单体中的服务拆分成多个服务,如下图所示:
随着业务及数据的规模不断扩大,又逐渐进入多应用分布式服务集群化时代,此时基于TSF微服务平台提供一站式的微服务构建、自动化部署,服务注册、发现、服务治理等方案。可以帮助我们开发者在极短时间内快速构建微服务系统。
性能提升最佳案例
基于TSF处理单点/网络瓶颈的可行方式
1、通过去分布式调用进行去中心化,可以规避网络设备成为瓶颈和单点故障
2、增加数据处理中间层可以缓解数据库连接池的瓶颈,最好的处理方式是对架构进行服务化和单元化,将数据量大的数据库进行拆分,分散压力。
对于小型企业的业务,通过进行较为简单的单系统优化,并辅助结构性优化,便能满足大部分企业的要求,但随着企业的业务量不断增加,单独的单机优化已经不能满足需求。分布式部署是中大型企业的必经之路,水平扩展、垂直拆分、服务化等方式是实现分布式部署的方式。
但是对于大型厂商,已经不再满足固定模式的水平扩展, 那么当一个机房的容量不足时要如何应对呢?一个城市的机房容量不足时又要如何应对?综合不断增长的业务述求,正在实施单元化进程,根据一定的数据分片规则,使特定分片规则下的用户访问到特定单元化的应用系统,并通过不同城市的单元实现流量的自由切换和容灾。
技术总是在不断更迭,今天的解决办法是明天的问题,也许单元化也不是最终的解决办法,总会涌现出越来越多的新挑战和应用模式。