今天我想和大家分享一个知识点。大概是我们平时开发系统做rpc通讯的时候,经常会设置两个参数:超时和重试。如果这两个参数设置不好,很可能会导致我们的系统崩溃,但是很多人可能不知道其中的问题,所以我今天就来告诉大家。
如果你长时间调用一个系统,无法返回,这个时候会发生什么?我们应该知道,您自己的系统依赖线程来接收外部请求。假设我们通过springboot内嵌的tomcat接收外部请求,其实tomcat会打开很多线程,每个http请求都会交给一个线程处理,如下图所示。
然后在一个线程得到一个请求并开始处理它之后,它会调用其他系统。如果因为他在过程中出现故障,需要很长时间调用其他系统,几秒钟都没有响应怎么办?那不容易,会导致tomcat的一个线程阻塞几秒,无法处理其他请求。那么这个时候,如果调用一个服务阻塞了所有线程,是否会导致新的请求到来而没有线程可以处理呢?如下图。
所以一般来说,我们要给其他服务的rpc调用设置一个超时,比如设置timeout=1s,也就是说如果我们调用其他系统超过1s,就会抛出异常,直接返回,这样就避免了我们的tomcat线程长时间被阻塞,如下图。
好了,
比如你把超时设置的太长,比如5s或者10s,可能是在极端情况下,比如对方系统故障,你要把每一个请求都退回5s或者10s,就不会出现上面说的问题。也就是tomcat的每个线程都要阻塞5s和10s才能返回,导致你的系统无法处理新的请求,如下图。
那么超时设置太短怎么办?比如设置timeout=500ms,那很好,这个可能也有很大的问题,因为有可能有一天,因为活动的流量很大,你调用的系统压力很大,导致cpu负载很高,然后通常300~400ms就能返回请求,今天500~600ms,刚好超过超时时间,就会导致你的大量请求。
因此,超时参数设置通常是这样设置的。对于你要调用的系统,你需要看它平时需要多长时间返回,然后可以设置为正常时间的50%以上。比如一般是100~200ms,偶尔顶峰是500ms,那么可以设置超时=800ms或者1s。
然后是重试参数,不能随意设置,尤其是一些调用其他系统写数据的接口。如果对其他服务的写接口设置重试,可能会出现某个写接口时间可能会稍长,导致超时错误的场景。因此,如果您再次尝试写入,数据可能会重复。所以通常建议可以为读接口设置重试参数,但最好为写接口设置。
好了,今天分享rpc超时和重试参数到此为止。