1、压测工具

1.1.MeterSphere

2、系统参数配置优化

2.1.用户请求阻塞,进入线程池阻塞队列

2.2.1 问题发现

TPS上不去,通过skywalking查询是否有请求阻塞的情况或者频繁GC或者GC时间过长的情况,发现服务存在请求阻塞进入线城池阻塞队列的情况。

2.2.2 参数配置修改

修改web容器-undertown参数配置

# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
server.undertow.io-threads=16

# 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
server.undertow.worker-threads=256

# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
server.undertow.buffer-size=1024

# 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region
server.undertow.buffers-per-region=1024

...

2.2.Gateway服务CPU占用过高

2.2.1 问题发现

Gateway服务CPU一直处于高负载状态。

2.2.2 问题定位

查看服务配置以及网上查找相关资料,定位到可能是hystrix隔离参数的问题

hystrix隔离参数配置

2.2.3 为什么要隔离

比如我们的Gateway服务可能会将用户请求转发到后面的多个服务去,其中某个服务A的接口耗时比较长,并且在某一段时间内很多用户同时访问A服务,消耗掉了系统大部分资源,这个时候,如果有用户想要调用服务B的接口,由于资源不足,导致无法访问,因此就需要对Gateway服务依赖的服务进行隔离,保证不同的服务之间相互不受影响。

https://www.cnblogs.com/hzzjj/p/15956974.html

2.2.4 隔离的两种方式

Hystrix的隔离策略有两种:

 

  • THREAD(线程隔离)
hystrix:
  command:
    default:
      circuitBreaker:
        sleepWindowInMilliseconds: 5000 #定义在断路器打开后,Hystrix 将在多长时间内进入"半开"状态,允许一部分流量通过以检测服务是否恢复。在此配置中,设置为5000毫秒(5秒)。
      execution:
        timeout:
          enabled: true #指定是否启用超时。在此处,超时功能已启用
        isolation:
          strategy: THREAD #确定 Hystrix 在执行命令时使用的隔离策略。这里选择了线程隔离(THREAD),这意味着每个命令将在自己的线程中执行,以避免由于一个命令的问题而影响其他命令
          thread:
            interruptOnTimeout: true #当超时发生时,指定是否应该中断执行该命令的线程。设置为 true,表示如果命令超时,将中断线程
            timeoutInMilliseconds: 60000 #指定命令执行的最大时间。在此处,设置为60000毫秒(60秒),即60秒内如果命令未完成,将被视为超时
  threadpool:
    default:
      coreSize: 128 #指定线程池的核心线程数。在此处,设置为128个线程
      maximumSize: 256 #指定线程池的最大线程数。在此处,设置为256个线程
      maxQueueSize: 512 #指定线程池等待队列的最大大小。当所有核心线程和最大线程都处于活动状态,并且队列已满时,后续任务将被拒绝执行。在此处,设置为512
      queueSizeRejectionThreshold: 512 #当队列的大小达到此阈值时,新任务将被拒绝执行。在此处,设置为512,与最大队列大小相同
      allowMaximumSizeToDivergeFromCoreSize: true #指定是否允许最大线程数超过核心线程数。设置为 true,允许最大线程数达到或超过核心线程数
  • SEMAPHORE(信号量隔离)
hystrix:
  command:
    default:
      circuitBreaker:
        sleepWindowInMilliseconds: 5000
      execution:
        timeout:
          enabled: true
        isolation:
          strategy: SEMAPHORE
          semaphore:
            maxConcurrentRequests: 200  # 设置默认信号量为200

2.2.5 两种隔离方式的适用场景

  1. 线程池隔离:适用于处理大量并发请求的情况。由于每个线程都有独立的执行路径,可以避免一个请求的问题影响到其他请求。此外,通过为每个依赖项使用独立的线程池,可以更好地控制资源的使用和隔离潜在的故障。
  2. 信号量隔离:适用于处理高吞吐量、低延迟的场景。由于信号量不限制并发请求的数量,因此在处理大量并发请求时,性能表现可能优于线程池隔离。但是,如果某个请求需要很长时间才能完成,可能会导致其他请求被阻塞或回退。

2.3.Gateway服务堆外内存泄漏

2.3.1 问题发现

压测过程中,一旦请求数量上去之后,Gateway就会打印出内存泄露的日志。

2.3.2 问题解决

参考资料

由于spring-cloud-gateway中依赖了webflux,webflux中又依赖了netty,从netty的报错信息来看,正是由于使用了netty中的ByteBuf,但是未释放掉(未调用release方法)。

https://netty.io/wiki/reference-counted-objects.html

初始版本:

spring-boot.version:2.2.5.RELEASE
spring-cloud-gateway.version:2.2.2.RELEASE
spring-boot-starter-webflux.version:2.2.5.RELEASE
spring-boot-starter-reactor-netty.version:2.2.5.RELEASE
reactor-netty.version:0.9.5.RELEASE

升级后版本:

spring-boot.version:2.2.13.RELEASE
spring-cloud-gateway.version:2.2.8.RELEASE
spring-boot-starter-webflux.version:2.2.13.RELEASE
spring-boot-starter-reactor-netty.version:2.2.13.RELEASE
reactor-netty.version:0.9.16.RELEASE

2.4.慢接口查询,优化代码

2.4.1 慢接口查询,优化代码

  1. 通过skywalking查看对应接口的trace日志
  2. 通过arthas的trace指令获取指定方法的执行时间
  3. 给常用的业务表创建合适的索引

2.4.2 Mycat配置调整

  1. 通过上个步骤排查到许多mapper接口执行时间很长,长达十几秒
  2. 电商W系统中部分服务并非直接连接数据库,而是通过mycat做了分库,然后查看了mycat的配置,首先是将mycat中打印到Console的日志配置取消,发现速度直接大幅提升,可以判断mycat服务本身输出到console的日志对执行请求的影响是很大的。
  3. mycat其他配置参数
processorBufferChunk(处理器缓冲区大小):指定用于处理数据的缓冲区大小,以字节为单位。增加此值可提高处理大型查询和数据传输的性能。
processors(处理器数量):指定处理器线程的数量,根据服务器上可用的 CPU 核心数量进行调整。增加此值可更有效地利用可用的 CPU 资源。
processorExecutor(处理器执行器):确定每个处理器可以同时执行的最大任务数。增加此值可改善并行性和整体吞吐量。
processorBufferPoolType(处理器缓冲池类型):选择处理器使用的缓冲池类型,可以是 DirectByteBufferPool、ByteBufferArena 或 NettyBufferPool。
idleTimeout(空闲超时时间):设置空闲连接保持打开的时间。适当的超时时间可避免资源浪费和频繁的连接建立开销。
dataNodeIdleCheckPeriod(数据节点空闲检查间隔):调整检查数据节点空闲连接的频率。较短的间隔可能导致更频繁的检查,但可以更及时地释放资源。
useOffHeapForMerge(合并操作是否使用堆外内存):启用合并操作的堆外内存可以减少垃圾收集开销,并提高性能。
memoryPageSize(内存页大小)和 spillsFileBufferSize(溢出文件缓冲区大小):微调内存页大小和溢出文件缓冲区大小,以优化内存使用和磁盘 I/O 性能。
useStreamOutput(是否使用流式输出):启用流式输出可减少内存消耗,并改善对流式传输大型结果集的处理。
systemReserveMemorySize(系统保留内存大小):为 MyCAT 的内部操作分配适当的内存量,以确保性能稳定。
handleDistributedTransactions(分布式事务处理):根据需要调整分布式事务的处理方式。