1 查询类接口

一 mysql数据库查询超时问题

1 查询字段是否存在索引,索引是否失效

索引是个老生常谈的问题了, 需要特别注意下面几个点

唯一的值必须要建立唯一索引

比如订单号,售后单号,上门取件单号等必须要唯一的值,有助于数据准确

两个字段组成唯一的值必须要建立联合唯一索引

比如pps数据库表t_poroduct_supply 产品和商家供应商关系表, 正常来说supplier_id+product_id 肯定是唯一的值, 这里就要把这两个字段建立唯一索引, 避免产生脏数据, 查询效率也会变高, 需要注意一下联合索引的最左前缀, 只用product_id查询索引会失效的

同一个数据库下, 两张表同一个字段字符集不一样联查时索引会失效

这个问题曾经就遇到过,一张表是utf8格式, 另一张表是utf8mb4格式, 即使关联字段都是varchar类型, 索引也会失效

2 是否有分页?一次性返回数量是否过多导致堆内存溢出

问题描述:

在运费险白名单用户配置功能就遇到过这个问题,当时前端调用了两个接口, 一个是已分配用户列表, 一个是待分配用户列表(全部), 查询已分配用户列表时没有携带分页参数, 导致查询了全部已分配的用户数据(大概几十w条) , 直接后果就是pps服务器堆内存溢出,pps数据库cpu飙升 , 导致服务不可用

解决方案:

任何需要查询列表的接口, 必须都要使用分页, 前端可以采用默认查询第一页+ 支持精准搜索 方式展示,

拒绝一次性把所有列表数据拿到后在内存中做模糊匹配

3 数据库机器cpu是否正常?有没有可能其他慢SQL导致cpu飙升

这里主要看下执行时长, 平均返回行, 看是否存在执行时间过长,返回数据量过大的SQL产生, 具体页面在哪 怎样优化查询

4 数据库数据量大,根据某一状态查询变慢,可以默认加时间只查询最近一段周期数据

这个问题在上门取件列表根据未支付状态搜索遇到过, 表格数据总数大概一百万条数据, 用支付状态搜索时会SQL查询超时, 支付状态只存在几个值,加索引也没什么意义, 只能采用减少查询总量的方式去优化这部分查询, 只查最近一个月的数据, 大概有几万条, 查询效率就很高了

5 针对统计类数据,要是实时性不高,查询时间长,耗费cpu性能

缓存方案

在BMS系统首页有大量的统计数据, 这些统计数据查询的SQL一般在几百毫秒到几秒之间, ,因为这部分查询对实时性不高, 就加了接口切面级别的缓存, 避免存在相同条件的SQL短时间内重复请求数据库

统计表方案

针对于一些统计数据, 比如产品每日的维权率, 转化率等查询涉及到数据量很大时, 就可以将需要统计的数据存放在统计表中, 直接查询这张统计表就可以了

二 Redis超时问题

1 使用keys命令阻塞线程

因为redis是单线程执行的, 执行keys命令时底层是遍历所有的key匹配, 当一个库下面数据量很大时, 需要匹配的时间特别长, 而且会阻塞其他命令, 间接影响其他功能

问题代码:

下面代码是更新了店铺选款列表的配置后, 清空对应所有店铺下的缓存, 这里使用了keys模糊查询导致线程阻塞

优化代码:

因为店铺数量本来就不多,最多也就10多个店铺, 索性全部查询出来循环删除

三 调用第三方接口查询超时问题

1 查询出的数据需要持久化

在使用上门取件功能时, 在调用下单接口会出现一定比例的接口超时, 超时原因是在调用第三方下单接口服务响应时长>5s, 成功响应后执行入库操作时, 因为超过了当前切面事务最大执行时间5s, 会抛出事务超时异常, 导致的问题是上门取件在服务商那边创建成功了, 但是在我们系统却找不到对应的订单, 后期用户也无法支付运费, 对平台造成一定的损失

问题代码:

可以看到在执行操作数据库操作时, 并没有针对出现的异常做重试, 导致需要新增的数据没有落库

优化代码:

抽离出操作DB的方法insertData(), 在执行抛出事务超时异常时,会启动一个子线程重试调用insertData(), 后续提示用户"下单成功,刷新页面", 避免用户重复点击造成重复下单

2 查询出的数据不需要持久化

这种就是只针对于查询的需求了, 可能因为第三方接口不稳定导致接口响应慢, 在要求实时性不是很高时, 可以做一段时间的缓存, 减轻调用的qps

2 新增/更新类接口

1 批量操作代替循环操作

循环操作不管是DB还是OTS, 还有远程服务的调用, 每次循环都会产生的连接请求时间, 这都是一种资源的浪费, 优化方法就是请求数据在内存中整合好, 只调用一次持久化操作

2 大量数据分批操作

当需要新增或者更新几千条数据时, 一次性操作对数据库压力造成一定影响, 可以将需要操作的集合分片, 结合实际场景使用串行执行或者并行执行的方式

3 涉及复杂流程的单一操作可以并发执行

具体场景:

单独的新增业务复杂, 需要进行各种校验,不同状态执行不同流程, 这种情况下就不适合使用批量操作, 可以使用并发操作提高效率

代码案例:

例如填写售后单物流方法,一个方法执行时长大概100ms左右, 要是批量填写几百个串行操作耗时过长

优化代码:

使用callback多线程执行方式, 并行操作填写物流流程,大大提升了串行执行的效率, 并且将修改成功失败结果标识响应给用户

3 调用远程接口响应超时

1 针对非核心逻辑可以使用异步方案处理降低总的接口调用时间

1 非核心逻辑 :

非核心逻辑可以理解为不需要和核心逻辑强绑定关系的逻辑, 可以不在一个事务里, 非核心逻辑的失败也不要影响核心逻辑的执行,

具体场景 :

1 例如下单扣减库存, 库存扣减(非核心逻辑)失败不要响应下单成功的结果

2 上门取件接单后给用户发送接单短信, 发短信(非核心逻辑)的失败不要影响取件单接单状态的变更

3 仓库收货错误商家原因处罚商家, 处罚商家(非核心逻辑)的失败不要影响仓库收货步骤

2 异步方案

消息队列:

消息队列是一种通知消息, 可以解除业务之间的耦合关系, 从接口调用的强耦合转为消息传递的松耦合, 上游不用关心下游成功与否, 都不影响主要流程执行, 一般作用在跨项目间业务的交互

案例1 : 下单扣减库存mq

下单时把对应的扣减库存参数传递个下游, 下游执行扣减库存逻辑, 不影响整个上游下单流程

案例2 : 仓库收货错误生成处罚给商家

仓库收货后, 把生成处罚相关参数传递给处罚模块, 处罚模块根据通知执行新增处罚流程,处罚生成与否, 不影响仓库收货流程

子线程执行 :

子线程也是一种优化方法耗时的一种方法, 核心逻辑执行完成后, 直接给客户端响应回去, 后续流程可以启动子线程继续执行, 这种是针对于实时性要求不高, 可以提升接口响应效率的一种手段

案例1 : 同步ES操作

更新库存接口中, 核心逻辑修改库存执行后, 启动一个子线程同步ES, 减少用户等待时间, 需要特别注意一下, 子线程内部一定要上报异常日志, 不然子线程内部报错后不能在loghub上看到

2 单独优化响应时长偏高的接口

有些接口业务很复杂, 调用了很多的远程调用, 偶尔就会不明原因的超时, 这时候可以去阿里云后台开一下接口整体执行时间, 看下到底是哪个接口执行耗时导致的

案例1 : 优化修改供货变更库存及库存状态逻辑

在整体调用链路中发现com.weidiango.pps.stock.impl.ProductSkuStockServiceImpl#batchAddSkuStockPlan接口时长占了总时长很大的比例, 在不影响整体业务流程的情况下, 保证这个接口入参,出参不变, 优化其中内部逻辑

问题代码:

主要逻辑是for循环内串行执行添加补货计划核心逻辑(修改库存, 修改库存状态, 上报操作记录), 这个流程在sku量不大的情况下执行时间还可以接受, 当sku数量>100个时, 耗时会>5s 导致超时

优化代码:

采用callback多线程优化方式, 并行执行更新补货计划逻辑, 因为更新的sku都归属于一个产品, 把更新供货状态和上报操作记录放在外层, 保证只需要执行一次即可, 从原来100个sku时长6s左右 优化到1s左右

3 涉及到多次调用不同的远程服务,可以通过串行改并行的方式调用,统一获取返回值

具体场景:

比如在下单时,

需要用到用户地址信息, 需要远程调用用户地址信息, 产品信息,

需要远程调用产品详情快照保存起来, 优惠卷信息,

需要调用查询最终用户需支付金额 等一系列的接口,

在分布式项目下, 各个模快信息都需要远程调用查询, 一个接口就算100ms, 涉及到的接口多起来总体下单时长也是很长的

解决方案 :

可以使用callback线程模式并行查询, 统一接收返回值做后续流程处理

高并发下解决方案:

上面说到的用户信息查询接口需要调用用户查询接口、积分查询接口 和 成长值查询接口,然后汇总数据统一返回。

那么,我们能不能把数据冗余一下,把用户信息、积分和成长值的数据统一存储到一个地方,比如:redis,存的数据结构就是用户信息查询接口所需要的内容。然后通过用户id,直接从redis中查询数据出来,不就OK了?

如果在高并发的场景下,为了提升接口性能,远程接口调用大概率会被去掉,而改成保存冗余数据的数据异构方案。

但需要注意的是,如果使用了数据异构方案,就可能会出现数据一致性问题。

用户信息、积分和成长值有更新的话,大部分情况下,会先更新到数据库,然后同步到redis。但这种跨库的操作,可能会导致两边数据不一致的情况产生。

4 避免在循环中调用远程方法,提供批量查询接口只调用一次

批量操作的这种思想不管是在前端调用后端接口, 后端远程接口调用, 操作DB, 操作OTS, 能使用批量执行尽量用批量执行, 除非接口层面不支持批量操作, 单针对于这种可以采用callback多线程方式优化

4 排查接口超时常用工具

1 调用耗时剖析

一个接口超时, 先入为主的必然是这个接口的调用路径, 上下游调用链路, 每个链路执行耗时情况, 具体原因具体分析

以com.weidiango.api.pps.service.ItemTagLibraryService@selectTagByItemId接口为例可以看出该接口内部执行的耗时情况

2 资源饼图分析

这里可以看出底层储存执行的耗时情况, 如果是mysql或者redis 耗时占比很大, 就要到对应的数据库下面看下数据库的cpu情况和慢SQL情况

3 mysql实例的cpu和慢日志分析

主要关注在接口超时的时间范围内, 数据库cpu的波动和执行慢SQL的语句,

观察是因为超时接口的慢SQL导致cpu上升从而查询变慢,

还是其他的慢SQL执行导致cpu上升而影响了当前执行的接口耗时

4 Redis实例的cpu和慢日志分析

当执行一条耗时的redis命令时(例如keys), 可以看到cpu会显著升高, 慢日志中也会打印出这条命令, 当前执行的方法会一直阻塞执行这条命令等待redis执行结束, 共享当前redis实例的其他请求会因为redis线程池满从而把请求拒绝掉, 影响其他操作redis的业务执行

5 超时日志的比例与参数查看

可以通过loghub查询某个接口日志的总数与超时总数, 分析出大概的超时比例, 根据参数分析大概超时的原因

com.weidiango.reserve.svc.Impl.ReserveOrderServiceImpl#add 以这个接口为例

生产事故总结篇(2) 接口响应超时优化方案相关推荐

  1. 第三方支付接口响应超时处理方法

    问题:调用第三方支付接口超时怎么办? 解决方法:调用接口时设置超时时间,当接口超过60秒未返回结果,自动将改订单设置为处理中,然后由定时任务调用查询接口,同时如果用户下拉刷新页面也会发起单笔交易查询. ...

  2. java接口经常变动前端怎么办_Java进程故障排查(CPU资源占用高,接口响应超时,功能接口停滞等)...

    故障分析 # 导致系统不可用情况(频率较大): 1)代码中某个位置读取数据量较大,导致系统内存耗尽,进而出现Full GC次数过多,系统缓慢: 2)代码中有比较消耗CPU的操作,导致CPU过高,系统运 ...

  3. java 监控 m_Java接口响应超时监控

    为什么要监控 服务化接口是提供服务的,接口正确性.稳定性是最最重要的,在保证正确的同时需要尽量提高接口响应时间. 有的团队会有专门的工具来对系统响应时间.吞吐量做监控,但如果团队没有这种"待 ...

  4. tomcat服务器接口响应超时,Tomcat请求超时

    如果您试图阻止请求运行太长时间,那么在Tomcat中设置超时将无济于事.正如克里斯所说,您可以为Tomcat设置全局超时值.但是,从" Apache Tomcat连接器-通用方法超时&quo ...

  5. 接口访问超时 504 Gateway Time-out 优化方案

    我们在调用GET请求获取数据的接口中,由于接口的处理逻辑复杂.查询的数据库表过多.nginx设置的超时时间过短和慢sql等原因,会造成接口请求了20秒左右,都没有结果返回,浏览器就会报错504 Gat ...

  6. (十一)jmeter接口自动化难点系列---设置响应超时时间

    在做jmeter接口测试的时候,有时服务器问题,导致我们的接口一直在请求,而无法得到返回. 所以我们需要用到jmeter的一个功能响应超时自动停止请求. 在jmeter中, 有一项设置名称为timeo ...

  7. Postman进阶篇(十二)-在脚本中使用pm对象访问接口响应数据(pm.response.*)

    在之前的文章中介绍过postman中的两个脚本--pre-request script或test script,在这两个脚本中都有使用到pm对象.(pre-request script详细介绍.Tes ...

  8. java 接口超时控制_Java接口请求响应超时的解决办法

    最近在做报表需求的时候,遇到一个问题: 前台给个请求,由于后台执行逻辑需要很长时间,因此导致页面响应超时. 在网上查询相关资料,找到了几种解决方案: 通过修改配置文件,延长响应时间: rest.Rea ...

  9. Spring Transactional还能导致生产事故?

    在Spring中进行事务管理非常简单,只需要在方法上加上注解@Transactional,Spring就可以自动帮我们进行事务的开启.提交.回滚操作.甚至很多人心里已经将Spring事务与@Trans ...

最新文章

  1. 什么是CUDA编程 统一计算架构
  2. 中国数字化进程比发达国家快,小程序让我感到自豪 | IT领袖峰会
  3. 腾讯员工中66%是研发,用C++最多,去年新写12.9亿行代码
  4. 什么是document对象?如何获取文档对象上的元素?_javascript自学记录:Document类型...
  5. 蜗牛慢慢爬 LeetCode 6. ZigZag Conversion [Difficulty: Medium]
  6. 大动作!这所“国字头”大学获批成立12个新学院
  7. mysql plsql cursor_Oracle--plsql游标创建和使用
  8. Cocos2d-x场景功能描述的生命周期
  9. 关于redis的db的使用几号db的问题
  10. java restful开发规范_restful api 开发规范
  11. ubuntu 挂载优盘
  12. Android中使用sax解析XML
  13. 最新Erphpdown v13.11modown8.02主题破jie版去授权无域名限制版本
  14. 基于文本语义的智能问答机器人——工业应用
  15. 在线裁剪图片 Jcrop
  16. python输出excel指定列为文本格式_POI设置excel某列值为文本格式
  17. 如何在html中做超链接,如何在HTML上做一个超链接?
  18. 摘要-Amira用户指南
  19. 4K智能AI双目自动跟踪云台摄像机
  20. sqlserver如何删库跑路

热门文章

  1. win10 Windows无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目。
  2. macOS安装Cplex+yalmip
  3. 电脑硬件故障维护小全(十三)
  4. 如何评论stem教育的特点
  5. 关于sql2008卸载后再安装问题
  6. python日记Ddy19——Pandas速查中文手册
  7. 大学物理第七章“机械波”复习笔记
  8. 钉钉群机器人定时发送消息并@所有人
  9. MMA-Cadence下spectre仿真数据导出matlab数据处理
  10. 批处理经典入门教程!(从不懂到高手)