Dubbo的超时和重试

Dubbo的超时和重试,第1张

Dubbo的超时和重试

文章目录
  • 超时原理
  • 设置级别
  • 超时设置的优先级
  • 超时是针对消费端还是服务端?
  • 超时设置方式
  • 服务超时设置的代码实例
    • 场景一:服务消费者设置超时时间3秒,服务提供者设置超时时间5秒
    • 场景二:服务消费者设置超时时间5秒,服务提供者设置超时时间3秒
  • 总结

超时原理
  • Dubbo默认采用了netty做为网络组件,它属于一种NIO的模式。
  • 消费端发起远程请求后,线程不会阻塞等待服务端的返回,而是马上得到一个ResponseFuture,消费端通过不断的轮询机制判断结果是否有返回。
  • 因为是通过轮询,轮询有个需要特别注要的就是避免死循环,所以为了解决这个问题就引入了超时机制,只在一定时间范围内做轮询,如果超时时间就返回超时异常。
设置级别
  • 针对方法设置超时时间
  • 在服务方设置超时时间
  • 在调用方设置超时时间
超时设置的优先级
  • 客户端(consumer)方法级>服务端(provider)方法级>客户端(consumer)接口级>服务端(provider)接口级>客户端(consumer)全局>服务端(provider)全局
超时是针对消费端还是服务端?
  • 超时是针对消费端的,消费端会抛出TimeoutException 而服务器端仅仅是一个 warn日志
超时设置方式
  • 基于XML方式的超时配置
    • 服务提供者xml方式超时配置如下:
 全局配置

 接口类配置

 方法配置
  • 服务消费者xml 方式配置如下:
 全局配置

 接口类配置

 方法配置
  • 基于注解方式的超时配置
    • 服务提供者注解方式配置
@Slf4j
@DubboService(timeout = 5000)
public class TestDubboTimeOutFacadeImpl implements TestDubboTimeOutFacade {

    @Override
    public void sendMessage(String param) {
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("_________________服务提供者设置的超时时间是5s");
    }
}
  • 服务消费者注解方式配置
    @DubboReference(timeout = 3000)
    private TestDubboTimeOutFacade testDubboTimeOutFacade;
服务超时设置的代码实例 场景一:服务消费者设置超时时间3秒,服务提供者设置超时时间5秒

服务提供者注解方式配置

@Slf4j
@DubboService(timeout = 5000)
public class TestDubboTimeOutFacadeImpl implements TestDubboTimeOutFacade {

    @Override
    public void sendMessage(String param) {
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("_________________服务提供者设置的超时时间是5s");
    }
}

服务消费者注解方式配置

    @DubboReference(timeout = 3000)
    private TestDubboTimeOutFacade testDubboTimeOutFacade;

执行结果如下:
消费者端报错:

Caused by: java.util.concurrent.ExecutionException: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2022-01-06 15:06:59.482, end time: 2022-01-06 15:07:02.513, client elapsed: 0 ms, server elapsed: 3031 ms, timeout: 3000 ms, request: Request [id=92, version=2.0.2, twoway=true, event=false, broken=false, data=null], channel: /127.0.0.1:50076 -> /127.0.0.1:7890
	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1928)
	at org.apache.dubbo.rpc.AsyncRpcResult.get(AsyncRpcResult.java:181)
	at org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker.invoke(AsyncToSyncInvoker.java:61)
	at org.apache.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(ListenerInvokerWrapper.java:78)
	at com.dahai.video.dubbotrace.DubboTransferTraceIdFilter.invoke(DubboTransferTraceIdFilter.java:43)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
	at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:89)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
	at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:51)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
	at com.dahai.video.dubbotrace.DubboTransferUserLidFilter.invoke(DubboTransferUserLidFilter.java:33)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
	at org.apache.dubbo.rpc.filter.ConsumerContextFilter.invoke(ConsumerContextFilter.java:69)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
	at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)
	at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:82)
	... 107 more
Caused by: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2022-01-06 15:06:59.482, end time: 2022-01-06 15:07:02.513, client elapsed: 0 ms, server elapsed: 3031 ms, timeout: 3000 ms, request: Request [id=92, version=2.0.2, twoway=true, event=false, broken=false, data=null], channel: /127.0.0.1:50076 -> /127.0.0.1:7890
	at org.apache.dubbo.remoting.exchange.support.DefaultFuture.doReceived(DefaultFuture.java:210)
	at org.apache.dubbo.remoting.exchange.support.DefaultFuture.received(DefaultFuture.java:175)
	at org.apache.dubbo.remoting.exchange.support.DefaultFuture$TimeoutCheckTask.notifyTimeout(DefaultFuture.java:298)
	at org.apache.dubbo.remoting.exchange.support.DefaultFuture$TimeoutCheckTask.lambda$run$0(DefaultFuture.java:285)
	at org.apache.dubbo.common.threadpool.ThreadlessExecutor.waitAndDrain(ThreadlessExecutor.java:93)
	at org.apache.dubbo.rpc.AsyncRpcResult.get(AsyncRpcResult.java:179)
	... 121 more

服务提供者被重试3次

场景二:服务消费者设置超时时间5秒,服务提供者设置超时时间3秒

服务提供者注解方式配置

@Slf4j
@DubboService(timeout = 3000)
public class TestDubboTimeOutFacadeImpl implements TestDubboTimeOutFacade {

    @Override
    public void sendMessage(String param) {
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("_________________服务提供者设置的超时时间是5s");
    }
}

服务消费者注解方式配置

    @DubboReference(timeout = 5000)
    private TestDubboTimeOutFacade testDubboTimeOutFacade;

执行结果如下:
服务消费者端正常执行

服务提供者正常显示结果,不过有一个warn提醒

总结
  • 在Provider上尽量多配置Consumer端属性

    • 作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
    • 在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作为Consumer的缺省值。否则,Consumer会使用Consumer端的全局设置,这对于Provider不可控的,并且往往是不合理的
  • 在Provider可以配置的Consumer端属性

    • timeout,方法调用超时
    • retries,失败重试次数,缺省是2(表示加上第一次调用,会调用3次)
    • loadbalance,负载均衡算法(有多个Provider时,如何挑选Provider调用),缺省是随机(random)。还可以有轮训(roundrobin)、最不活跃优先(leastactive,指从Consumer端并发调用最好的Provider,可以减少的反应慢的Provider的调用,因为反应更容易累积并发的调用)
    • actives,消费者端,最大并发调用限制,即当Consumer对一个服务的并发调用到上限后,新调用会Wait直到超时。在方法上配置(dubbo:method )则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务。
  • Provider上可以配置的Provider端属性

    • threads,服务线程池大小
    • executes,一个服务提供者并行执行请求上限,即当Provider对一个服务的并发调用到上限后,新调用会Wait(Consumer可能到超时)。在方法上配置(dubbo:method )则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务。

感谢您的阅读,如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏哈。~~

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5698925.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-17
下一篇2022-12-17

发表评论

登录后才能评论

评论列表(0条)

    保存