zoukankan      html  css  js  c++  java
  • dubbo超时重试

    dubbo超时重试概述

    consumer端和provider端都可以设置timeout。

    超时优先级:consumer方法级>provider方法级>consumer接口级>provider接口级>consumer级>provider级

    当consumer端调用超时,会触发重试调用。

    重试对应的配置属性是retries。默认的重试次数是2。就是说,当调用超时,会最多重试2次,如果仍然失败,会提示异常。

    对于查询或删除来说,接口重试是幂等的。

    对于新增数据,如果retries>0,则要做幂等处理,否则会造成重复数据入库而产生bug。安全起见,可单独设置retries=0。

    【说明】在直连的情况下,是不会触发重试的。

    代码

    服务接口定义:

    package dubbodemo.contract;
    
    public interface HelloWord {
        String say();
    
        String add(String str);
    }

    Provider application.yml dubbo配置:

    dubbo:
      application:
        name: zhanggz-dubbodemo
      registry:
    #    address: N/A
        address: zookeeper://127.0.0.1:2181
      protocol:
        port: 28088
        name: dubbo
      scan:
        base-packages: dubbodemo.provider
      provider:
        timeout: 2200
        retries: 3
    View Code

    Provider代码:

    package dubbodemo.provider;
    
    import dubbodemo.contract.HelloWord;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.RandomUtils;
    import org.apache.dubbo.config.annotation.Service;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @Slf4j
    @Service(retries = 3)
    @SpringBootApplication
    public class ProviderApplication implements HelloWord {
        public static void main(String[] args) {
            SpringApplication.run(ProviderApplication.class);
        }
    
        public String add(String str) {
            log.info("add入参:{}", str);
            long start = System.currentTimeMillis();
            try {
    //int i=1/0;
                try {
                    int r = RandomUtils.nextInt(1000, 2000);
                    log.info("sleep time={}", r);
                    Thread.sleep(r);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "test retry:" + str;
            } finally {
                log.info("duration={}", System.currentTimeMillis() - start);
            }
        }
    
        public String say() {
            return ("hello");
        }
    }
    View Code

    Consumer application.yml dubbo配置:

    dubbo:
      application:
        name: zhanggz-dubbodemo-consumer
      registry:
        address: zookeeper://127.0.0.1:2181
      #    address: N/A
      protocol:
        name: dubbo
      consumer:
        timeout: 1000
    #    retries: 0
    View Code

    Consumer代码:

    package dubbodemo.consumer;
    
    import dubbodemo.contract.HelloWord;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.dubbo.config.annotation.Reference;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DubboConsumerTest {
        @Reference(/*url = "dubbo://localhost:28088",*/)
        private HelloWord helloWord;
    
        @Test
        public void testAddRetry() {
            long start = System.currentTimeMillis();
            log.info("请求开始...");
            try {
                String str = helloWord.add("str");
                log.info("返回值={}", str);
            } finally {
                log.info("duration=={}", System.currentTimeMillis() - start);
            }
        }
    }
    View Code

    测试结论

    --------直连的情况下,测试dubbo调用超时。

    将Provider方法利用Thread.sleep(2000)来模拟超时。

    consumer不设置timeout(默认值=1000ms),改变provider的timeout值

    【provider】
    设置provider.timeout=1000 ,因为方法执行耗时是2000,会有WARN提示。

    2020-07-23 18:53:57.427 INFO 13356 --- [:20880-thread-2] dubbodemo.provider.ProviderApplication : duration=2000
    2020-07-23 18:53:57.432 WARN 13356 --- [:20880-thread-2] o.apache.dubbo.rpc.filter.TimeoutFilter : [DUBBO] invoke time out. method: add arguments: [str] , url is dubbo://192.168.40.69:20880/dubbodemo.contract.HelloWord?anyhost=true&application=zhanggz-dubbodemo&bean.name=ServiceBean:dubbodemo.contract.HelloWord&bind.ip=192.168.40.69&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=dubbodemo.contract.HelloWord&methods=add,say&pid=13356&qos.enable=false&register=true&release=2.7.3&side=provider&timeout=1000&timestamp=1595501612605, invoke elapsed 2005 ms., dubbo version: 2.7.3, current host: 192.168.40.69

    【provider】
    设置provider.timeout=2200, 方法耗时2000<2200,不会提示invoke timeout。

    2020-07-23 18:57:16.949 INFO 12280 --- [:20880-thread-2] dubbodemo.provider.ProviderApplication : duration=2000



    不管Provider如何设置timeout,因为Consumer的timeout=1000,所以consumer都会收到timeout异常。

    2020-07-23 18:53:56.273 INFO 13216 --- [ main] dubbodemo.consumer.DubboConsumerTest : duration==1040
    
    org.apache.dubbo.rpc.RpcException: Invoke remote method timeout. method: add, provider: dubbo://localhost:20880/dubbodemo.contract.HelloWord?application=zhanggz-dubbodemo-consumer&interface=dubbodemo.contract.HelloWord&lazy=false&pid=13216&qos.enable=false&register.ip=192.168.40.69&remote.application=&side=consumer&sticky=false, cause: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2020-07-23 18:53:55.250, end time: 2020-07-23 18:53:56.272, client elapsed: 106 ms, server elapsed: 916 ms, timeout: 1000 ms, request: Request [id=0, version=2.0.2, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=add, parameterTypes=[class java.lang.String], arguments=[str], attachments={path=dubbodemo.contract.HelloWord, interface=dubbodemo.contract.HelloWord, version=0.0.0}]], channel: /192.168.40.69:1813 -> /192.168.40.69:20880

    ----------------------------- Provider服务停止后,客户端无法启动

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubbodemo.consumer.DubboConsumerTest': Injection of @Reference dependencies is failed; nested exception is org.apache.dubbo.rpc.RpcException: Fail to create remoting client for service(dubbo://localhost:20880/dubbodemo.contract.HelloWord?application=zhanggz-dubbodemo-consumer&codec=dubbo&heartbeat=60000&interface=dubbodemo.contract.HelloWord&lazy=false&pid=5236&qos.enable=false&register.ip=192.168.40.69&remote.application=&side=consumer&sticky=false&timeout=2200): client(url: dubbo://localhost:20880/dubbodemo.contract.HelloWord?application=zhanggz-dubbodemo-consumer&codec=dubbo&heartbeat=60000&interface=dubbodemo.contract.HelloWord&lazy=false&pid=5236&qos.enable=false&register.ip=192.168.40.69&remote.application=&side=consumer&sticky=false&timeout=2200) failed to connect to server localhost/127.0.0.1:20880, error message is:Connection refused: no further information: /192.168.40.69:20880

    consumer端设置dubbo.consumer.check=false。则可以启动consumer服务。

    check属性说明:Check if service provider exists, if not exists, it will be fast fail

    不过,当调用远程服务的时候,由于远程服务处于停止状态,所以当然会报错。

    连接注册中心时的错误提示:

    org.apache.dubbo.rpc.RpcException: No provider available from registry 192.168.40.84:2181 for service dubbodemo.contract.HelloWord on consumer 192.168.40.69 use dubbo version 2.7.3, please check status of providers(disabled, not registered or in blacklist).

     直连的错误提示:

    org.apache.dubbo.rpc.RpcException: Failed to invoke remote method: add, provider: dubbo://localhost:20880/dubbodemo.contract.HelloWord?application=zhanggz-dubbodemo-consumer&check=false&interface=dubbodemo.contract.HelloWord&lazy=false&pid=12504&qos.enable=false&register.ip=192.168.40.69&remote.application=&side=consumer&sticky=false&timeout=2200, cause: message can not send, because channel is closed . url:dubbo://localhost:20880/dubbodemo.contract.HelloWord?application=zhanggz-dubbodemo-consumer&check=false&codec=dubbo&heartbeat=60000&interface=dubbodemo.contract.HelloWord&lazy=false&pid=12504&qos.enable=false&register.ip=192.168.40.69&remote.application=&side=consumer&sticky=false&timeout=2200

    ----------------------------------

    consumer端,设置retries=3

    2020-07-24 17:12:57.389 INFO 7468 --- [ main] dubbodemo.consumer.DubboConsumerTest : 请求开始...
    2020-07-24 17:13:00.202 INFO 7468 --- [ main] dubbodemo.consumer.DubboConsumerTest : 返回值=test retry:str
    2020-07-24 17:13:00.202 INFO 7468 --- [ main] dubbodemo.consumer.DubboConsumerTest : duration==2813

    provider端:最多会被执行1+retries=4次

    2020-07-24 17:12:57.540 INFO 2372 --- [28088-thread-17] dubbodemo.provider.ProviderApplication : add入参:str
    2020-07-24 17:12:57.541 INFO 2372 --- [28088-thread-17] dubbodemo.provider.ProviderApplication : r=1169
    2020-07-24 17:12:58.444 INFO 2372 --- [28088-thread-18] dubbodemo.provider.ProviderApplication : add入参:str
    2020-07-24 17:12:58.444 INFO 2372 --- [28088-thread-18] dubbodemo.provider.ProviderApplication : r=1934
    2020-07-24 17:12:58.711 INFO 2372 --- [28088-thread-17] dubbodemo.provider.ProviderApplication : duration=1170
    2020-07-24 17:12:59.461 INFO 2372 --- [28088-thread-19] dubbodemo.provider.ProviderApplication : add入参:str
    2020-07-24 17:12:59.461 INFO 2372 --- [28088-thread-19] dubbodemo.provider.ProviderApplication : r=736
    2020-07-24 17:13:00.198 INFO 2372 --- [28088-thread-19] dubbodemo.provider.ProviderApplication : duration=737
    2020-07-24 17:13:00.379 INFO 2372 --- [28088-thread-18] dubbodemo.provider.ProviderApplication : duration=1935

    优先级测试

    Provider设置retries=1 consumer设置retries=3,服务端会重试1次。 

    注意,log里的Tried 2 times 指的是一共调用了2次。即首次+重试的那1次。

    org.apache.dubbo.rpc.RpcException: Failed to invoke the method add in the service dubbodemo.contract.HelloWord. Tried 2 times of the providers [192.168.40.84:28088, 192.168.40.69:28088] (2/2) from the registry 192.168.40.84:2181 on the consumer 192.168.40.69 using the dubbo version 2.7.3. Last error is: Invoke remote method timeout. method: add, provider: dubbo://192.168.40.84:28088/dubbodemo.contract.HelloWord?anyhost=true&application=zhanggz-dubbodemo-consumer&bean.name=ServiceBean:dubbodemo.contract.HelloWord&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=dubbodemo.contract.HelloWord&lazy=false&methods=add,say&pid=23324&qos.enable=false&register=true&register.ip=192.168.40.69&release=2.7.3&remote.application=zhanggz-dubbodemo&retries=1&revision=1.0-SNAPSHOT&side=consumer&sticky=false&timeout=1000&timestamp=1596179853357, cause: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2020-07-31 15:33:52.809, end time: 2020-07-31 15:33:53.826, client elapsed: 1 ms, server elapsed: 1016 ms, timeout: 1000 ms, request: Request [id=1, version=2.0.2, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=add, parameterTypes=[class java.lang.String], arguments=[str], attachments={path=dubbodemo.contract.HelloWord, interface=dubbodemo.contract.HelloWord, version=0.0.0, timeout=1000}]], channel: /192.168.40.69:3666 -> /192.168.40.84:28088

    Provider设置retries=0 consumer设置retries=3,服务端不会重试。

    org.apache.dubbo.rpc.RpcException: Failed to invoke the method add in the service dubbodemo.contract.HelloWord. Tried 1 times of the providers [192.168.40.69:28088] (1/1) from the registry 127.0.0.1:2181 on the consumer 192.168.40.69 using the dubbo version 2.7.3. Last error is: Invoke remote method timeout. method: add, provider: dubbo://192.168.40.69:28088/dubbodemo.contract.HelloWord?anyhost=true&application=zhanggz-dubbodemo-consumer&bean.name=ServiceBean:dubbodemo.contract.HelloWord&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=dubbodemo.contract.HelloWord&lazy=false&methods=add,say&pid=9436&qos.enable=false&register=true&register.ip=192.168.40.69&release=2.7.3&remote.application=zhanggz-dubbodemo&retries=0&side=consumer&sticky=false&timeout=1000&timestamp=1596170589487, cause: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2020-07-31 12:43:36.395, end time: 2020-07-31 12:43:37.419, client elapsed: 111 ms, server elapsed: 912 ms, timeout: 1000 ms, request: Request [id=0, version=2.0.2, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=add, parameterTypes=[class java.lang.String], arguments=[str], attachments={path=dubbodemo.contract.HelloWord, interface=dubbodemo.contract.HelloWord, version=0.0.0, timeout=1000}]], channel: /192.168.40.69:2295 -> /192.168.40.69:28088
  • 相关阅读:
    Multi-Sensor, Multi- Network Positioning
    基于智能手机的3D地图导航
    2010上海世博会三维导航地图
    hdu 5452(树链刨分)
    蓝桥杯危险系数
    蓝桥杯横向打印二叉树(中序+先序遍历)
    蓝桥杯幸运数(线段树)
    hdu 5185(DP)
    2014江西理工大学C语言程序设计竞赛高级组题解
    uva 12730(期望经典)
  • 原文地址:https://www.cnblogs.com/buguge/p/13373611.html
Copyright © 2011-2022 走看看