服务性能优化过程

背景

组内有好几个线上服务,除了业务逻辑不一样,请求处理过程基本上都是一致的。这些服务的执行逻辑都非常简单,但是有几个问题:

  1. 单机QPS很低,需要很多台机器
  2. 99分位耗时比理论上的长很多
  3. 在服务的负载达到上限时,服务器的负载却非常低

上面的这些问题在财大气粗的公司面前都不是问题啊,性能不够加机器!性能不够加机器! 上游再一次过来反映超时问题时,为了壮年程序员的尊严,这次刚好有时间决定不再单纯的加机器,要把这个程序优化一下,用一次屠龙技。

技术栈:

语言:java
通信方式:thrift,server模式为THsHaServer
redis客户端:jedis
模型:xgboost
执行环境:docker,8核 8G
缓存集群:通信协议为redis,但实现方式和redis不一样

优化后结果

优化过程

想要提升程序的性能,首先需要找到程序的瓶颈所在,然后有针对的去进行优化。

流程分析

优化前流程图

在这里插入图片描述

这个流程图省略了业务处理逻辑,只展示了各个线程之间的交互关系。构造redis请求的那部分逻辑,其实使用了两个forkjoin线程池,但它们两个的逻辑非常类似,为了简化把它们合并到一个流程中了。流程图中有两个深红色的步骤,很明显的看出两个明显能影响性能的地方。

结合服务的执行环境,可以总结出以下问题:

线程数过多

由于操作系统对线程的抢占式调度,线程频繁的上下文切换会带来几个问题:

  1. 系统指令执行时间增长,对应的指标值为cpu.sys,造成cpu执行时间的浪费
  2. 单位时间内分配给执行用户态指令的时间减少,对应的指标为cpu.user
  3. 综上可看出,其不仅使机器负载升高,也会使执行单次任务耗时增长

两个阻塞

流程图中标红的两个步骤在执行时都会阻塞线程。其中thrift-server是在阻塞等待所有的redis结果,forkjoin中是在阻塞等待redis返回结果,网络通信使用的是同步io模式

线程从运行状态切换为阻塞状态时,会发生一次线程上下文切换并且线程需要等待被重新调度。这是在操作系统层面的影响。

假设服务同时接收到40个请求,从流程图中可以看出,此时服务最多同时能发送86个redis请求,而要想让服务能通时执行40个任务,则必须要同时发送2000 = 40 * 20个redis请求。如果将f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值