NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

巧用工具提升无源码系统的性能和稳定性

  • 2020-02-11
  • 本文字数:2999 字

    阅读完需:约 10 分钟

巧用工具提升无源码系统的性能和稳定性

导读:在没有核心系统源码的情况下,修改源码打印耗时的方法无法使用,通过 tcpdump、wireshark、gdb、010 editor、火焰图、ida、数据库抓 sql 耗时语句、oracle ash 报告、loadrunner 等工具找到了服务器 tps 上不去,C 程序进程随机挂掉的问题,并顺利解决,收获颇多。

背景

公司最近新上线一个系统,主要架构如下:


1557385732344055544.png


测试环境系统部署后,出现了两个问题:


1.loadrunner 压测 tps 上不去,压测 java 接口 tps 单机只能到 100 多 tps 就上不去了,耗时从单次访问的 100ms 上升到 110 并发时的 1s 左右。 2. 压测期间 C 服务器 1 经常不定时挂掉。


因为某些原因,该项目 C 相关程序没有源码,只有安装部署文件,为了解决上述两个问题,我们几个同事和重庆同事一块参与问题排查和解决。因为没有源码,中间经历了层层波折,经过一个月努力,终于解决了上述两个问题,整个排查过程学到了很多知识。

用到的分析工具

1.tcpdump,


2.wireshark,


3.gdb,


4.010 editor,


5.火焰图,


6.ida,


7.数据库抓 sql 耗时语句,


8.oracle ash 报告,


9.loadrunner

几句话总结

1.C 程序客户端 socket 长连接调用 C 服务端存在性能瓶颈,通过 tcpdump,wireshark 二进制分析出传输协议后改用 java 调用 C 服务端,单机 tps 提升 1 倍,性能提升 3 倍


2.数据库语句存在 for update 语句导致并发上不去,经过分析从业务上采用 sequence 替换 for update 语句,并通过 010 editor 直接修改二进制 修改 for update 语句相关逻辑为 sequence ,系统具备了扩容服务器 tps 也能同步提升的能力


3.数据库 insert 语句并发情况下存在瓶颈,扩大 oracle redo log 日志大小解决,继续提升 tps40%。


4.程序进程随机挂掉,通过 gdb 分析 core dump 文件,定位到在并发情况下程序中使用的 gethostbyname 有问题,采用临时方法解决。

分析过程

1.第一次瓶颈定位


刚开始排查问题时,loadrunner 压测 java 接口,并发用户从 0 逐渐增加到 110 个的情况下,tps 到 100 左右就不再提升,响应耗时从 100ms 增大到 1s。此时我们的分析重点是谁是当前的主要瓶颈


1557385749084086043.png


再看一遍架构图, 图中 5 个节点都有可能是瓶颈点,数据库此时我们通过数据库 dba 管理权限抓取耗时 sql,没抓取到,先排除数据库问题,java 的我们打印分步耗时日志,定位到 jni 调用 c 客户端耗时占比最大。这时瓶颈点初步定位到 C 客户端,C 服务端 1,C 服务端 2 这三个节点。


因为没有源码,我们采用 tcpdump 抓包分析,在 C 服务器 1 上


tcpdump   -i  eth0  -s  0   -w aa.txt  host  java客户端ip
复制代码


抓出的包用 wireshark 分析


1557385770945013038.png


通过追踪流-TCP 流 分析服务端耗时并没有变的太大,因为 C 客户端和 C 服务端是长连接,多个请求可能会共用一个连接,所以此时分析出的数据可能会不太准,因此我们采用 loadrunner 压测,其它条件不变,一台 C 服务器 1 和两台 C 服务器 1 分别查看耗时变化,


其它条件不变,一台 java 服务器和两台 java 服务器分别查看耗时变化.


最终定位到是 C 客户端的问题。(ps:在 wireshark 的分析数据时还跟秦迪大师弄明白了 tcp 延迟确认)


2.改造 C 客户端


C 客户端和 C 服务端是通过长连接通信的,直接改造 C 代码难度较大,所有我们准备把 C 替换成 java,这就需要分析 C 之间通信传参时候用的什么协议,然后根据这个协议用 java 重写。我们根据之前的经验推测出了编码协议,用 wireshark 分析二进制确认确实是这种编码。


1557385794505066716.png


我们根据这种协议编码采用 java 重写后,同样在 110 并发用户情况下,tps 提升到了 210(提升两倍),耗时降到了 330ms(是原来的三分之一)


3.第二次瓶颈定位。


经过第二步优化后 tps 提升了两倍,但是此时扩容 tomcat,扩容 C 服务器,tps 就维持在 210 左右,不会变高了。因此我们继续进行定位新的瓶颈点。此时找 dba 要到一个实时查看 oracle 耗时 sql 的语句


select
(select b.SQL_TEXT from v$sqlarea b where b.SQL_ID=a.SQL_ID ) sqltxt,
(select c.SQL_FULLTEXT from v$sqlarea c where c.SQL_ID=a.SQL_ID ) sqlfulltxt,
a.username, a.LAST_CALL_ET,a.MACHINE ,a.command, a.EVENT, a.SQL_ID ,a.SID,a.SERIAL#,
'alter system kill session ''' || a.SID ||','||a.SERIAL# ||''';' as killstment
from v$session a
where a.STATUS = 'ACTIVE'
and a.USERNAME not in ('SYS', 'SYSTEM')
order by
a.LAST_CALL_ET desc ,a.username,a.MACHINE ,a.command, a.EVENT, a.SQL_ID ,a.SID;
复制代码


发现有个 for update 的 sql 并发量大的时候部分请求 LAST_CALL_ET 列的值能达到 6 秒,for update 导致了所有请求被串行执行,影响了并发能力。我们经过分析业务逻辑后,用 sequence 暂时替换 for update 语句,但是我们没有源码,没法修改,后来又通过 010 editor 直接修改二进制文件,通过 010 editor 查询找到了 for update 语句,顺利替换。


替换后,4 台 C 服务器 tps 达到了 580,提升了 2.7 倍(580/210),系统初步具备了横向扩展能力


4.第三次瓶颈定位。


经过上一步改造,4 台 C 服务器时系统的 tps 提升了 2.7 倍,但是并没有提升到 4 倍(210*4=840),没有线性提升,说明还是有别的瓶颈,又通过 dba 上边给的 sql 发现 insert 语句偶尔耗时也很长,在 1s 左右,EVENT 等待事件是 IO 事件,DBA 同事给修改了 redo log file 大小(这个是测试环境 Oracle,之前没有优化),从默认的 50M,修改为 1G, tps 提升到了 640 (还没提升到 4 倍,也就是说还有瓶颈,可能还是数据库,但因为数据库暂时没办法抓取到毫秒级的耗时 sql,没再继续追查)


经过这几次性能提升,加上我们测试服务器配置都不高,如果线上服务器性能预估能达到 1000tps,基本满足眼前需求,因此就没再继续进行性能优化。


5.程序进程随机挂掉问题。


压测过程中,C 服务器进程经常随机挂掉,通过 tail -f /var/log/messages 发现生成了 core dump 文件,但是又被系统自动删除了。董建查到了开启 core dupm 文件的方法,如下:


a、ulimit -c


查看是否为 0,如果为 0,表示 coredump 文件设置为 0,需要修改为不限制


ulimit -c unlimited
复制代码


b、修改/etc/abrt/abrt-action-save-package-data.conf


ProcessUnpackaged = yes
复制代码


修改后进程又崩溃时 core dump 文件生成了,进入 core dump 目录进行调试


gdb 脚本路径 coredump


bt 显示堆栈信息


1557385818730041636.png


继续执行如下命令


f 0


1557385940619005067.png


set print pretty on
info local //显示当前函数中的局部变量信息。
复制代码


1557385958240060013.png


通过 p 命令查看里边变量的值


1557385972529098668.png


发现变量 thishost->h_addr_list 的值为 null


我们分析可能是并发请求时有方法不是线程安全的导致这个值为 null,从而引起了进程 crash,继续调试。


在 gdb 中 set logging on 把调试信息输出到文件


1557385988259045673.png


thread apply all bt 输出所有的线程信息。


退出 gdb


grep --color -i clientconnect -C5 gdb.txt
复制代码


1557386019141074009.png


确实有两个线程并发在访问


1557386229214033131.png


通过 ida 工具反编译 so,最终定位到以下语句在并发时有问题,thishost 中的变量可能会被另一个线程在一瞬间初始化为 null。


thishost = gethostbyname((const char *)hostname);
ip = inet_ntoa(*(struct in_addr *)*thishost->h_addr_list);
复制代码


根据我们的项目特点,因为我们没有远程调用,C 服务端 1 和 C 服务端 2 都部署在了同一台服务器上,所以我们通过修改二进制把地址暂时写死成了 127.0.0.1,把 ip = inet_ntoa(*(struct in_addr _)_thishost->h_addr_list);修改成了空指令,重新部署后没再出现系统崩溃的问题。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/245


2020-02-11 17:43554

评论

发布
暂无评论
发现更多内容

react源码解析13.hooks源码

buchila11

React React Hooks

音视频学习--SRTP优化

Fenngton

音视频 传输协议 签约计划第二季

音视频学习--VLC优化

Fenngton

音视频 RTSP 签约计划第二季

JVM分代回收机制和垃圾回收算法

Ayue、

JVM 技术专题合集

JVM类加载机制

Ayue、

JVM 技术专题合集

【LeetCode】赎金信Java题解

Albert

算法 LeetCode 12月日更

自动驾驶车辆控制 最终项目作业 实现分析 易筋 ARTS 打卡 Week 78

John(易筋)

ARTS 打卡计划

大厂算法面试之leetcode精讲20.字符串

全栈潇晨

算法 LeetCode

看动画学算法之:二叉搜索树BST

程序那些事

数据结构 算法 程序那些事 12月日更

react源码解析14.手写hooks

buchila11

React React Hooks

音视频学习--新codec适配和兼容

Fenngton

音视频 视频编解码 签约计划第二季

音视频学习--X264码率控制起航

Fenngton

音视频 视频编解码 签约计划第二季

音视频学习--日常开发踩坑系列(1)

Fenngton

音视频 传输协议 签约计划第二季

flutter如何从TextWidget复制文本【Flutter专题17】

坚果

flutter 28天写作 12月日更

音视频学习合集

Fenngton

内容合集 签约计划第二季

【Dart 专题】Map 集合小结~

阿策小和尚

28天写作 0 基础学习 Flutter Android 小菜鸟 12月日更

一次redis节点宕机引发的后续操作--部署哨兵集群

为自己带盐

redis redis哨兵模式 28天写作 签约计划第二季 12月日更

架构训练营 Week1 学习总结

红莲疾风

「架构实战营」

纯css实现117个Loading效果(上)

德育处主任

CSS 大前端 纯CSS 特效

JVM 性能诊断工具

Ayue、

JVM 技术专题合集

DDD领域驱动设计落地实践系列:工程结构分层

慕枫技术笔记

后端 架构师 签约计划第二季

架构训练营 -- 模块一

LJK

架构训练营

程序员写作模版献给懵逼的你

jerry

了解 JVM 的方法调用

Ayue、

JVM 技术专题合集

大厂算法面试之leetcode精讲19.数组

全栈潇晨

算法 LeetCode

「2021年11月复盘」买了个小太阳很暖和

宋天伦

复盘

RocketMQ存储设计到底强在哪?

慕枫技术笔记

架构 后端 28天写作 12月日更

日志归一管理的一种解决方案

为自己带盐

redis elasticsearch 28天写作 签约计划第二季 12月日更

Java面向对象精讲【上】

XiaoLin_Java

面向对象 java基础 12月日更

23种设计模式第一种——单例模式

李子捌

28天写作 12月日更

纯css实现117个Loading效果(中)

德育处主任

CSS css3 大前端 纯CSS

巧用工具提升无源码系统的性能和稳定性_行业深度_杨振、董建_InfoQ精选文章