1、Gateway隔离问题导致CPU高负载

多个服务请求报错。查看监控,一个服务产生大量请求,占用了gateway大部分CPU资源,其他服务请求占用很少,其他服务经常报错。

添加机器,gateway进行隔离。

每个模块服务应当隔离,各占固定的gateway资源,相互不影响。

2、Gateway服务报错

下发单子时,经常会有一些单子下发不下来,业务日志也没有。查看gateway日志时,发现报错信息。搜索资料,nacos的请求数收到限制,默认100并发,后面改了配置增加到1000。

线上生成问题排查_sql

参考资料后确定大概率是nacos中网关的hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests配置未设置好

线上生成问题排查_gateway_02

gateway的请求数收到限制,默认100并发,后面改了配置增加到1000。

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds:  120000
          semaphore:
            maxConcurrentRequests: 1000   //最大请求数
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

参考资料:

1、 SpringCloud-Hystrix 报 could not acquire a semaphore for execution

2、 网关默认最大并发量过低问题


3、mysql死锁问题

业务反馈某个接口一直报错,查看日志发现数据库死锁(Deadlock found when trying to get lock; try restarting transaction)。

线上生成问题排查_sql_03


页面excel导入数据,发现很多失败的。排查结果是mq消费者里面调feign,feign熔断了,于是把消费者放到feign对应的接口所在的项目里,进行本地消费。然后发现存在很多数据库死锁。

排查步骤:

1、使用SHOW ENGINE INNODB STATUS;查询mysql最近一次死锁日志,LATEST DETECTED DEADLOCK块,查看发生死锁的sql

线上生成问题排查_生产问题_04

2、去代码里找到执行此段sql的位置

3、在代码里附近找到操作发生死锁sql的同一张表的其他sql

线上生成问题排查_sql_05

4、查看日志里发生死锁的索引,及其构成

线上生成问题排查_mysql_06

线上生成问题排查_生产问题_07

5、对比死锁信息及死锁附近sql进行分析

线上生成问题排查_sql_08

行锁的兼容矩阵

 

Gap

Insert Intention

Record

Next-Key

Gap

兼容

兼容

兼容

兼容

Insert Intention

冲突

兼容

兼容

冲突

Record

兼容

兼容

冲突

冲突

Next-Key

兼容

兼容

冲突

冲突

表注:横向是已经持有的锁,纵向是正在请求的锁。

死锁产生的必要条件有:1、临界资源 2、循环等待 3、不可剥夺 4、请求并保持 破坏其中一个均可打破死锁。

通过日志分析,事务1获得并持有间隙锁gap1,事务2获得并持有间隙锁gap2,此时事务1执行插入操作,插入的数据在事务2所持有的间隙锁gap2中间,于是等待事务2释放间隙锁gap2,此时事务2执行到了插入操作,同样插入的数据在事务1持有的gap1中间,事务1与事务2形成互相等待对方释放资源,发生死锁。mysql通过策略对事务2进行回滚释放gap2,此时事务1获取到了资源完成了插入操作。

对附近sql进行分析

线上生成问题排查_生产问题_09

附近sql就只有这个删除,mysql加锁是对索引进行加锁的,通过explain对sql的执行计划进行分析,删除走的索引就是产生死锁的索引

线上生成问题排查_死锁_10

由于delete语句中的条件无法唯一锁定一条记录,因此会加上间隙锁,与日志分析一致

线上生成问题排查_mysql_11

因此要解决这个问题,去掉间隙锁的占用即可,于是采用先根据条件查询出id,根据id去删除,将间隙锁降级为行锁,减少临界资源的占用即可。

经实际验证,改了以后,批量导入,未产生死锁。