写点什么

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

  • 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:43780

评论

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

iMile 利用 Zadig 多云环境周部署千次,跨云跨地域持续交付全球业务

Zadig

DevOps 持续交付 跨境电商 自动化运维 Zadig

火山引擎入选国内首个《边缘计算产业全景图》

火山引擎边缘云

云计算 云原生 边缘计算 火山引擎 火山引擎边缘计算

web前端培训 | 34 道 Vue 高频面试题

@零度

Vue 前端开发

3个最佳实践助力企业改善供应链安全

SEAL安全

安全 软件供应链 第三方风险

基于信通院 Serverless 工具链模型的实践:Serverless Devs

阿里巴巴云原生

阿里云 开源 云原生 Serverless Devs

图像边缘检测的新方向——量子算法

启科量子开发者官方号

tensorflow 边缘计算 图像处理 量子计算 量子算法

纯CSS 波点背景 🏀

德育处主任

css3 前端 纯CSS css特效 6月月更

墨天轮“高可用架构”干货文档分享(含Oracle、MySQL、PG资料124篇)

墨天轮

MySQL 数据库 oracle postgresql 高可用

架构实战营模块五作业

Geek_Q

架构

2022年第一季度保险服务数字化跟踪分析

易观分析

保险 消费金融

DataKit 作为本地获取数据的 API 服务器

观测云

从第三次技术革命看企业应用三大开发趋势

葡萄城技术团队

Numpy 的研究仿制 1

祖维

c Numpy

等保测评结论为差,是不是表示等保工作白做了?

行云管家

等保 等保测评

云创平台+播放器SDK,腾讯云音视频新工具助力视频生产、终端能力全面升级

科技热闻

《网络是怎么样连接的》读书笔记 - WEB服务端请求和响应(五)

懒时小窝

网络

《网络是怎么样连接的》读书笔记 - 服务器端的局域网中(四)

懒时小窝

网络

自主可控再下一城!首套国产ARTIQ架构量子计算测控系统发布

启科量子开发者官方号

算力 量子计算机 量子计算 离子阱 启科量子

瓜分1000+万奖金池,昇腾AI创新大赛2022实力赋能开发者

极客天地

微博评论高可用高性能计算架构

地下地上

架构实战营

防范企业数据泄露,就用网络安全产品堡垒机!

行云管家

数据库 网络安全 堡垒机 数据审计

手把手教你安装jdk8配置环境变量

不凡~

wallys/m.2/Adapter card(one pcie1x to 4 x Mini PCIE)

wallys-wifi6

wallys/ IPQ4019/IPQ4029 /Access Point Wireless Module Dual band 11AC Wave2 Module

wallys-wifi6

有了HTTP,为什么还要RPC?

C++后台开发

网络编程 RPC HTTP C++后台开发 C++开发

新朝旧将 vite和webpack煮酒论英雄

转转技术团队

vite webpack

使用 Gerrit + Zadig 实现主干开发主干发布(含字节跳动飞书实践)

Zadig

DevOps 分支管理 敏捷实践 研发协作 开发模式

攻防演练之战前扫雷:漏洞管理的5大措施

青藤云安全

主机安全 资产安全 漏洞防护 攻防演练

wallys/ IPQ4018/IPQ4028/Access Point Wireless Module Dual band 11AC Wave2 Module

wallys-wifi6

技术分享| 融合调度中的广播功能设计

anyRTC开发者

音视频 调度 实时消息 快对讲 广播

京东联盟API - 万能转链接口 - 京品库接口 - 接口定制

江苏京酷电子商务有限公司

京东 API JSON格式化 开放api

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