世界看点:佳禾智能、传音控股入股赣锋锂电 后者从事固态电池产业化开发
1月11日,记者查询天眼查发现,近日,江西赣锋锂电科技股份有限公司(下称“赣锋锂电”)发生工商变更,新增股东新余市城乡建设投资(集团)有限公
大家好,我是鱼皮。不知道你有没有遇到过这样的场景:我们提供的某个 API 接口,响应时间原本一直都很快,但在某个不经意的时间点,突然出现了接口超时。鱼皮最新原创项目教程,欢迎学习
也许你会有点懵,到底是为什么呢?
(资料图片)
今天咱们来聊聊接口突然超时的 10 个原因,希望对你会有所帮助。
1.网络异常接口原本好好的,突然出现超时,最常见的原因,可能是网络出现异常了。比如:偶然的网络抖动,或者是带宽被占满了。
1.1 网络抖动经常上网的我们,肯定遇到过这样的场景:大多数情况下我们访问某个网站很快,但偶尔会出现网页一直转圈,加载不出来的情况。
有可能是你的网络出现了抖动,丢包了。
网页请求 API 接口,或者接口返回数据给网页,都有可能会出现网络丢包的情况。
网络丢包可能会导致接口超时。
2.1 带宽被占满有时候,由于页面或者接口设计不合理,用户请求量突增的时候,可能会导致服务器的网络带宽被占满的情况。
服务器带宽指的是在一定时间内传输数据的大小,比如:1秒传输了10M的数据。
如果用户请求量突然增多,超出了1秒10M的上限,比如:1秒100M,而服务器带宽本身1秒就只能传输10M,这样会导致在这1秒内,90M数据就会延迟传输的情况,从而导致接口超时的发生。
2.线程池满了所以对于有些高并发请求场景,需要评估一下是否需要增加服务器带宽。
我们调用的API接口,有时候为了性能考虑,可能会使用线程池异步查询数据,最后把查询结果进行汇总,然后返回。
如下图所示:调用远程接口总耗时 200ms = 200ms(即耗时最长的那次远程接口调用)
在java8之前可以通过实现Callable接口,获取线程返回结果。
java8以后通过CompleteFuture类实现该功能。我们这里以CompleteFuture为例:
publicUserInfogetUserInfo(Longid)throwsInterruptedException,ExecutionException{finalUserInfouserInfo=newUserInfo();CompletableFutureuserFuture=CompletableFuture.supplyAsync(()->{getRemoteUserAndFill(id,userInfo);returnBoolean.TRUE;},executor);CompletableFuturebonusFuture=CompletableFuture.supplyAsync(()->{getRemoteBonusAndFill(id,userInfo);returnBoolean.TRUE;},executor);CompletableFuturegrowthFuture=CompletableFuture.supplyAsync(()->{getRemoteGrowthAndFill(id,userInfo);returnBoolean.TRUE;},executor);CompletableFuture.allOf(userFuture,bonusFuture,growthFuture).join();userFuture.get();bonusFuture.get();growthFuture.get();returnuserInfo;}
这里我用到了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. 死循环所以第三方这种根据日期查询增量数据的接口,建议做成分页查询的,不然后面没准哪一天,遇到批量更新的操作,就可能出现接口超时的问题。
死循环也会导致接口超时?
死循环不应该在接口测试阶段就发现了,为什么要到生产环境才发现?
确实,绝大部分死循环问题,在测试阶段可以发现。
但有些无限递归隐藏的比较深,比如下面的情况。
死循环其实有两种:
普通死循环无限递归7.1 普通死循环有时候死循环是我们自己写的,例如下面这段代码:
while(true){if(condition){break;}System.out.println("dosamething");}
这里使用了while(true)的循环调用,这种写法在CAS自旋锁中使用比较多。
当满足 condition 等于 true 的时候,则自动退出该循环。
如果 condition 条件非常复杂,一旦出现判断不正确,或者少写了一些逻辑判断,就可能在某些场景下出现死循环的问题。
出现死循环,大概率是开发人员人为的 bug 导致的,不过这种情况很容易被测出来。
还有一种隐藏的比较深的死循环,是由于代码写的不太严谨导致的。如果用正常数据,可能测不出问题,但一旦出现异常数据,就会立即出现死循环。
7.2 无限递归如果想要打印某个分类的所有父分类,可以用类似这样的递归方法实现:
publicvoidprintCategory(Categorycategory){if(category==null||category.getParentId()==null){return;}System.out.println("父分类名称:"+category.getName());Categoryparent=categoryMapper.getCategoryById(category.getParentId());printCategory(parent);}
正常情况下,这段代码是没有问题的。
但如果某次有人误操作,把某个分类的 parentId 指向了它自己,这样就会出现无限递归的情况。导致接口一直不能返回数据,最终会发生堆栈溢出。
8.sql语句没走索引建议写递归方法时,设定一个递归的深度,比如:分类最大等级有 4 级,则深度可以设置为 4。然后在递归方法中做判断,如果深度大于 4 时,则自动返回,这样就能避免无限递归的情况。
你有没有遇到过这样一种情况:明明是同一条 sql,只有入参不同而已。有的时候走的索引 a,有的时候却走的索引 b?
没错,有时候 mysql 会选错索引,甚至有时会不走索引。
mysql 在执行某条 sql 语句之前,会通过抽样统计来估算扫描行数,根据影响行数、区分度、基数、数据页等信息,最后综合评估走哪个索引。
有时候传入参数 1,sql 语句走了索引 a,执行时间很快。但有时候传入参数 2,sql语句走了索引 b,执行时间明显慢了很多。
这样有可能会导致 API 接口出现超时问题。
9.服务OOM必要时可以使用force index来强制查询sql走某个索引。
我之前遇到过这样一种场景:一个根据 id 查询分类的接口,该 id 是主键, sql 语句可以走主键索引,竟然也出现了接口超时问题。
我当时觉得有点不可思议,因为这个接口平均耗时只有十几毫秒,怎么可能会出现超时呢?
但从当时的日志看,接口响应时间有5秒,的确出现了接口超时问题。
最后从Prometheus的服务内存监控中,查到了OOM问题。
其实该API接口部署的服务当时由于OOM内存溢出,其实挂了一段时间。
当时所有的接口都出现了请求超时问题。
但由于K8S集群有监控,它自动会将挂掉的服务节点kill掉,并且在容器中重新部署了一个新的服务节点,幸好对用户没造成太大的影响。。
10.在debug我们有时候需要在本地开发工具,比如:idea中,直接连接测试环境的数据库,调试某个API接口的业务逻辑。
因为在开发环境,某些问题不太好复现。
为了排查某个 bug,你在请求某个本地接口时,开启了debug模式,一行行的跟踪代码,排查问题。
走到某一行代码的时候,停留了很长一段时间,该行代码主要是更新某条数据。
此时,测试同学在相关的业务页面中,操作更新了相同的数据。
这种也可能会出现数据库死锁的问题。
由于你在 idea 的 debug 模式中,一直都没有提交事务,会导致死锁的时间变得很长,从而导致业务页面请求的 API 接口出现超时问题。
欢迎学编程的朋友们加入我的编程知识星球,我会 1 对 1 解决你的问题,直播带你做出项目、为你定制学习计划和求职指导,还能获取海量编程学习资源,和上万名学编程的同学共享知识、交流进步。
往期推荐
我的学习小圈子
又一个新项目搞完啦!!!
寒假自学的小建议,弯道超车!
这样写SQL,同事说我坑。。
最适合程序员的画图工具?
1月11日,记者查询天眼查发现,近日,江西赣锋锂电科技股份有限公司(下称“赣锋锂电”)发生工商变更,新增股东新余市城乡建设投资(集团)有限公
随着国庆假期临近,不少银行及理财子公司推出国庆节专属理财产品。记者调查发现,由于业绩比较基准略高于其他同类型同期限理财产品,节日专
西陇科学股份有限公司独立董事 关于公司第五届董事会第十九次会议相关事项的独立意见 根据《上市公司独立董事规则》、《深圳证券交易所股票
(原标题:金石亚药:公司未收到相关举牌或要约收购有关通知)同花顺(300033)金融研究中心12月6日讯,有投资者向金石亚药(300434)提问,你
9月1日,拼多多旗下跨境电商出口平台Temu上线,预计9月16日正式开售。据悉,目前Temu上架了饰品、服装、鞋包、3C数码等多个品类的商品,并
《黎明杀机》主题恋爱模拟游戏《心醉神迷》今日Steam发售,截至发稿,本作获特别好评(543),好评率为94%。大量玩家在七夕这个日子甜蜜地打
近两年的显示行业,Mini LED的火爆程度大家有目共睹,从平板、到笔记本再到电视,各大行业头部品牌纷纷加入了Mini LED阵营。
3月15日晚,央视315晚会报道了软件下载平台“高速下载”陷阱的问题。记者在PC6下载站、桔梗下载站、腾牛网、ZOL软件下载等平台下载软件时都出现类似的问题。
AMD近日正式发布了3D V-Cache缓存堆叠版的锐龙7 5800X3D,拥有4MB二级缓存、32MB三级缓存、64MB外置缓存,合计达100MB,号称可击败i9-12900K,重夺最强游戏处理器称号。
Intel在欧洲地区的投资规模不亚于美国本土的投资计划,而且涉及范围更多,美国本土主要是半导体制造及研发,欧洲地区还有先进封装技术。
一直以来,微信PC版因为始终没有添加好友的功能而被用户吐槽,对上班族来说,想要添加好友,还要拿起手机操作,十分不便。
今天上午,锤子科技CEO罗永浩、OPPO首席产品官刘作虎和罗翔老师展开了一场真实的对话。
据浪潮官方发布的消息,在浪潮信息生态伙伴大会IPF2022大会上,浪潮信息发布了业内首款元宇宙服务器Meta Engine。
据浪潮官方发布的消息,在浪潮信息生态伙伴大会IPF2022大会上,浪潮信息发布了业内首款元宇宙服务器Meta Engine。
对于那些想要购买iPhone SE3的用户来说,今晚这款手机就要正式开售了,起售价为3499元,这是苹果公司史上最便宜的5G iPhone。
对于那些想要购买iPhone SE3的用户来说,今晚这款手机就要正式开售了,起售价为3499元,这是苹果公司史上最便宜的5G iPhone。
今天,realme为新机realme GT Neo3预热。该机搭载独立显示芯片,这是realme首款双芯手机,也是目前首款配备双芯片的天玑8100机型。
据美国媒体2月4日报道,澳大利亚政府日前发布“JP9102”军用通信卫星项目招标书,旨在帮助澳大利亚国防军提升军用
“应急救助暖人心,用心服务为老兵。”春节前夕,广东省佛山市三水区退役军人陈桂芳委托家人向区退役军人事务局送
王勇军(右二)为民兵应急分队队员讲解无人机操控方法。逯毅摄2021年10月,一纸命令,王勇军从中部战区陆军某部交
俄军“美洲虎”第四代防空预警系留气球系统。德国CargoLifter CL 160型军民两用高空气球。美军“战斗天星”小型
初春,暖阳驱散了闽南的湿冷。迎着和煦春风,记者来到第73集团军某旅,探访该旅组织的军娃“冬令营”。“我们是共
岁月从不败拼搏!邱冷掌心上写着:“老武 加油!”鼓励未进入决赛的队友;金博洋以赛季个人最佳成绩宣告“曾经的
“妈,您放心吧,我在部队可好了,不仅吃得好、住得暖,就连膝关节疼痛都治好了!”春节前夕,记者探访海拔4000多
春节前夕,第78集团军某旅与兄弟单位展开实兵对抗演练。该旅作为蓝方部队,对兵力火力进行作战编组时,以“按需混