性能优化--如何保证自己服务的SLA与稳定性?

前言

公司业务处于稳定发展期,前期系统快速迭代,业务快速支持,堆积了很多技术债务,其中,系统的性能就是关键的一部分,随着业务代码的堆叠,性能逐步裂化,需要快速优化,这里主要对接口SLA性能的稳定性保证做一个梳理。

影响SLA的关键点

影响服务/接口的SLA的关键点主要在:

  1. 依赖RPC下游服务:
    主要是下游的服务,微服务化后,单一服务职责、边界更清晰,需要资源或者数据,会直接从下游获取,比如依赖订单信息,调用订单服务;依赖用户信息,调用用户服务。下游的服务SLA是否裂化,也是影响自身服务SLA的关键点。
  2. 内部自身代码设计、逻辑:
    a. 线程池:
    参数、队列等
    b. 调用下游RPC合理性:
    编排是否合理,
    有没有重复PRC调用
    对下游超时之后的处理
    c. 代码是否高效:
    循环、序列化、锁 、算法等
  3. 系统指标:
    GC、磁盘、load、网络等

接口示意图

如下图:
一个普通服务的接口内部逻辑如下:
性能优化--如何保证自己服务的SLA与稳定性?_第1张图片
该接口提供上游查询服务功能,服务本身依赖下游商品、订单、营销、用户、规则、展销服务的接口,并且这些服务之间互相有依赖,不能同时并行调用(比如调用展示服务的接口,需要商品、订单、营销服务的数据),这样多个服务,其实变为三个阶段,基本阶段之间是串行调用。
拿到依赖数据之后,做相应逻辑处理,这块儿就是服务的自身代码逻辑。
最终将所有数据 + 业务逻辑处理后,组装返回给上游。

优化策略

1. 依赖RPC下游服务:
这个其实没有什么好的办法,需要根据下游的RPC服务的SLA来定。如果下游超过了它们的SLA,需要推动下游去进行优化,这个一般上游没有办法控制。
如果需要控制,保证自己SLA不裂化,只能根据重要性对下游进行降级,比如下游超时后,直接返回空数据。
2. 内部自身代码设计、逻辑
a.线程池:
这里主要关注线程池的配置,高流量情况下线程池出现大量等待情况,会导致该线程池的处理结果不能返回。
过多的线程池是否可以合并,有些服务线程池可能会很多,这里好处是可以不同业务逻辑做一定隔离,坏处就是导致线程资源的膨胀、浪费,进而影响系统的容量,导致过多的ygc,进而影响服务执行时间,SLA。
b.调用下游RPC合理性:
编排合理性:目前RPC的调用顺序是合理的,有没有不需要串行的调用,进行了串行调用?
重复RPC:这个比较好理解,循环对下游的调用,要求下游提供批量接口进行合并调用。笔者之前优化过的代码有过拿出一批id,对数据库循环获取每条的数据。
下游超时:下游的超时时间必须做好严格的控制和设计,因为一旦下游超时,而服务设置的超时间较久的话,会直接拖垮自身服务,导致自身服务性能急剧下降。
c.代码是否高效:
循环:有没有无效的循环,是否可以用空间换取一定时间?比如冒泡排序的算法,其中一种算法就是存储一个标记位,让整个算法的复杂度降低。
序列化:序列化是否高效,这个也是非常关键的一环,选用合适的高效的序列化算法,节省的时间也是可观的。可看笔者之前的文章:点击这里
:并发过程中锁的使用,有没有热锁,如果解开。有没有更好的实现方式?
锁粒度是否过细了?笔者之前优化过循环过程中加锁,其实可以将锁放在循环外。
算法:从自身业务逻辑特性考虑,是否有更好的顺序、逻辑处理。
3. 系统指标:
这里提到的gc、load、磁盘、网络,需要其他运维同学一起关注。

总结:

常见的优化策略和优化工具结合,才能达到保证自己的系统的SLA的目的。除此之外,还需要做一些定期的压测和演练,保证自己的系统不裂化。

你可能感兴趣的:(调优,常见问题分析,高效编程,程序人生,经验分享,性能优化,微服务,java)