接口突然超时10宗罪。。。

 

往期热门文章:

 
1、2022全球程序员薪酬报告:字节在榜,上海薪资近9万美元
2、撸了个牛逼的项目,可在14个平台运行,爽!
3、换掉 VMware?轻量级虚拟机,横空出世!
4、Spring Boot三步就能完成日志脱敏,简直太哇塞了!
5、推荐一款基于 SpringBoot + Vue 的前后端分离实战项目!

前言

不知道你有没有遇到过这样的场景:我们提供的某个API接口响应时间原本一直都很快,但在某个不经意的时间点,突然出现了接口超时

也许你会有点懵,到底是为什么呢?

今天跟大家一起聊聊接口突然超时的10个原因,希望对你会有所帮助。

1.网络异常

接口原本好好的,突然出现超时,最常见的原因,可能是网络出现异常了。比如:偶然的网络抖动,或者是带宽被占满了。

1.1 网络抖动

经常上网的我们,肯定遇到过这样的场景:大多数情况下我们访问某个网站很快,但偶尔会出现网页一直转圈,加载不出来的情况。

有可能是你的网络出现了抖动,丢包了。

网页请求API接口,或者接口返回数据给网页,都有可能会出现网络丢包的情况。

网络丢包可能会导致接口超时。

2.1 带宽被占满

有时候,由于页面或者接口设计不合理,用户请求量突增的时候,可能会导致服务器的网络带宽被占满的情况。

服务器带宽指的是在一定时间内传输数据的大小,比如:1秒传输了10M的数据。

如果用户请求量突然增多,超出了1秒10M的上限,比如:1秒100M,而服务器带宽本身1秒就只能传输10M,这样会导致在这1秒内,90M数据就会延迟传输的情况,从而导致接口超时的发生。

所以对于有些高并发请求场景,需要评估一下是否需要增加服务器带宽。

2.线程池满了

我们调用的API接口,有时候为了性能考虑,可能会使用线程池异步查询数据,最后把查询结果进行汇总,然后返回。

如下图所示:136c3911c9a1c1cfa8497cbe8d7a917a.png调用远程接口总耗时 200ms = 200ms(即耗时最长的那次远程接口调用)

在java8之前可以通过实现Callable接口,获取线程返回结果。

java8以后通过CompleteFuture类实现该功能。我们这里以CompleteFuture为例:

public UserInfo getUserInfo(Long id) throws InterruptedException, ExecutionException {final UserInfo userInfo = new UserInfo();CompletableFuture userFuture = CompletableFuture.supplyAsync(() -> {getRemoteUserAndFill(id, userInfo);return Boolean.TRUE;}, executor);CompletableFuture bonusFuture = CompletableFuture.supplyAsync(() -> {getRemoteBonusAndFill(id, userInfo);return Boolean.TRUE;}, executor);CompletableFuture growthFuture = CompletableFuture.supplyAsync(() -> {getRemoteGrowthAndFill(id, userInfo);return Boolean.TRUE;}, executor);CompletableFuture.allOf(userFuture, bonusFuture, growthFuture).join();userFuture.get();bonusFuture.get();growthFuture.get();return userInfo;
}

这里我用到了executor,表示自定义的线程池,为了防止高并发场景下,出现线程过多的问题。

但如果用户请求太多,线程池中已有的线程处理不过来,线程池会把多余的请求,放到队列排队,等待空闲线程的去处理。

如果队列中排队的任务非常多,某次API请求一直在等待,没办法得到及时处理,就会出现接口超时问题。

这时候,我们可以考虑是否核心线程数设置太小了,或者有多种业务场景共用了同一个线程池。

如果是因为核心线程池设置太小,可以将其调大一些。

如果是因为多种业务场景共用了同一个线程池,可以拆分成多个线程池

3.数据库死锁

有时候接口超时得有点莫名其妙,特别是遇到数据库出现死锁的时候。

你提供的API接口中通过某个id更新某条数据,此时,正好线上在手动执行一个批量更新数据的sql语句。

该sql语句在一个事务当中,并且刚好也在更新那条数据,可能会出现死锁的情况。

由于该sql语句执行时间很长,会导致API接口的那次更新数据操作,长时间被数据库锁住,没法即使返回数据,而出现接口超时问题。

你说坑不坑?

所以建议在执行数据库批量操作前,一定要评估数据的影响范围,不要一次性更新太多的数据,不然可能会导致很多意想不到的问题。

此外,批量更新操作建议在用户访问少的时段执行,比如:凌晨。

4.传入参数太多

有时候,偶尔的一次接口超时,是由于参数传入太多导致的。

例如:根据id集合批量查询分类接口,如果传入的id集合数据量不多,传入几十个或上百个id,不会出现性能问题。毕竟id是分类表的主键,可以走主键索引,数据库的查找速度是非常快的。

但如果接口调用方,一次性传入几千个,甚至几万个id,批量查询分类,也可能会出现接口超时问题。

因为数据库在执行sql语句之前,会评估一下耗时情况,查询条件太多,有可能走全表扫描更快。

所以这种情况下sql语句可能会丢失索引,让执行时间变慢,出现接口超时问题。

因此我们在设计批量接口的时候,建议要限制传入的集合的大小,比如:500。

如果超过我们设置最大的集合大小,则接口直接返回失败,并提示给用户:一次性传入参数过多

该限制一定要写到接口文档中,避免接口调用方,在生产环境调用接口失败而踩坑。要在接口开发阶段通知到位。

此外,如果接口调用方要传入的参数就是很多怎么办?

答:可能是需求不合理,或者系统设计有问题,我们要尽量在系统设计阶段就规避这个问题。

如果我们重新进行系统设计改动比较大的话,有个临时的解决方案:在接口调用方中多线程分批调用该接口,最后将结果进行汇总。

5.超时时间设置过短

通常情况下,建议我们在调用远程API接口时,要设置连接超时时间读超时时间这两个参数,并且可以动态配置。

这样做的好处是,可以防止调用远程API接口万一出现了性能问题,响应时间很长,把我们自己的服务拖挂的情况发生。

比如:你调用的远程API接口,要100秒才返回数据,而你设置的超时时间是100秒。这时1000个请求过来,去请求该API接口,这样会导致tomcat线程池很快被占满,导致整个服务暂时不可用,至少新的请求过来,是没法即使响应的。

所以我们需要设置超时时间,并且超时时间还不能设置太长。

并发量不大的业务场景,可以将这两个超时时间设置稍微长一点,比如:连接超时时间为10秒,读超时时间为20秒。

并发量大的业务场景,可以设置成秒级或者毫秒级

有些小伙伴为了开发方便,在多种业务场景共用这两个超时时间。

某一天,在并发量大的业务场景中,你将该超时时间改短了。

但直接导致并发量不大的业务场景中,出现调用API接口超时的问题。

因此,不建议多种业务场景共用同一个超时时间,最好根据并发量的不同,单独设置不同的超时时间。

6.一次性返回数据太多

不知道你有没有遇到过这样的需求:我们有个job,每天定时调用第三方API查询接口,获取昨天更新的数据,然后更新到我们自己的数据库表中。

由于第三方每天更新的数据不多,所以该API接口响应时间还是比较快的。

但突然有一天,该API接口却出现了接口超时问题。

查看日志发现,该API接口一次性返回的数据太多,而且该数据的更新时间相同。

这就可以断定,该API接口提供方进行了批量更新操作,修改了大量的数据,导致该问题的发生。

即使我们在job中加了失败重试机制,但由于该API一次性返回数据实在太多太多,重试也很有可能会接口超时,这样会导致一直获取不到第三方前一天最新的数据。

所以第三方这种根据日期查询增量数据的接口,建议做成分页查询的,不然后面没准哪一天,遇到批量更新的操作,就可能出现接口超时的问题。

7. 死循环

死循环也会导致接口超时?

死循环不应该在接口测试阶段就发现了,为什么要到生产环境才发现?

确实,绝大部分死循环问题,在测试阶段可以发现。

但有些无限递归隐藏的比较深,比如下面的情况。

死循环其实有两种:

  1. 普通死循环

  2. 无限递归

7.1 普通死循环

有时候死循环是我们自己写的,例如下面这段代码:

while(true) {if(condition) {break;}System.out.println("do samething");
}

这里使用了while(true)的循环调用,这种写法在CAS自旋锁中使用比较多。

当满足condition等于true的时候,则自动退出该循环。

如果condition条件非常复杂,一旦出现判断不正确,或者少写了一些逻辑判断,就可能在某些场景下出现死循环的问题。

出现死循环,大概率是开发人员人为的bug导致的,不过这种情况很容易被测出来。

还有一种隐藏的比较深的死循环,是由于代码写的不太严谨导致的。如果用正常数据,可能测不出问题,但一旦出现异常数据,就会立即出现死循环。

7.2 无限递归

如果想要打印某个分类的所有父分类,可以用类似这样的递归方法实现:

public void printCategory(Category category) {if(category == null || category.getParentId() == null) {return;} System.out.println("父分类名称:"+ category.getName());Category parent = categoryMapper.getCategoryById(category.getParentId());printCategory(parent);
}

正常情况下,这段代码是没有问题的。

但如果某次有人误操作,把某个分类的parentId指向了它自己,这样就会出现无限递归的情况。导致接口一直不能返回数据,最终会发生堆栈溢出

建议写递归方法时,设定一个递归的深度,比如:分类最大等级有4级,则深度可以设置为4。然后在递归方法中做判断,如果深度大于4时,则自动返回,这样就能避免无限递归的情况。

8.sql语句没走索引

你有没有遇到过这样一种情况:明明是同一条sql,只有入参不同而已。有的时候走的索引a,有的时候却走的索引b?

没错,有时候mysql会选错索引,甚至有时会不走索引。

mysql在执行某条sql语句之前,会通过抽样统计来估算扫描行数,根据影响行数、区分度、基数、数据页等信息,最后综合评估走哪个索引。

有时候传入参数1,sql语句走了索引a,执行时间很快。但有时候传入参数2,sql语句走了索引b,执行时间明显慢了很多。

这样有可能会导致API接口出现超时问题。

必要时可以使用force index来强制查询sql走某个索引。

9.服务OOM

我之前遇到过这样一种场景:一个根据id查询分类的接口,该id是主键,sql语句可以走主键索引,竟然也出现了接口超时问题。

我当时觉得有点不可思议,因为这个接口平均耗时只有十几毫秒,怎么可能会出现超时呢?

但从当时的日志看,接口响应时间有5秒,的确出现了接口超时问题。

最后从Prometheus的服务内存监控中,查到了OOM问题。

其实该API接口部署的服务当时由于OOM内存溢出,其实挂了一段时间。

当时所有的接口都出现了请求超时问题。

但由于K8S集群有监控,它自动会将挂掉的服务节点kill掉,并且在容器中重新部署了一个新的服务节点,幸好对用户没造成太大的影响。

10.在debug

我们有时候需要在本地开发工具,比如:idea中,直接连接测试环境的数据库,调试某个API接口的业务逻辑。

因为在开发环境,某些问题不太好复现。

为了排查某个bug,你在请求某个本地接口时,开启了debug模式,一行行的跟踪代码,排查问题。

走到某一行代码的时候,停留了很长一段时间,该行代码主要是更新某条数据。

此时,测试同学在相关的业务页面中,操作更新了相同的数据。

这种也可能会出现数据库死锁的问题。

由于你在idea的debug模式中,一直都没有提交事务,会导致死锁的时间变得很长,从而导致业务页面请求的API接口出现超时问题。

往期热门文章:
1、IntelliJ IDEA终于支持对Redis 的可视化窗口操作了,真香!
2、ChatGPT能接入微信了!
3、Java 反射慢?它到底慢在哪?
4、当我去了不到 20 人的 IT 公司后。。。
5、GitHub 被超火的 ChatGPT 霸榜!
6、Java使用 try catch会影响性能?
7、Java使用 try catch会影响性能?
8、原来count(*)是接口性能差的真凶!
9、大公司病了,这也太形象了吧!!!
10、全球最大资源站创始人被抓,但网站还会继续活下去

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/56044.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPT-4杀疯了!Copilot X重磅发布!AI写代码效率10倍提升,码农遭降维打击...

点击下方卡片,关注“CVer”公众号 AI/CV重磅干货,第一时间送达 点击进入—>【计算机视觉】微信技术交流群 转载自:新智元 | 编辑:编辑部 【导读】GPT-4加强版Copilot来了!刚刚,GitHub发布了新一代代码生…

何恺明MIT求职演讲现场:提前三小时就有排队!超百页PPT回顾CV发展!

点击下方卡片,关注“CVer”公众号 AI/CV重磅干货,第一时间送达 点击进入—>【计算机视觉】微信技术交流群 杨净 鱼羊 发自 凹非寺转载自:量子位(QbitAI) 何恺明MIT求职演讲,真成AI圈大型追星现场了&…

英语四级作文备战全攻略

前言 今天是2016年11月21日,距离12月17日的CET4还有26天,距离2017年研究生考试初试还有34天,距离2017年国家公务员考试还有6天,距离2016年结束还有41天,距离2017年春节还有68天。 如果你不去安排好自己的时间&#…

2021年英语四级作文

2021年英语四级作文 2021年6月第1套:人类对电脑科技上瘾 作文题目: Directions: For this part, you are allowed 30 minutes to write an essay titled “Are people becoming addicted to technology?”. The statement given below is for your r…

四六级作文模板

表格模板——图表类 In resent years, 主题词 is becoming increasingly prevalent at an amazing rate. It is generally agreed that the 比例大的那项 has playing a increasingly important role in our life, which has brought us a lot of benefits but has triggered …

宣讲:保研流程分享ustc信院夏令营预推免介绍

lail 来了来了不咕稿,说好的写一篇宣讲会的总结来着。 这是一个声明,因为里面有很多东西是自己的,如果跟各位佬意见相悖,那就是你对。 接下来讲保研流程,这是一个新奇的角度:从最终offer的角度 接下来是…

开始使用 Bing Chatbot 的 5 个简单步骤

Bing Chatbot 是一种对话式 AI 工具,它使用自然语言处理来回答您的查询并为您提供信息。这是一种无需进行大量研究即可快速获得问题答案的有效且有趣的方式。以下是有关如何开始使用 Bing Chatbot 的分步指南: 第 1 步:创建 Microsoft 帐户 …

APS高级排程在制鞋企业的应用

随着市场的生产制造和消费生产及变化,市场上各种品类的鞋履不断被细分,生产领域仍需要技术老提高产能和产品多样性。在大数据、物联网的发展带动下,智能运动鞋在设计下问世,运动鞋本身可以帮助检测个人的运动数据,包括…

基于python的电商运动服饰销售分析与预测系统

温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目背景 随着电⼦商务的蓬勃发展,⽹络服装销售已经逐渐成为消费者最为青睐的廉价购物渠道。本项目基于python网络爬虫从某电商平台抓取所有运动服饰的销售数据,分析不同品牌…

宝宝看的启蒙动画片哪里找?三款电视软件推荐,孩子启蒙不怕难

家里宝宝已经2岁2个月,最近开始让她慢慢学着自己刷牙,刚开始那几天还很乐意,但是现在越来越抗拒刷牙了……周末带她去朋友家玩了一天,回来居然主动说晚上要刷牙才睡觉,我震惊了,一问她才知道,原…

Locust性能测试入门案例及分布式压测

前言 大家好,我是洋子。最近好多身边人都阳了,记得保护好自己 性能测试已经成为作为测试工程师/测试开发工程师一项重要的专项能力 在抢红包、活动秒杀这种短时间内流量突增的场景,或者是健康宝这种使用用户超级多的场景,我们均…

【笔记】Hawkes Process:超详细带示例的讲解

最近准备学Hawkes Process, 但是找遍了百度,b站,谷歌和youtube,都没有找到通俗易懂的讲解。今天终于在拆老师(ChatGPT)的帮助下搞懂了!关于使用ChatGPT进行自学的Prompt可以看之前的笔记&#x…

用月壤实现太阳能发电,人类离「定居月球」又近一步 | 来自贝索斯蓝色起源...

Alex 发自 凹非寺量子位 | 公众号 QbitAI 用月球表面土壤搞太阳能发电?! 你没听错,有人用这种材料做出了太阳能电池,人类朝“在月亮上搞基建”又前进一步。 这个“幕后使者”,既非马斯克的SpaceX,也非NASA&…

python调用oepnai API

目录 apiAI官网介绍([Introduction](https://platform.openai.com/docs/api-reference/introduction))安装官方SDK认证(Authentication)申请API KEY请求组织(Requesting organization) 发送请求关于chat to…

在线作图|2分钟在线绘制三维PCOA图

三维PCoA PCoA(Principal Co-ordinates Analysis)分析即主坐标分析,可呈现研究数据相似性或差异性的可视化坐标,是一种非约束性的数据降维分析方法,可用来研究样本群落组成的相似性或相异性。它与PCA类似,通过一系列的特征值和特…

python绘制3D图表

pyecharts绘制3D图表 参数配置和说明 Grid3DOpts、Axis3DOpts为3D图标需要配置项 Grid3DOpts:三位坐标系配置项 class pyecharts.options.Grid3DOpts class Grid3DOpts(# 三维笛卡尔坐标系组件在三维场景中的宽度width: Numeric 200,# 三维笛卡尔坐标系组件在三维…

在线作图|2分钟在线绘制三维CCA图

​三维CCA 典型相关分析(Canonical Correlation Analysis)是研究两组变量之间相关关系的一种多元统计方法,它能够揭示出两组变量之间的内在联系。冗余分析(redundancy analysis, RDA)或者典范对应分析(can…

在线作图|2分钟绘制三维PCA图

三维PCA 主成分分析算法(PCA)是最常用的线性降维方法。PCA降维为了在尽量保证“信息量不丢失”的情况下,对原始特征进行降维,也就是尽可能将原始特征往具有最大投影信息量的维度上进行投影。将原特征投影到这些维度上&#xff0c…

Tikz 作图教程:pgfplots 宏包三维数据的可视化绘图

前一篇推文讲解了使用pgfplots 宏包导入二维数据和可视化绘图的方法。今天我们来介绍一下科研工作者常常用到的三维数据的导入与绘图的方法。 当一个函数关系式中出现了两个自变量时,我们需要用空间曲面来呈现其图像。 编辑之谈(知名origin 绘图公众号)最近一篇推…

plotly绘制3D图技巧

简介 Plotly 是一个非常强大的开源数据可视化框架,它通过构建基于 HTML 的交互式图表来显示信息,可创建各种形式的精美图表。本文所说的 Plotly 指的是 Plotly.js 的 Python 封装,plotly本身是个生态非常复杂的绘图工具,它对很多…