目录
zk存储结构
dubbo在zookeeper的存储结构如下图,
其中流程大致分为:
1.消费者启动时在对应的servce目录下注册自己的ip节点地址;
2.生产者在启动时在对应的servce目录下注册自己的ip节点地址;
3.监控中心会订阅service目录下所有消费者和生产者的ip地址信息。
线程模型
dubbo底层采用netty框架实现,它的线程模型就是连接接受线程池和业务线程池分开处理,是其不会相互干扰独立,职责单一,在高负载的情况下依然能迅速处理。
dubbo在rpc调用的时候还支持同步和异步调用,在调用时可以对async参数进行配置;
<dubbo:reference id="xxService" interface="com.xx.dubbo.xx.api.xxService">
<dubbo:method name="xxUpdate" async="true"/>
</dubbo:reference>
dubbo的源码如下,会获取线程异步配置,采用Future的方式做异步处理;
@Override
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
inv.setAttachment(Constants.VERSION_KEY, version);
ExchangeClient currentClient;
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
//同步异步判断
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
boolean isAsyncFuture = RpcUtils.isGeneratedFuture(inv) || RpcUtils.isFutureReturnType(inv);
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
if (isOneway) {
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
return new RpcResult();
} else if (isAsync) {
ResponseFuture future = currentClient.request(inv, timeout);
// For compatibility
FutureAdapter<Object> futureAdapter = new FutureAdapter<>(future);
RpcContext.getContext().setFuture(futureAdapter);
Result result;
if (isAsyncFuture) {
// register resultCallback, sometimes we need the asyn result being processed by the filter chain.
result = new AsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
} else {
result = new SimpleAsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
}
return result;
} else {
RpcContext.getContext().setFuture(null);
return (Result) currentClient.request(inv, timeout).get();
}
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
} catch (RemotingException e) {
throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
集群容错
dubbo在rpc调用的过程大致分为以下步骤:
1.获取注册中心注册的服务提供责的服务地址列表;
2.根据配置的 loadbalance="xxx" 负载均衡策略进行节点的选取,有随机、一致性hash、平滑加权轮询算法、最少活跃数;
3.调用选取的节点获取服务结果,如果调用过程失败,会根据服务的配置采取不同的容错机制。4种容错如下:
failover:失败重试
failfast:快速失败,报异常
failsafe:安全失败,无异常
failback:失败后重发
样例:
<dubbo:service cluster="failover" retries="3"/>或<dubbo:reference cluster="failover" retries="3"/>