分布式金融系统调优实践

引言:

某银行采用分布式架构对其核心产品系统进行重构,重构后该系统由多个技术模块和业务模块组成,存在联机交易、异步消息、自动任务、批量等交易形态。各模块之间交互较多,内部交易线复杂,本文结合该系统的性能测试实践分享一些在这种复杂的分布式金融系统中如何定位性能问题并通过调优提升系统性能的经验。

一、性能问题定位方法

1、响应时间分析

系统的性能指标主要体现在响应时间和TPS两点。互联网金融时代,客户的用户体验尤其重要。如果系统响应慢,应优先定位响应时间问题,优化联机交易响应时间。做性能测试时,记录下被测系统访问数据库、与其他模块/组件的交互、主要处理逻辑等各关键步骤消耗的时间,将各个步骤消耗的时间与现有老系统、经验值、预期值等进行比对分析,找到消耗时间长且不合理的步骤,然后对其进行重点分析和优化。例如,一次数据库操作平均执行时间超过了20ms,明显高于普通的SQL执行时间,需要重点关注;类似的应用处理逻辑在现有系统只花费10ms,而被测系统需要30ms,存在明显的差异,需分析其原因。

2、中间件状态监控

通过查看weblogic中间件的线程数、JDBC连接数判断weblogic的健康状况。如果出现问题,可以查看console日志和分析线程dump信息来判断是应用程序问题还是weblogic参数设置问题,再决定是优化应用程序还是调整weblogic的相关参数。

3、系统资源瓶颈分析

用nmon等工具监控系统的CPU、内存、磁盘IO、网络IO,观察哪种资源最先达到瓶颈,然后结合系统程序特点找到突破口。如果CPU是系统瓶颈,可以使用Jstack分析哪些线程CPU消耗高,是否存在死锁,使用JAVA VisualVM、Jprofile等工具定位哪些函数消耗资源较高。如果是内存消耗高,使用JAVA VisualVM、Jmap等工具将内存dump,分析哪些对象较大。对于磁盘、网络开销大,如果是应用端,分析可否减小与外部的交互,减小磁盘读写(如日志等);如果是数据库端,分析可否减少物理读、硬解析,调整数据库参数增加缓存命中率等。

4、数据库性能分析

通过AWR报告,分析SQL执行效率、缓存命中率、物理读、逻辑读、CPU消耗、响应时间等各项指标是否合理,是否需要优化。获取重点交易的SQL,分析这些SQL的执行计划是否合理,对于数据库较大的表是否存在全表扫描等耗时多的执行计划。

5、极限测试法

一般情况下,系统的处理能力都是在60%CPU使用率时获取的,如果处理能力达到了预期往往调优到此就截止了,但并不代表系统不存在性能问题。由于各主要步骤响应时间、各类资源消耗没有绝对的标准,有时无法判断这些值是否合理,此时可以进行极限测试,或者CPU等资源的扩展测试来发现潜在的问题。通常情况下,增加单台服务器压力,更容易暴露系统存在的性能瓶颈。例如,CPU资源加倍,如果增加一倍并发用户后,TPS没有翻倍,而响应时间急剧增加,Weblogic线程被消耗完,打印日志发现锁等待,最后通过日志定位出具体问题,并进行优化从而提升系统的处理能力和响应时间。

6、排除法

系统中涉及多个模块,有时仅查看日志无法判断瓶颈、问题出现在哪个模块。通过逐一剔除各模块(采用挡板等方法)排除无问题的模块,进而确认出现问题的模块,最后重点分析该模块。

7、静态分析法

(1)代码扫描:使用Fortify等代码扫描工具,对应用程序进行扫描,对扫描出来的问题进行分析和整改。

(2)数据库扫描:功能业务测试覆盖的交易更全面,业务场景更接近生产实际情况,使用数据库扫描工具对功能、非功能测试环境进行扫描发现数据库的问题。例如,SQL执行时间较长,大表扫描,缺少where条件等。数据库数据检核工具可以检查索引设计、库表设计、分区设计等是否合理,从而进一步规范数据库表设计。

(3)关键技术参数检核:对操作系统、数据库、中间件、框架平台和应用的一些关键参数进行检查,避免因参数配置错误引起的性能缺陷。

二、性能调优措施

1、交易线优化

通过观察交易日志发现,存在模块A的TOP5交易多次外呼模块B,甚至存在模块A外呼B,模块B外呼C,然后模块C的交易反过来外呼A的情况。由于网络开销和框架外呼开销在整个交易过程是占比较高的,因此将接口字段进行归并,交易过程中尽量只外呼一次相同模块。对于A呼B,B呼C,C再呼A的情况,在A呼B时就将C需要的一些接口要素传给B,再传给C,如此C就不用再回调A了,避免循环调用情况。

2、日志优化

日志虽然不是应用程序的逻辑,但是金融系统事关客户切身利益,即使有一笔账务交易失败,也必须查明原因。因此在金融系统中打印日志是很普遍的事情,日志方便了测试人员,更方便了运维人员。为了尽量获取更多的案发现场,经常打印了许多许多日志,适得其反,降低了系统的性能。日志优化主要从以下几方面着手:

(1)减少不必要的日志,对于排查问题、统计生产运行情况无影响的日志不再打印。例如:交易量很大的查询交易,不再打印其输入输出报文。

(2)调整日志级别,如仅在交易报错,排查问题时才会用到的日志调整打印级别为ERROR级。

(3)去除打印日志时获取行号功能(该功能对响应时间和CPU资源消耗影响较大),详见本文第三节。

(4)注意日志相关配置信息,将日志写进缓冲区。

3、优化缓存访问方式

在本系统中,有一些频繁使用的共享类参数,在设计过程中,为了保证性能和可用性,采用了三级存储方式,即本地JVM内存、分布式缓存和远程数据库。如果使用方能在本地内存访问的则直接访问;如果本地内存没有,则应用直接访问分布式缓存获取;如果分布式缓存也没有,则需要外呼参数提供方,提供方从其数据库中获取参数返回给使用方。本地内存访问,非常快,不到1ms,但是占用内存空间。访问分布式缓存,主要是网络开销,解析数据,也较快,1-2ms。但是如果外呼提供方的交易,则需要经过完整的外呼框架调用、报文解析、网络访问,响应时间需要10-15ms,增加了一个数量级。为此,在满足可用性的情况下应尽量提供本地内存、分布式缓存的缓存命中率。

(1)明确各类参数的存储方式、访问方式、生命周期和加载策略;

(2)提供方初始化应用时将参数类共享数据加载至分布式缓存;

(3)使用方初始化应用时将参数类共享数据加载至应用本地内存;

(4)缓存失效时,再往后一级访问的同时将参数缓存起来,以免后续交易仍不命中。

4、数据库优化

(1)建立合适的索引,特别是数据量较大、查询为主的表,根据查询条件建立合适的索引。

(2)在本系统测试过程中,数据库是40C256G的物理机,配置比较高,数据库端CPU消耗较低,性能瓶颈主要出现在AP端。由于AP、DB间通讯有开销,AP解析数据包也有CPU开销,因此减少数据库访问次数,多次数据库单表查询改为单次表连接查询,将AP的部分性能压力转移至数据库。

(3)数据库内存资源较充足,因此需充分利用物理内存。调整数据库SGA、SHARE POOL、CACHE SIZE等系统参数,提高数据库缓存命中率。总物理内存扣除连接数占用的内存(每个连接约10M)及操作系统(约4G)、常用软件占用的内存之后,剩余的内存按3:1的比例分配给数据库的SGA、PGA,即SGA占其中的3/4,PGA占1/4。SGA中SHARED POOL分1/4,DB BUFFER和其他内存池共用其余的1/2。在修改SGA等数据库参数时也需要修改linux系统参数,并且需要设置oracle - memlock $hugepage。

(4)将重要的索引,使用频繁数据量小的表常驻数据库内存,提高数据库缓存命中率,降低数据库访问时间、提升效率。

(5)缩减SQL查询、更新等操作的字段数,可以降低网络传输数据量、降低应用解析数据包的开销,进而降低应用的处理时间和资源消耗。

(6)对某些库表的字段频繁更新,应固定SQL格式,绑定变量,避免数据库大量硬解析操作。

三、一次具体调优过程实践

在模块A的CPU纵向扩展性测试中,资源加倍后,发压用户数也加倍,但此时响应时间增加了很多,CPU资源使用率和扩之前基本一致,TPS只增长60%,与响应时间不变,TPS加倍的预期结果不符,见图1、图2。

图1 Total Transactions per Second

图2 Average Transaction Response Time

观察响应时间日志,外呼、数据库操作、主体处理逻辑的响应时间都没有增长,只是交易总时间有增长。这说明与其他系统、数据库操作、网络、程序逻辑都没有关系。

图3 线程栈信息一

图4 线程栈信息二

通过JAVA VisualVM打印CPU消耗较高的热点方法,发现排名第三、四、五的都是log4j相关函数,见图5。

图5 热点方法CPU消耗排名

将JAVA VisualVM和Jstack结果结合起来分析,发现JAVA VisualVM中log4j的三个函数在Jstack中都出现了,说明问题确实出现在log4j,log4j的这几个函数增加了交易响应时间和CPU资源消耗。再看函数的名称,有一个getLocationInformation的函数,字面意思就是获取位置信息,但获取什么位置信息呢?

与开发人员一起分析log4j配置文件,并未发现异常,但仔细观察,发现每个日志的匹配模式中有%l的标志,如图六所示。这个配置会显示出打印日志的具体函数及行号,如下图7所示。获取具体位置的函数(getLocationInformation)会遍历一遍调用栈,将最终结果打印出来。其开销与程序异常输出函数调用栈差不多,根据之前的生产测试情况,大量输出异常调用栈将消耗CPU资源,响应时间也会受到影响。

图6 log4j配置信息

图7 log4j日志打印信息

那就在log4j配置去了%l试试,输出日志不再打印函数行号,见下图所示。

图8 log4j日志打印信息2

经测试未扩展CPU资源时,响应时间比优化前降低30%,TPS比优化前增长25%。CPU资源扩展后,响应时间几乎无增长,TPS处理能力可以翻倍,纵向扩展有效,见图9、图10。

图9 TPS图

图10 交易平均响应时间图

结语:

性能调优是一个漫长的过程,不能一蹴而就。本次项目非功能测试实施过程中不断发现并解决相关性能问题,是一次学习和成长的过程,本文总结的一些方法经验,也希望给大家带来一些收获。

本文来自企鹅号 - 非功能之路媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA高级架构

微服务架构组件分析

服务描述:服务调用首先解决的问题就是服务如何对外描述。 常用的服务描述方式包括 RESTful API、XML 配置以及 IDL 文件三种。

14240
来自专栏FreeBuf

关于Sql注入以及Burpsuite Intruders使用的一些浅浅的见解

最近一直在看关于SQL注入的一些文章,因为很多不懂所以看的比较慢,看的过程中中遇到了很多问题,但是静下心来细细品味一下,发现sql注入还是很有意思的!昨晚在看一...

16420
来自专栏双十二技术哥

组件化实践详解(二)

在上一篇文章《组件化实践详解(一)》中我们介绍了组件化实践的目标和实践步骤,本文继续说说关于组件化实践遇到的问题及思考。

13340
来自专栏Java架构师学习

你想了解的分布式--从ACID到CAP/BASE

本文先介绍传统关系数据库中事务的ACID特性,再介绍分布式系统中的经典理论——CAP定理和BASE理论。 事务 事务的定义: 事务(Transaction)是由...

30380
来自专栏最高权限比特流

漫谈计算机组成原理(二)系统总线

从引言中,我们基本上能够了解到总线在计算机系统中的作用。但是上面的说法只是一个概论,我们需要给出更加详细的总线的作用:总线是计算机中各个部件的信息传输线。在计算...

40830
来自专栏FreeBuf

我们来“劫持”个GitHub自定义域名玩吧!

作为一个国内外项目都不怎么挖的我,比较喜欢拿自己正在使用的服务入手挖洞,毕竟拥有需求又了解业务才能长期跟进,更好的去发现各种流程上出现的毛病。

21430
来自专栏進无尽的文章

基础篇-服务器工作实现的浅析

对于一个前端开发的人员来说,了解服务器的基础知识,个人觉得是非常必要的,于是就有一个这篇侧重于Java的服务器相关知识的文章,只是简单介绍对于我也是一个拓展。

15320
来自专栏大白虾谈架构

Windows10 Oracle ODBC安装配置

20140
来自专栏FreeBuf

反取证技术:内核模式下的进程隐蔽

介绍 本文是介绍恶意软件的持久性及传播性技术这一系列的第一次迭代,这些技术中大部分是研究人员几年前发现并披露的,在此介绍的目的是建立这些技术和取证方面的知识框架...

36080
来自专栏编程坑太多

『高级篇』docker之了解kubernetes(31)

PS:(梳理概念)pod里面包括N个容器,service里面包括pod,Deployment可能包括service或者是pod。

16240

扫码关注云+社区

领取腾讯云代金券