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; } }