当holding服务向market-data服务发送请求时,holding服务会在等待market-data服务回应的同时消耗资源。为这一调用设置合适的截止时间能够限制资源消耗的时间。
可以在HTTP请求方法中设置超时时间。对于HTTP调用,如果迟迟没有收到任何响应数据,应该超时终止;但如果只是响应结果下载比较慢,这种情况下不应该超时终止。
和数据计算相比,网络通信是比较慢的,所以失败的速度很重要。在分布式系统中,有些错误几乎是立刻就发生的,比如,某个依赖服务可能因为内部程序错误而快速失败。但还有许多失败是非常慢的,比如,服务因为请求量过载会响应得特别慢,从而调用方服务在等待响应结果时的资源消耗可能是徒劳的,因为结果可能永远也不会返回。
这种耗时很长的失败正说明为微服务通信设置恰当的时间期限(合理的时间段内超时)的重要性。如果不设置一个上限,不响应的问题很容易就蔓延到整个微服务依赖链。事实上,最后期限时间的缺失会扩大问题的影响范围,因为一个服务在无休止地等待问题解决时也在消耗资源。
设置期限时间是一个难题。如果设置的时间过长,而服务又没有响应的话,调用服务就是在消耗不必要的资源;如果设置的时间过短,又会导致某些耗时比较长的请求失败率升高。
选择合适的期限时间需要平衡时间约束来最大限度提高请求成功的机会。
对于许多微服务应用,可以为每种不同的交互分别设置截止时间,比如holding服务对market-data服务的调用一直是10秒的期限。而一种更加优雅的方式是为整个操作设置一个绝对的期限时间,然后将剩余时间传给下游协作方。
如果不使用最后期限时间传播方案的话,在一个请求中保持最后期限的一致性就会比较困难,比如,如果holding服务等待market-data服务的时间超过了API网关这一上层服务所指定的整体的期限,那么holding服务也是在浪费资源。
设想一下,多个服务之间的依赖链路。每个服务需要花费一定的时间才能完成它的工作,并且能够预见到对应的协作方也要花费一些时间。如果这些时间各不相同的话,那么设置一个静态的预期时间就不合适了。
服务可以为调用方的执行耗时设定期望值;由于失败或延迟的缘故,这些期望值差距很大,并会加剧这些失败的影响程度。
如果服务是通过HTTP相互调用的,可以使用一个自定义的HTTP报头(如X-Deadline: 1000)来传递最后期限时间,这个值会被用来设置后续的HTTP客户端调用的读超时时间。许多RPC框架(如gRPC)也会在请求上下文中明确地实现这个期限时间传播的机制。
除了http/https协议请求,其它TCP类型协议,比如FTP、Kafka、MQ等类型消息也是一样需要设置合理的超时时间。
摘取自 摩根·布鲁斯和保罗·A.佩雷拉的《微服务实战》
网友评论