Cluster is a service broker,Cluster 是服務的經紀人,motan的服務治理和高可用都是經過它來實現的。java
@Spi(scope = Scope.PROTOTYPE) public interface Cluster<T> extends Caller<T> { @Override void init(); void setUrl(URL url); void setLoadBalance(LoadBalance<T> loadBalance); void setHaStrategy(HaStrategy<T> haStrategy); void onRefresh(List<Referer<T>> referers); List<Referer<T>> getReferers(); LoadBalance<T> getLoadBalance(); }
經過負載均衡策略,來選擇服務的引用實例。api
@Spi(scope = Scope.PROTOTYPE) public interface LoadBalance<T> { void onRefresh(List<Referer<T>> referers); Referer<T> select(Request request); void selectToHolder(Request request, List<Referer<T>> refersHolder); void setWeightString(String weightString); }
支持多種負載均衡策略:併發
支持兩種容錯策略:Failfast(快速失敗) 和 Failover(故障轉移,故障切換),實現故障節點自動摘除,自動探測恢復,有效進行服務故障隔離,遠離服務卡死及雪崩。
···
@Spi(scope = Scope.PROTOTYPE)
public interface HaStrategy
void setUrl(URL url); Response call(Request request, LoadBalance<T> loadBalance);
}
···dom
@SpiMeta(name = "failfast") public class FailfastHaStrategy<T> extends AbstractHaStrategy<T> { @Override public Response call(Request request, LoadBalance<T> loadBalance) { Referer<T> refer = loadBalance.select(request); return refer.call(request); } }
@SpiMeta(name = "failover") public class FailoverHaStrategy<T> extends AbstractHaStrategy<T> { protected ThreadLocal<List<Referer<T>>> referersHolder = new ThreadLocal<List<Referer<T>>>() { @Override protected java.util.List<com.weibo.api.motan.rpc.Referer<T>> initialValue() { return new ArrayList<Referer<T>>(); } }; @Override public Response call(Request request, LoadBalance<T> loadBalance) { List<Referer<T>> referers = selectReferers(request, loadBalance); if (referers.isEmpty()) { throw new MotanServiceException(String.format("FailoverHaStrategy No referers for request:%s, loadbalance:%s", request, loadBalance)); } URL refUrl = referers.get(0).getUrl(); // 先使用method的配置 int tryCount = refUrl.getMethodParameter(request.getMethodName(), request.getParamtersDesc(), URLParamType.retries.getName(), URLParamType.retries.getIntValue()); // 若是有問題,則設置爲不重試 if (tryCount < 0) { tryCount = 0; } for (int i = 0; i <= tryCount; i++) { Referer<T> refer = referers.get(i % referers.size()); try { request.setRetries(i); return refer.call(request); } catch (RuntimeException e) { // 對於業務異常,直接拋出 if (ExceptionUtil.isBizException(e)) { throw e; } else if (i >= tryCount) { throw e; } LoggerUtil.warn(String.format("FailoverHaStrategy Call false for request:%s error=%s", request, e.getMessage())); } } throw new MotanFrameworkException("FailoverHaStrategy.call should not come here!"); } protected List<Referer<T>> selectReferers(Request request, LoadBalance<T> loadBalance) { List<Referer<T>> referers = referersHolder.get(); referers.clear(); loadBalance.selectToHolder(request, referers); return referers; } }