• dubbo 集群容错源码


      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package com.alibaba.dubbo.rpc.cluster.support;
     18 
     19 import com.alibaba.dubbo.common.Constants;
     20 import com.alibaba.dubbo.common.Version;
     21 import com.alibaba.dubbo.common.logger.Logger;
     22 import com.alibaba.dubbo.common.logger.LoggerFactory;
     23 import com.alibaba.dubbo.common.utils.NetUtils;
     24 import com.alibaba.dubbo.rpc.Invocation;
     25 import com.alibaba.dubbo.rpc.Invoker;
     26 import com.alibaba.dubbo.rpc.Result;
     27 import com.alibaba.dubbo.rpc.RpcContext;
     28 import com.alibaba.dubbo.rpc.RpcException;
     29 import com.alibaba.dubbo.rpc.cluster.Directory;
     30 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
     31 
     32 import java.util.ArrayList;
     33 import java.util.HashSet;
     34 import java.util.List;
     35 import java.util.Set;
     36 
     37 /**
     38  * When invoke fails, log the initial error and retry other invokers (retry n times, which means at most n different invokers will be invoked)
     39  * Note that retry causes latency.
     40  * <p>
     41  * <a href="http://en.wikipedia.org/wiki/Failover">Failover</a>
     42  *
     43  */
     44 public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
     45 
     46     private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);
     47 
     48     public FailoverClusterInvoker(Directory<T> directory) {
     49         super(directory);
     50     }
     51 
     52     @Override
     53     @SuppressWarnings({"unchecked", "rawtypes"})
     54     public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
     55         List<Invoker<T>> copyinvokers = invokers;
     56         checkInvokers(copyinvokers, invocation);
     57         int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
     58         if (len <= 0) {
     59             len = 1;
     60         }
     61         // retry loop.
     62         RpcException le = null; // last exception.
     63         List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers.
     64         Set<String> providers = new HashSet<String>(len);
     65         for (int i = 0; i < len; i++) {
     66             //Reselect before retry to avoid a change of candidate `invokers`.
     67             //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
     68             if (i > 0) {
     69                 checkWhetherDestroyed();
     70                 copyinvokers = list(invocation);
     71                 // check again
     72                 checkInvokers(copyinvokers, invocation);
     73             }
     74             Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
     75             invoked.add(invoker);
     76             RpcContext.getContext().setInvokers((List) invoked);
     77             try {
     78                 Result result = invoker.invoke(invocation);
     79                 if (le != null && logger.isWarnEnabled()) {
     80                     logger.warn("Although retry the method " + invocation.getMethodName()
     81                             + " in the service " + getInterface().getName()
     82                             + " was successful by the provider " + invoker.getUrl().getAddress()
     83                             + ", but there have been failed providers " + providers
     84                             + " (" + providers.size() + "/" + copyinvokers.size()
     85                             + ") from the registry " + directory.getUrl().getAddress()
     86                             + " on the consumer " + NetUtils.getLocalHost()
     87                             + " using the dubbo version " + Version.getVersion() + ". Last error is: "
     88                             + le.getMessage(), le);
     89                 }
     90                 return result;
     91             } catch (RpcException e) {
     92                 if (e.isBiz()) { // biz exception.
     93                     throw e;
     94                 }
     95                 le = e;
     96             } catch (Throwable e) {
     97                 le = new RpcException(e.getMessage(), e);
     98             } finally {
     99                 providers.add(invoker.getUrl().getAddress());
    100             }
    101         }
    102         throw new RpcException(le != null ? le.getCode() : 0, "Failed to invoke the method "
    103                 + invocation.getMethodName() + " in the service " + getInterface().getName()
    104                 + ". Tried " + len + " times of the providers " + providers
    105                 + " (" + providers.size() + "/" + copyinvokers.size()
    106                 + ") from the registry " + directory.getUrl().getAddress()
    107                 + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
    108                 + Version.getVersion() + ". Last error is: "
    109                 + (le != null ? le.getMessage() : ""), le != null && le.getCause() != null ? le.getCause() : le);
    110     }
    111 
    112 }
     1 /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  * contributor license agreements.  See the NOTICE file distributed with
     4  * this work for additional information regarding copyright ownership.
     5  * The ASF licenses this file to You under the Apache License, Version 2.0
     6  * (the "License"); you may not use this file except in compliance with
     7  * the License.  You may obtain a copy of the License at
     8  *
     9  *     http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  * Unless required by applicable law or agreed to in writing, software
    12  * distributed under the License is distributed on an "AS IS" BASIS,
    13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  * See the License for the specific language governing permissions and
    15  * limitations under the License.
    16  */
    17 package com.alibaba.dubbo.rpc.cluster.support;
    18 
    19 import com.alibaba.dubbo.common.Version;
    20 import com.alibaba.dubbo.common.utils.NetUtils;
    21 import com.alibaba.dubbo.rpc.Invocation;
    22 import com.alibaba.dubbo.rpc.Invoker;
    23 import com.alibaba.dubbo.rpc.Result;
    24 import com.alibaba.dubbo.rpc.RpcException;
    25 import com.alibaba.dubbo.rpc.cluster.Directory;
    26 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
    27 
    28 import java.util.List;
    29 
    30 /**
    31  * Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error.
    32  * Usually used for non-idempotent write operations
    33  *
    34  * <a href="http://en.wikipedia.org/wiki/Fail-fast">Fail-fast</a>
    35  *
    36  */
    37 public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
    38 
    39     public FailfastClusterInvoker(Directory<T> directory) {
    40         super(directory);
    41     }
    42 
    43     @Override
    44     public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    45         checkInvokers(invokers, invocation);
    46         Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
    47         try {
    48             return invoker.invoke(invocation);
    49         } catch (Throwable e) {
    50             if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception.
    51                 throw (RpcException) e;
    52             }
    53             throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0, "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName() + " select from all providers " + invokers + " for service " + getInterface().getName() + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e.getCause() != null ? e.getCause() : e);
    54         }
    55     }
    56 }
     1 /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  * contributor license agreements.  See the NOTICE file distributed with
     4  * this work for additional information regarding copyright ownership.
     5  * The ASF licenses this file to You under the Apache License, Version 2.0
     6  * (the "License"); you may not use this file except in compliance with
     7  * the License.  You may obtain a copy of the License at
     8  *
     9  *     http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  * Unless required by applicable law or agreed to in writing, software
    12  * distributed under the License is distributed on an "AS IS" BASIS,
    13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  * See the License for the specific language governing permissions and
    15  * limitations under the License.
    16  */
    17 package com.alibaba.dubbo.rpc.cluster.support;
    18 
    19 import com.alibaba.dubbo.common.logger.Logger;
    20 import com.alibaba.dubbo.common.logger.LoggerFactory;
    21 import com.alibaba.dubbo.rpc.Invocation;
    22 import com.alibaba.dubbo.rpc.Invoker;
    23 import com.alibaba.dubbo.rpc.Result;
    24 import com.alibaba.dubbo.rpc.RpcException;
    25 import com.alibaba.dubbo.rpc.RpcResult;
    26 import com.alibaba.dubbo.rpc.cluster.Directory;
    27 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
    28 
    29 import java.util.List;
    30 
    31 /**
    32  * When invoke fails, log the error message and ignore this error by returning an empty RpcResult.
    33  * Usually used to write audit logs and other operations
    34  *
    35  * <a href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a>
    36  *
    37  */
    38 public class FailsafeClusterInvoker<T> extends AbstractClusterInvoker<T> {
    39     private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class);
    40 
    41     public FailsafeClusterInvoker(Directory<T> directory) {
    42         super(directory);
    43     }
    44 
    45     @Override
    46     public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    47         try {
    48             checkInvokers(invokers, invocation);
    49             Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
    50             return invoker.invoke(invocation);
    51         } catch (Throwable e) {
    52             logger.error("Failsafe ignore exception: " + e.getMessage(), e);
    53             return new RpcResult(); // ignore
    54         }
    55     }
    56 }
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package com.alibaba.dubbo.rpc.cluster.support;
     18 
     19 import com.alibaba.dubbo.common.logger.Logger;
     20 import com.alibaba.dubbo.common.logger.LoggerFactory;
     21 import com.alibaba.dubbo.common.utils.NamedThreadFactory;
     22 import com.alibaba.dubbo.rpc.Invocation;
     23 import com.alibaba.dubbo.rpc.Invoker;
     24 import com.alibaba.dubbo.rpc.Result;
     25 import com.alibaba.dubbo.rpc.RpcException;
     26 import com.alibaba.dubbo.rpc.RpcResult;
     27 import com.alibaba.dubbo.rpc.cluster.Directory;
     28 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
     29 
     30 import java.util.HashMap;
     31 import java.util.List;
     32 import java.util.Map;
     33 import java.util.concurrent.ConcurrentHashMap;
     34 import java.util.concurrent.ConcurrentMap;
     35 import java.util.concurrent.Executors;
     36 import java.util.concurrent.ScheduledExecutorService;
     37 import java.util.concurrent.ScheduledFuture;
     38 import java.util.concurrent.TimeUnit;
     39 
     40 /**
     41  * When fails, record failure requests and schedule for retry on a regular interval.
     42  * Especially useful for services of notification.
     43  *
     44  * <a href="http://en.wikipedia.org/wiki/Failback">Failback</a>
     45  *
     46  */
     47 public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
     48 
     49     private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class);
     50 
     51     private static final long RETRY_FAILED_PERIOD = 5 * 1000;
     52 
     53     private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2, new NamedThreadFactory("failback-cluster-timer", true));
     54     private final ConcurrentMap<Invocation, AbstractClusterInvoker<?>> failed = new ConcurrentHashMap<Invocation, AbstractClusterInvoker<?>>();
     55     private volatile ScheduledFuture<?> retryFuture;
     56 
     57     public FailbackClusterInvoker(Directory<T> directory) {
     58         super(directory);
     59     }
     60 
     61     private void addFailed(Invocation invocation, AbstractClusterInvoker<?> router) {
     62         if (retryFuture == null) {
     63             synchronized (this) {
     64                 if (retryFuture == null) {
     65                     retryFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
     66 
     67                         @Override
     68                         public void run() {
     69                             // collect retry statistics
     70                             try {
     71                                 retryFailed();
     72                             } catch (Throwable t) { // Defensive fault tolerance
     73                                 logger.error("Unexpected error occur at collect statistic", t);
     74                             }
     75                         }
     76                     }, RETRY_FAILED_PERIOD, RETRY_FAILED_PERIOD, TimeUnit.MILLISECONDS);
     77                 }
     78             }
     79         }
     80         failed.put(invocation, router);
     81     }
     82 
     83     void retryFailed() {
     84         if (failed.size() == 0) {
     85             return;
     86         }
     87         for (Map.Entry<Invocation, AbstractClusterInvoker<?>> entry : new HashMap<Invocation, AbstractClusterInvoker<?>>(
     88                 failed).entrySet()) {
     89             Invocation invocation = entry.getKey();
     90             Invoker<?> invoker = entry.getValue();
     91             try {
     92                 invoker.invoke(invocation);
     93                 failed.remove(invocation);
     94             } catch (Throwable e) {
     95                 logger.error("Failed retry to invoke method " + invocation.getMethodName() + ", waiting again.", e);
     96             }
     97         }
     98     }
     99 
    100     @Override
    101     protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    102         try {
    103             checkInvokers(invokers, invocation);
    104             Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
    105             return invoker.invoke(invocation);
    106         } catch (Throwable e) {
    107             logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: "
    108                     + e.getMessage() + ", ", e);
    109             addFailed(invocation, this);
    110             return new RpcResult(); // ignore
    111         }
    112     }
    113 
    114 }
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package com.alibaba.dubbo.rpc.cluster.support;
     18 
     19 import com.alibaba.dubbo.common.Constants;
     20 import com.alibaba.dubbo.common.utils.NamedThreadFactory;
     21 import com.alibaba.dubbo.rpc.Invocation;
     22 import com.alibaba.dubbo.rpc.Invoker;
     23 import com.alibaba.dubbo.rpc.Result;
     24 import com.alibaba.dubbo.rpc.RpcContext;
     25 import com.alibaba.dubbo.rpc.RpcException;
     26 import com.alibaba.dubbo.rpc.cluster.Directory;
     27 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
     28 
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 import java.util.concurrent.BlockingQueue;
     32 import java.util.concurrent.ExecutorService;
     33 import java.util.concurrent.Executors;
     34 import java.util.concurrent.LinkedBlockingQueue;
     35 import java.util.concurrent.TimeUnit;
     36 import java.util.concurrent.atomic.AtomicInteger;
     37 
     38 /**
     39  * Invoke a specific number of invokers concurrently, usually used for demanding real-time operations, but need to waste more service resources.
     40  *
     41  * <a href="http://en.wikipedia.org/wiki/Fork_(topology)">Fork</a>
     42  *
     43  */
     44 public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T> {
     45 
     46     private final ExecutorService executor = Executors.newCachedThreadPool(new NamedThreadFactory("forking-cluster-timer", true));
     47 
     48     public ForkingClusterInvoker(Directory<T> directory) {
     49         super(directory);
     50     }
     51 
     52     @Override
     53     @SuppressWarnings({"unchecked", "rawtypes"})
     54     public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
     55         checkInvokers(invokers, invocation);
     56         final List<Invoker<T>> selected;
     57         final int forks = getUrl().getParameter(Constants.FORKS_KEY, Constants.DEFAULT_FORKS);
     58         final int timeout = getUrl().getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
     59         if (forks <= 0 || forks >= invokers.size()) {
     60             selected = invokers;
     61         } else {
     62             selected = new ArrayList<Invoker<T>>();
     63             for (int i = 0; i < forks; i++) {
     64                 // TODO. Add some comment here, refer chinese version for more details.
     65                 Invoker<T> invoker = select(loadbalance, invocation, invokers, selected);
     66                 if (!selected.contains(invoker)) {//Avoid add the same invoker several times.
     67                     selected.add(invoker);
     68                 }
     69             }
     70         }
     71         RpcContext.getContext().setInvokers((List) selected);
     72         final AtomicInteger count = new AtomicInteger();
     73         final BlockingQueue<Object> ref = new LinkedBlockingQueue<Object>();
     74         for (final Invoker<T> invoker : selected) {
     75             executor.execute(new Runnable() {
     76                 @Override
     77                 public void run() {
     78                     try {
     79                         Result result = invoker.invoke(invocation);
     80                         ref.offer(result);
     81                     } catch (Throwable e) {
     82                         int value = count.incrementAndGet();
     83                         if (value >= selected.size()) {
     84                             ref.offer(e);
     85                         }
     86                     }
     87                 }
     88             });
     89         }
     90         try {
     91             Object ret = ref.poll(timeout, TimeUnit.MILLISECONDS);
     92             if (ret instanceof Throwable) {
     93                 Throwable e = (Throwable) ret;
     94                 throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0, "Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e.getCause() != null ? e.getCause() : e);
     95             }
     96             return (Result) ret;
     97         } catch (InterruptedException e) {
     98             throw new RpcException("Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
     99         }
    100     }
    101 }
     1 /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  * contributor license agreements.  See the NOTICE file distributed with
     4  * this work for additional information regarding copyright ownership.
     5  * The ASF licenses this file to You under the Apache License, Version 2.0
     6  * (the "License"); you may not use this file except in compliance with
     7  * the License.  You may obtain a copy of the License at
     8  *
     9  *     http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  * Unless required by applicable law or agreed to in writing, software
    12  * distributed under the License is distributed on an "AS IS" BASIS,
    13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  * See the License for the specific language governing permissions and
    15  * limitations under the License.
    16  */
    17 package com.alibaba.dubbo.rpc.cluster.support;
    18 
    19 import com.alibaba.dubbo.common.logger.Logger;
    20 import com.alibaba.dubbo.common.logger.LoggerFactory;
    21 import com.alibaba.dubbo.rpc.Invocation;
    22 import com.alibaba.dubbo.rpc.Invoker;
    23 import com.alibaba.dubbo.rpc.Result;
    24 import com.alibaba.dubbo.rpc.RpcContext;
    25 import com.alibaba.dubbo.rpc.RpcException;
    26 import com.alibaba.dubbo.rpc.cluster.Directory;
    27 import com.alibaba.dubbo.rpc.cluster.LoadBalance;
    28 
    29 import java.util.List;
    30 
    31 /**
    32  * BroadcastClusterInvoker
    33  *
    34  */
    35 public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
    36 
    37     private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
    38 
    39     public BroadcastClusterInvoker(Directory<T> directory) {
    40         super(directory);
    41     }
    42 
    43     @Override
    44     @SuppressWarnings({"unchecked", "rawtypes"})
    45     public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    46         checkInvokers(invokers, invocation);
    47         RpcContext.getContext().setInvokers((List) invokers);
    48         RpcException exception = null;
    49         Result result = null;
    50         for (Invoker<T> invoker : invokers) {
    51             try {
    52                 result = invoker.invoke(invocation);
    53             } catch (RpcException e) {
    54                 exception = e;
    55                 logger.warn(e.getMessage(), e);
    56             } catch (Throwable e) {
    57                 exception = new RpcException(e.getMessage(), e);
    58                 logger.warn(e.getMessage(), e);
    59             }
    60         }
    61         if (exception != null) {
    62             throw exception;
    63         }
    64         return result;
    65     }
    66 
    67 }
  • 相关阅读:
    Java基础教程(15)--枚举类型
    Java基础教程(14)--嵌套类
    Java基础教程(13)--包
    Java基础教程(12)--深入理解类
    Java基础教程(11)--对象
    Java基础教程(10)--类
    Java基础教程(9)--流程控制
    Java基础教程(8)--表达式、语句和块
    Java基础教程(7)--运算符
    Java基础教程(6)--数组
  • 原文地址:https://www.cnblogs.com/toUpdating/p/9058482.html
Copyright © 2020-2023  润新知