上篇文章https://blog.csdn.net/qq_38340127/article/details/112712044为当一个服务提供者直接进行request等,那么当有多个服务提供者,消费者是如何进行选择?
首先新增一个服务提供者:
provider1中暴露端口修改为20881
将两个服务都进行启动,消费者进行调试:
用zookeeper客户端进行查看(由于我在idea中安装插件无效。。。)
未启动消费者
消费者调用-客户端与服务端进行连接
对上篇中存在的部分遗漏进行添加:
在org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doSubscribe 方法中,会对provider进行订阅,其中主要方法为:
List<String> children = zkClient.addChildListener(path, zkListener);// 获取到当前节点下的所有监听对象
于是便得到了zookeeper的providers下的相关信息
List<URL> urls = new ArrayList<>();
for (String path : toCategoriesPath(url)) { //当是消费者进行订阅时,一共监听了对应的providers、configurators、routers
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<>());
listeners = zkListeners.get(url);
}
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
listeners.putIfAbsent(listener, (parentPath, currentChilds) -> ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds)));
zkListener = listeners.get(listener);
}
zkClient.create(path, false);
List<String> children = zkClient.addChildListener(path, zkListener);// 获取到当前节点下的所有监听对象
if (children != null) {
urls.addAll(toUrlsWithEmpty(url, path, children));
}
}
notify(url, listener, urls);//对url进行获取相关信息
然后是主要方法
@Override
protected void notify(URL url, NotifyListener listener, List<URL> urls) {
if (url == null) {
throw new IllegalArgumentException("notify url == null");
}
if (listener == null) {
throw new IllegalArgumentException("notify listener == null");
}
try {
doNotify(url, listener, urls);
} catch (Exception t) {
// Record a failed registration request to a failed list, retry regularly
addFailedNotified(url, listener, urls);
logger.error("Failed to notify for subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t);
}
}
其中urls信息如下(可以看到有两个服务提供者的dubbo信息):
继续发现封装成invoker的时候
org.apache.dubbo.registry.integration.RegistryDirectory#toInvokers发现指定的服务提供者url为
于是进行创建两个client进行与不同的provider进行连接。
消费者进行执行对应方法
根据上篇了解到消费者进行调用方法,就是根据invoker进行request的操作,
同时添加补充在org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke方法中有指定对应的重试次数
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}//len代表重试次数 默认次数DEFAULT_RETRIES为2
那么该选择哪个client呢?
org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke
在获取对应的invoker时进行了负载均衡策略
@O