关于网关超时的一些思考与解决方案
2023年09月01日
开发接口的时候经常会发现,一些需要执行大量操作的接口,在逻辑处理上存在处理缓慢的问题的时候,前端经常会出现504 gateway timeout的错误,导致接口的可用性变差。
为什么会有504错误在微服务中,接口调用都是链式的,即是说一次接口调用伴随着多个并行和串行的子任务。如果子任务中某一环节发生处理缓慢的情况,且一直有请求在发送,就会导致改环节下未完成的子任务越来越多,从而让服务器执行效率下降,直至耗尽内存资源宕机。网关此时就作为一个流量控制的工具,在接口未能及时返回的情况下,应该阻止这种情况发生,所以网关会监听一个接口的响应时间,并在接口超时后及时阻断请求,返回504错误。
解决方案一般出现504错误,说明接口内的业务处理逻辑仍有需要优化的地方。目前自己在工作中常见的处理方法有以下几种。
异步处理。即对请求优先返回响应,但是让子任务继续执行。这种做法完美避开了网关超时的可能,但这并不是一个推荐的做法。首先它违背了网关对于异常流量阻断的原则,使得网关无法正确监听接口的实际执行时间。其次子任务执行缓慢的根本问题依旧没有解决,在多请求的情况下仍然会发生服务处理效率下降的问题。最后,异步处理还带来了问题定位上的问题,即很难通过一个完整的链路定位到问题。
多线程。如果业务逻辑中存在大量的独立任务,可以考虑使用多线程来并行执行。多线程可以显著提高接口效率,但是亦有诸多限制。首先是问题定位,多线程下的问题定位会变得困难,无法通过日志打印时间来定位。其次是对线程数量的控制,如果控制不当,一样会消耗服务器过多的资源。
消息队列。在一些链式调用中,可以通过消息队列来发送和接收消息。消息队列可以做到异步的功能,而且由于队列可以作为阻塞队列使用,能够容许消费端执行缓慢,也侧面解决了接口频繁调用导致的内存资源不足的问题。
————————————————————————————————————————————
最近逛掘金,看到了一篇不错的文章https://mp.weixin.qq.com/s?__biz=Mzg3NzU5NTIwNg==&mid=2247502660&idx=1&sn=17166646f82412cd81955930f799ab4e&chksm=cf22146df8559d7bcf9becd82e1d8006c35a781e5dbd0a79e0a9e121803ee40d6eae7ebd7ccb&token=1371687559&lang=zh_CN#rd,也介绍了一些优化接口的经验,可以记录一下。