<dubbo:reference > 对应 registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {}
既然是一个FactoryBean 根据规则从get()入手
public synchronized T get() {
if (destroyed) {
throw new IllegalStateException("Already destroyed!");
}
if (ref == null) {
// 父类的方法
init();
}
return ref;
}进入ReferenceConfig 的init方法说起
ref = createProxy(map); @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
private T createProxy(Map<String, String> map) {
URL tmpUrl = new URL("temp", "localhost", 0, map);
final boolean isJvmRefer;
if (isInjvm() == null) {
if (url != null && url.length() > 0) { //指定URL的情况下,不做本地引用
isJvmRefer = false;
} else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
//默认情况下如果本地有服务暴露,则引用本地服务.
isJvmRefer = true;
} else {
isJvmRefer = false;
}
} else {
isJvmRefer = isInjvm().booleanValue();
}
if (isJvmRefer) {
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
invoker = refprotocol.refer(interfaceClass, url);
if (logger.isInfoEnabled()) {
logger.info("Using injvm service " + interfaceClass.getName());
}
} else {
// url 为指定的url 点对点直连服务提供者地址,将绕过注册中心 也可以是注册中心的地址
if (url != null && url.length() > 0) { // 用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL
String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
if (us != null && us.length > 0) {
for (String u : us) {
URL url = URL.valueOf(u);
if (url.getPath() == null || url.getPath().length() == 0) {
url = url.setPath(interfaceName);
}
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
} else {
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
} else {
// 通过注册中心配置拼装URL
List<URL> us = loadRegistries(false);
if (us != null && us.size() > 0) {
for (URL u : us) {
URL monitorUrl = loadMonitor(u);
if (monitorUrl != null) {
map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
}
urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
}
}
if (urls == null || urls.size() == 0) {
throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
}
}
if (urls.size() == 1) {
// refprotocol 对应 Protocol$Adpative 自适应扩展点
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // 用了最后一个registry url
}
}
if (registryURL != null) { // 有 注册中心协议的URL
// 对有注册中心的Cluster 只用 AvailableCluster
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // 不是 注册中心的URL
invoker = cluster.join(new StaticDirectory(invokers));
}
}
}
Boolean c = check;
if (c == null && consumer != null) {
c = consumer.isCheck();
}
if (c == null) {
c = true; // default true
}
if (c && !invoker.isAvailable()) {
throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
}
if (logger.isInfoEnabled()) {
logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
}
// 创建服务代理
return (T) proxyFactory.getProxy(invoker);
}
- urls.get(0) 对应 registry://192.168.25.128:2181/com.alibaba.dubbo.registry.RegistryService?application=user-consumer&dubbo=2.5.5&pid=11884&refer=application%3Duser-consumer%26check%3Dfalse%26default.check%3Dfalse%26dubbo%3D2.5.5%26interface%3Dcom.zmz.order.api.IOrderService%26methods%3DdoCreateOrder%26pid%3D11884%26protocol%3Ddubbo%26revision%3D1.0%26side%3Dconsumer%26timestamp%3D1572670815240%26version%3D1.0®istry=zookeeper×tamp=1572670817505
- 所以先进入RegistryProtocol.refer() 进行分析
- 最终生成的invoker为

此时根据url上的协议进入 RegistryProtocol 中的refer()
RegistryProtocol
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 获取url中对应的协议 zookeeper
url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
// 获取注册中心 ZookeeperRegistry
Registry registry = registryFactory.getRegistry(url);
if (RegistryService.class.equals(type)) {
return proxyFactory.getInvoker((T) registry, type, url);
}
// group="a,b" or group="*"
Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
String group = qs.get(Constants.GROUP_KEY);
if (group != null && group.length() > 0) {
if ((Constants.COMMA_SPLIT_PATTERN.split(group)).length > 1
|| "*".equals(group)) {
return doRefer(getMergeableCluster(), registry, type, url);
}
}
//重点分析
return doRefer(cluster, registry, type, url);
}- registry 对应zookeeper://192.168.25.128:2181/com.alibaba.dubbo.registry.RegistryService?application=user-consumer&dubbo=2.5.5&interface=com.alibaba.dubbo.registry.RegistryService&pid=11884×tamp=1572670817505
RegistryProtocol
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//这是关键 服务目录
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
// 此时的registry 为对应的注册中心的实现
directory.setRegistry(registry);
//protocol为protocol$Adaptive
directory.setProtocol(protocol);
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0, type.getName(), directory.getUrl().getParameters());
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
&& url.getParameter(Constants.REGISTER_KEY, true)) {
// 注册consumer协议到注册中心 consumers/
registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
Constants.CHECK_KEY, String.valueOf(false)));
}
//这是重点中的重点
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
return cluster.join(directory);
}- 参数解释
- subscribeUrl 对应 consumer://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=consumers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=14796&protocol=dubbo&revision=1.0&side=consumer×tamp=1572671425766&version=1.0
- 首先看下RegistryDirectory 的类结构
- registry.register(subscribeUrl) 注册consumer节点数据consumer://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=consumers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=1176&protocol=dubbo&revision=1.0&side=consumer×tamp=1572678968723&version=1.0
先分析下 RegistryDirectory 类中成员属性
public class RegistryDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
private static final Logger logger = LoggerFactory.getLogger(RegistryDirectory.class);
private static final Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();
private static final RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension();
private static final ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).getAdaptiveExtension();
// com.alibaba.dubbo.registry.RegistryService
private final String serviceKey; // 构造时初始化,断言不为null
// com.zmz.order.api.IOrderService
private final Class<T> serviceType; // 构造时初始化,断言不为null
// {protocol=dubbo, side=consumer, application=user-consumer,
methods=doCreateOrder, default.check=false,
dubbo=2.5.5, pid=1176, check=false,
interface=com.zmz.order.api.IOrderService,
version=1.0, revision=1.0, timestamp=1572678968723}
private final Map<String, String> queryMap; // 构造时初始化,断言不为null
zookeeper://192.168.25.128:2181/com.alibaba.dubbo.registry.RegistryService?
application=user-consumer&check=false&default.check=false&dubbo=2.5.5
&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=1176
&protocol=dubbo&revision=1.0&side=consumer×tamp=1572678968723&version=1.0
private final URL directoryUrl; // 构造时初始化,断言不为null,并且总是赋非null值
// 接口方法数组
private final String[] serviceMethods;
// 是否多个group
private final boolean multiGroup;
private Protocol protocol; // 注入时初始化,断言不为null
private Registry registry; // 注入时初始化,断言不为null
private volatile boolean forbidden = false;
private volatile URL overrideDirectoryUrl; // 构造时初始化,断言不为null,并且总是赋非null值
/*override规则
* 优先级:override>-D>consumer>provider
* 第一种规则:针对某个provider <ip:port,timeout=100>
* 第二种规则:针对所有provider <* ,timeout=5000>
*/
private volatile List<Configurator> configurators; // 初始为null以及中途可能被赋为null,请使用局部变量引用
// Map<url, Invoker> cache service url to invoker mapping.
private volatile Map<String, Invoker<T>> urlInvokerMap; // 初始为null以及中途可能被赋为null,请使用局部变量引用
// Map<methodName, Invoker> cache service method to invokers mapping.
private volatile Map<String, List<Invoker<T>>> methodInvokerMap; // 初始为null以及中途可能被赋为null,请使用局部变量引用
// Set<invokerUrls> cache invokeUrls to invokers mapping.
private volatile Set<URL> cachedInvokerUrls; // 初始为null以及中途可能被赋为null,请使用局部变量引用
public RegistryDirectory(Class<T> serviceType, URL url) {
super(url);
if (serviceType == null)
throw new IllegalArgumentException("service type is null.");
if (url.getServiceKey() == null || url.getServiceKey().length() == 0)
throw new IllegalArgumentException("registry serviceKey is null.");
this.serviceType = serviceType;
this.serviceKey = url.getServiceKey();
this.queryMap = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
this.overrideDirectoryUrl = this.directoryUrl = url.setPath(url.getServiceInterface()).clearParameters().addParameters(queryMap).removeParameter(Constants.MONITOR_KEY);
String group = directoryUrl.getParameter(Constants.GROUP_KEY, "");
this.multiGroup = group != null && ("*".equals(group) || group.contains(","));
String methods = queryMap.get(Constants.METHODS_KEY);
this.serviceMethods = methods == null ? null : Constants.COMMA_SPLIT_PATTERN.split(methods);
}
FailbackRegistry
@Override
public void subscribe(URL url, NotifyListener listener) {
if (destroyed.get()){
return;
}
super.subscribe(url, listener);
removeFailedSubscribed(url, listener);
try {
// 向服务器端发送订阅请求
doSubscribe(url, listener);
} catch (Exception e) {
Throwable t = e;
List<URL> urls = getCacheUrls(url);
if (urls != null && urls.size() > 0) {
notify(url, listener, urls);
logger.error("Failed to subscribe " + url + ", Using cached list: " + urls + " from cache file: " + getUrl().getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/dubbo-registry-" + url.getHost() + ".cache") + ", cause: " + t.getMessage(), t);
} else {
// 如果开启了启动时检测,则直接抛出异常
boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
&& url.getParameter(Constants.CHECK_KEY, true);
boolean skipFailback = t instanceof SkipFailbackWrapperException;
if (check || skipFailback) {
if (skipFailback) {
t = t.getCause();
}
throw new IllegalStateException("Failed to subscribe " + url + ", cause: " + t.getMessage(), t);
} else {
logger.error("Failed to subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t);
}
}
// 将失败的订阅请求记录到失败列表,定时重试
addFailedSubscribed(url, listener);
}
} public class ZookeeperRegistry extends FailbackRegistry {
private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<URL, ConcurrentMap<NotifyListener, ChildListener>>();
// url consumer://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=providers,configurators,routers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=1176&protocol=dubbo&revision=1.0&side=consumer×tamp=1572678968723&version=1.0
// listener RegistryDirecory
protected void doSubscribe(final URL url, final NotifyListener listener) {
try {
// ANY_VALUE 为* interface 为具体的接口path
if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
//root /dubbo
String root = toRootPath();
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
listeners = zkListeners.get(url);
}
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
listeners.putIfAbsent(listener, new ChildListener() {
public void childChanged(String parentPath, List<String> currentChilds) {
for (String child : currentChilds) {
child = URL.decode(child);
if (!anyServices.contains(child)) {
anyServices.add(child);
subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
}
});
zkListener = listeners.get(listener);
}
zkClient.create(root, false);
List<String> services = zkClient.addChildListener(root, zkListener);
if (services != null && services.size() > 0) {
for (String service : services) {
service = URL.decode(service);
anyServices.add(service);
subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
} else {
从此处开始分析
List<URL> urls = new ArrayList<URL>();
// toCategoriesPath(url) 对应providers configurators routes节点
for (String path : toCategoriesPath(url)) {
// 判断该url上是否存在监听(实则对父节点进行监听)
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
listeners = zkListeners.get(url);
}
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
// 存储一个用于来通知节点数据发生变化的listener对象
listeners.putIfAbsent(listener, new ChildListener() {
public void childChanged(String parentPath, List<String> currentChilds) {
ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
zkListener = listeners.get(listener);
}
zkClient.create(path, false);
// 对该节点下的子节点注册监听事件 children为该path下的子节点
List<String> children = zkClient.addChildListener(path, zkListener);
// 返回结果为空列表是 会构造一个empty的协议即empty://
if (children != null) {
urls.addAll(toUrlsWithEmpty(url, path, children));
}
}
// 重点代码
notify(url, listener, urls);
}
} catch (Throwable e) {
throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}参数解释
url consumer://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=providers,configurators,routers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=14796&protocol=dubbo&revision=1.0&side=consumer×tamp=1572671425766&version=1.0- listener 为当前RegisterDirectory
- toCategoriesPath(url)
- /dubbo/com.zmz.order.api.IOrderService/providers
- /dubbo/com.zmz.order.api.IOrderService/configurators
- /dubbo/com.zmz.order.api.IOrderService/routers
分析下如何添加监听
List<String> children = zkClient.addChildListener(path, zkListener); 这段代码
AbstractZookeeperClient<TargetChildListener> implements ZookeeperClient {
public List<String> addChildListener(String path, final ChildListener listener) {
ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
if (listeners == null) {
childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>());
listeners = childListeners.get(path);
}
TargetChildListener targetListener = listeners.get(listener);
if (targetListener == null) {
listeners.putIfAbsent(listener, createTargetChildListener(path, listener));
targetListener = listeners.get(listener);
}
// 这里是重点
return addTargetChildListener(path, targetListener);
}接下来进入具体的实现可以是Zkclient 也可以是Curator实现
public class CuratorZookeeperClient extends AbstractZookeeperClient<CuratorWatcher> {
// path /dubbo/com.zmz.order.api.IOrderService/providers
// listener 为 zkListener 即上面的匿名内部类实现
public List<String> addTargetChildListener(String path, CuratorWatcher listener) {
try {
// 此处就很熟悉了
return client.getChildren().usingWatcher(listener).forPath(path);
} catch (NoNodeException e) {
return null;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
接着分析 notify(url, listener, urls); 这段代码
- 参数解疑
- url consumer://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=providers,configurators,routers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=17696&protocol=dubbo&revision=1.0&side=consumer×tamp=1572682533375&version=1.0
- listenerRegistryDirectory
- urls 为 (分别对应providers routers.configurators(空协议))
- dubbo://169.254.88.190:20881/com.zmz.order.api.IOrderService?anyhost=true&application=order-provider&dubbo=2.5.5&generic=false&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=15332&revision=1.0&side=provider×tamp=1572674326351&version=1.0
- empty://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=configurators&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=17696&protocol=dubbo&revision=1.0&side=consumer×tamp=1572682533375&version=1.0
- empty://169.254.88.190/com.zmz.order.api.IOrderService?application=user-consumer&category=routers&check=false&default.check=false&dubbo=2.5.5&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=17696&protocol=dubbo&revision=1.0&side=consumer×tamp=1572682533375&version=1.0
继续往下走
public abstract class FailbackRegistry extends AbstractRegistry {
@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) {
// 将失败的通知请求记录到失败列表,定时重试
Map<NotifyListener, List<URL>> listeners = failedNotified.get(url);
if (listeners == null) {
failedNotified.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, List<URL>>());
listeners = failedNotified.get(url);
}
listeners.put(listener, urls);
logger.error("Failed to notify for subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t);
}
}
protected void doNotify(URL url, NotifyListener listener, List<URL> urls) {
super.notify(url, listener, urls);
}
进入父类中
public abstract class AbstractRegistry implements Registry {
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");
}
if ((urls == null || urls.size() == 0)
&& !Constants.ANY_VALUE.equals(url.getServiceInterface())) {
logger.warn("Ignore empty notify urls for subscribe url " + url);
return;
}
if (logger.isInfoEnabled()) {
logger.info("Notify urls for subscribe url " + url + ", urls: " + urls);
}
Map<String, List<URL>> result = new HashMap<String, List<URL>>();
// url分类
for (URL u : urls) {
if (UrlUtils.isMatch(url, u)) {
String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
List<URL> categoryList = result.get(category);
if (categoryList == null) {
categoryList = new ArrayList<URL>();
result.put(category, categoryList);
}
categoryList.add(u);
}
}
// result 存储category 与url的关系
if (result.size() == 0) {
return;
}
Map<String, List<URL>> categoryNotified = notified.get(url);
if (categoryNotified == null) {
notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>());
categoryNotified = notified.get(url);
}
for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
String category = entry.getKey();
List<URL> categoryList = entry.getValue();
categoryNotified.put(category, categoryList);
// 保存到文件中
// <dubbo:registry file="d://a/txt" id="zookeeper" protocol="zookeeper" address="192.168.25.129:2181"/>
saveProperties(url);
listener.notify(categoryList);
}
}
这是 saveProperties(url)保存文件的数据格式 (本人进行过拆分)
#Dubbo Registry Cache
#Sun Nov 03 15:09:54 CST 2019
com.zmz.order.api.IOrderService\:1.0=
empty\://169.254.88.190/com.zmz.order.api.IOrderService?
application\=user-consumer&category\=configurators&check\=false
&default.check\=false&dubbo\=2.5.5&
interface\=com.zmz.order.api.IOrderService
&methods\=doCreateOrder&pid\=5388&protocol\=dubbo
&revision\=1.0&side\=consumer×tamp\=1572764973152&version\=1.0
empty\://169.254.88.190/com.zmz.order.api.IOrderService?application\=user-consumer&category\=
routers&check\=false&default.check\=false&dubbo\=2.5.5&interface\=com.zmz.order.api.IOrderServi
ce&methods\=doCreateOrder&pid\=5388&protocol\=dubbo&revision\=1.0&side\=consumer×tamp\=15727
64973152&version\=1.0
dubbo\://169.254.88.190\:20881/com.zmz.order.api.IOrderService?anyhost\=true&appl
ication\=order-provider&dubbo\=2.5.5&generic\=false&interface\=com.zmz.order.api.IOrderService&loadbalance
\=roundrobin&methods\=doCreateOrder&pid\=16484&revision\=1.0&side\=provider×tamp\=1572764847308&version\=1.0进入listener.notify(categoryList) 中
RegistryDirectory class
/**
* 当收到服务变更通知时触发。
* <p>
* 通知需处理契约:<br>
* 1. 总是以服务接口和数据类型为维度全量通知,即不会通知一个服务的同类型的部分数据,用户不需要对比上一次通知结果。<br>
* 2. 订阅时的第一次通知,必须是一个服务的所有类型数据的全量通知。<br>
* 3. 中途变更时,允许不同类型的数据分开通知,比如:providers, consumers, routers, overrides,允许只通知其中一种类型,但该类型的数据必须是全量的,不是增量的。<br>
* 4. 如果一种类型的数据为空,需通知一个empty协议并带category参数的标识性URL数据。<br>
* 5. 通知者(即注册中心实现)需保证通知的顺序,比如:单线程推送,队列串行化,带版本对比。<br>
*
* @param urls 已注册信息列表,总不为空,含义同{@link com.alibaba.dubbo.registry.RegistryService#lookup(URL)}的返回值。
*/
public synchronized void notify(List<URL> urls) {
// invokerurl
List<URL> invokerUrls = new ArrayList<URL>();
List<URL> routerUrls = new ArrayList<URL>();
List<URL> configuratorUrls = new ArrayList<URL>();
for (URL url : urls) {
String protocol = url.getProtocol();
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
if (Constants.ROUTERS_CATEGORY.equals(category)
|| Constants.ROUTE_PROTOCOL.equals(protocol)) {
routerUrls.add(url);
} else if (Constants.CONFIGURATORS_CATEGORY.equals(category)
|| Constants.OVERRIDE_PROTOCOL.equals(protocol)) {
configuratorUrls.add(url);
} else if (Constants.PROVIDERS_CATEGORY.equals(category)) {
invokerUrls.add(url);
} else {
logger.warn("Unsupported category " + category + " in notified url: " + url + " from registry " + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost());
}
}
// configurators
if (configuratorUrls != null && configuratorUrls.size() > 0) {
this.configurators = toConfigurators(configuratorUrls);
}
// routers
if (routerUrls != null && routerUrls.size() > 0) {
List<Router> routers = toRouters(routerUrls);
if (routers != null) { // null - do nothing
setRouters(routers);
}
}
List<Configurator> localConfigurators = this.configurators; // local reference
// 合并override参数
this.overrideDirectoryUrl = directoryUrl;
if (localConfigurators != null && localConfigurators.size() > 0) {
for (Configurator configurator : localConfigurators) {
this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl);
}
}
// providers 节点下的数据才会进入该方法中进行处理
refreshInvoker(invokerUrls);
}重点关注 refreshInvoker(invokerUrls);
RegistryDirectory
private void refreshInvoker(List<URL> invokerUrls) {
// empty 协议
if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null
&& Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) {
this.forbidden = true; // 禁止访问
this.methodInvokerMap = null; // 置空列表
destroyAllInvokers(); // 关闭所有Invoker
} else {
this.forbidden = false; // 允许访问
Map<String, Invoker<T>> oldUrlInvokerMap = this.urlInvokerMap; // local reference
if (invokerUrls.size() == 0 && this.cachedInvokerUrls != null) {
invokerUrls.addAll(this.cachedInvokerUrls);
} else {
this.cachedInvokerUrls = new HashSet<URL>();
this.cachedInvokerUrls.addAll(invokerUrls);//缓存invokerUrls列表,便于交叉对比
}
if (invokerUrls.size() == 0) {
return;
}
// 生成invoker
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// 将URL列表转成Invoker列表
Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 换方法名映射Invoker列表
// state change
//如果计算错误,则不进行处理.
if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) {
logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :" + invokerUrls.size() + ", invoker.size :0. urls :" + invokerUrls.toString()));
return;
}
this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
this.urlInvokerMap = newUrlInvokerMap;
try {
destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // 关闭未使用的Invoker
} catch (Exception e) {
logger.warn("destroyUnusedInvokers error. ", e);
}
}
}- 参数解释
- invokerUrls 为多个协议数据dubbo://169.254.88.190:20881/com.zmz.order.api.IOrderService?anyhost=true&application=order-provider&dubbo=2.5.5&generic=false&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=15332&revision=1.0&side=provider×tamp=1572674326351&version=1.0
RegistryDirectory
private Map<String, Invoker<T>> toInvokers(List<URL> urls) {
Map<String, Invoker<T>> newUrlInvokerMap = new HashMap<String, Invoker<T>>();
if (urls == null || urls.size() == 0) {
return newUrlInvokerMap;
}
Set<String> keys = new HashSet<String>();
// 获取可以接受的协议
urls 为provieders的url 协议可能有多个 //查找满足条件的协议
String queryProtocols = this.queryMap.get(Constants.PROTOCOL_KEY);
for (URL providerUrl : urls) {
//如果reference端配置了protocol,则只选择匹配的protocol
if (queryProtocols != null && queryProtocols.length() > 0) {
boolean accept = false;
String[] acceptProtocols = queryProtocols.split(",");
for (String acceptProtocol : acceptProtocols) {
if (providerUrl.getProtocol().equals(acceptProtocol)) {
accept = true;
break;
}
}
if (!accept) {
continue;
}
}
if (Constants.EMPTY_PROTOCOL.equals(providerUrl.getProtocol())) {
continue;
}
if (!ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) {
logger.error(new IllegalStateException("Unsupported protocol " + providerUrl.getProtocol() + " in notified url: " + providerUrl + " from registry " + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost()
+ ", supported protocol: " + ExtensionLoader.getExtensionLoader(Protocol.class).getSupportedExtensions()));
continue;
}
// 合并url参数 这里是为什么消费端配置数据优先的原因 详情参考标注!!1
URL url = mergeUrl(providerUrl);
String key = url.toFullString(); // URL参数是排序的
if (keys.contains(key)) { // 重复URL
continue;
}
keys.add(key);
// 缓存key为没有合并消费端参数的URL,不管消费端如何合并参数,如果服务端URL发生变化,则重新refer
Map<String, Invoker<T>> localUrlInvokerMap = this.urlInvokerMap; // local reference
Invoker<T> invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.get(key);
if (invoker == null) { // 缓存中没有,重新refer
try {
boolean enabled = true;
if (url.hasParameter(Constants.DISABLED_KEY)) {
enabled = !url.getParameter(Constants.DISABLED_KEY, false);
} else {
enabled = url.getParameter(Constants.ENABLED_KEY, true);
}
// 此处创建了InvokeDelegete 对象
if (enabled) {
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);
}
} catch (Throwable t) {
logger.error("Failed to refer invoker for interface:" + serviceType + ",url:(" + url + ")" + t.getMessage(), t);
}
if (invoker != null) { // 将新的引用放入缓存
newUrlInvokerMap.put(key, invoker);
}
} else {
newUrlInvokerMap.put(key, invoker);
}
}
keys.clear();
return newUrlInvokerMap;
}分析这段代码
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);参数解释
protocol 为自适应扩展点- serviceType com.zmz.order.api.IOrderService
url dubbo://169.254.88.190:20881/com.zmz.order.api.IOrderService?anyhost=true&application=user-consumer&check=false&default.check=false&dubbo=2.5.5&generic=false&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=17964&protocol=dubbo&revision=1.0&side=consumer×tamp=1572686580170&version=1.0
此时根据url的protocol 进入DubboProtocol的refer()方法
public class DubboProtocol extends AbstractProtocol {
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
// create rpc invoker.
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
// 建立连接
private ExchangeClient[] getClients(URL url) {
//是否共享连接
boolean service_share_connect = false;
int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0);
//如果connections不配置,则共享连接,否则每服务每连接
if (connections == 0) {
service_share_connect = true;
connections = 1;
}
ExchangeClient[] clients = new ExchangeClient[connections];
for (int i = 0; i < clients.length; i++) {
if (service_share_connect) {
clients[i] = getSharedClient(url);
} else {
clients[i] = initClient(url);
}
}
return clients;
}
}此时我们知道了invoke为DubboInvoker (当前会进行包装)
key 为 dubbo://169.254.88.190:20881/com.zmz.order.api.IOrderService?anyhost=true&application=user-consumer&check=false&default.check=false&dubbo=2.5.5&generic=false&interface=com.zmz.order.api.IOrderService&methods=doCreateOrder&pid=17964&protocol=dubbo&revision=1.0&side=consumer×tamp=1572686580170&version=1.0
private volatile Map<String, Invoker<T>> urlInvokerMap;
public abstract class AbstractProtocol implements Protocol {
protected final Logger logger = LoggerFactory.getLogger(getClass());
// 这个是服务端提供的export
protected final Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();
// 这个是消费端的invoker代理
//TODO SOFEREFENCE
protected final Set<Invoker<?>> invokers = new ConcurrentHashSet<Invoker<?>>();继续分析这段代码
RegistryProtocol
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
return cluster.join(directory);
}- 参数解释
cluster com.alibaba.dubbo.rpc.cluster.Cluster$Adpative 默认是 FailOverCluster(失败重试) 当前还会进行wrapper MockClusterWrapper(FailOverCluster)- directory 为com.alibaba.dubbo.registry.RegistryDirectory
分析invoker的生成
public class MockClusterWrapper implements Cluster {
private Cluster cluster;
public MockClusterWrapper(Cluster cluster) {
this.cluster = cluster;
}
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return new MockClusterInvoker<T>(directory,
this.cluster.join(directory));
}
}
接下来进入FailoverCluster 中
public class FailoverCluster implements Cluster {
public final static String NAME = "failover";
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return new FailoverClusterInvoker<T>(directory);
}
}分析下失败重试如何进行
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);
public FailoverClusterInvoker(Directory<T> directory) {
super(directory);
}
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
List<Invoker<T>> copyinvokers = invokers;
checkInvokers(copyinvokers, invocation);
// 此处定义了dubbo重试的次数
// Constants.RETRIES_KEY 对应url参数 retries
// Constants.DEFAULT_RETRIES 对应 public static final int DEFAULT_RETRIES = 2;// 为何加1 ? 重试次数不包括正常调用的一次
int len = getUrl().getMethodParameter(invocation.getMethodName(),
Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// retry loop.
RpcException le = null; // last exception.
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
//重试时,进行重新选择,避免重试时invoker列表已发生变化.
//注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
if (i > 0) {
// 检查是否停止服务(正在调用时 消费端停机)
checkWhetherDestroyed();
//
copyinvokers = list(invocation);
//重新检查一下
checkInvokers(copyinvokers, invocation);
}
// 负载均衡
Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
Result result = invoker.invoke(invocation);
if (le != null && logger.isWarnEnabled()) {
//省略部分代码
}
return result;
} catch (RpcException e) {
if (e.isBiz()) { // biz exception.
throw e;
}
le = e;
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
providers.add(invoker.getUrl().getAddress());
}
}
//省略部分代码
}
}回到最开始的这段代码
ReferenceConfig
return (T) proxyFactory.getProxy(invoker);参数解释
proxyFactory 为ProxyFactory$Adaptive 根据默认实现Javaassistinvoker 为生成的invoker MockClusterInovker(FailOverClusterInvoker)- 当然RegistryDirectory的invoker是经过了包装的
进入AbstractProxyFactory.getProxy()方法
public abstract class AbstractProxyFactory implements ProxyFactory {
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
Class<?>[] interfaces = null;
// interface -> com.zmz.order.api.IOrderService
// 无interfaces
String config = invoker.getUrl().getParameter("interfaces");
if (config != null && config.length() > 0) {
String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null && types.length > 0) {
interfaces = new Class<?>[types.length + 2];
interfaces[0] = invoker.getInterface();
interfaces[1] = EchoService.class;
for (int i = 0; i < types.length; i++) {
interfaces[i + 1] = ReflectUtils.forName(types[i]);
}
}
}
// 进入这段代码
if (interfaces == null) {
interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
}
return getProxy(invoker, interfaces);
}接着进入子类JavassistProxyFactory 中
public class JavassistProxyFactory extends AbstractProxyFactory {
// 这个是消费端的代理
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
// 这个是服务端的代理
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper类不能正确处理带$的类名
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}从上面的getProxy方法中的InvokerInvocationHandler 对象 我们可以猜想InvokerInvocationHandler 肯定实现了java中的InvocationHandler接口
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}所以最终生成的ref为

接着分析下服务调用的流程
orderService.doCreateOrder("ss");- orderService 为前面生成的代理对象ref
因为ref为InvokerInvocationHandler 对象 此时进入invoker方法
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 获取方法名称
String methodName = method.getName();
// 获取方法参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
// 进入具体调用
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}此处的invoker为MockCluster(FailOverClusterInvoker) 对象
进入MockCluster的invoker 方法
public class MockClusterInvoker<T> implements Invoker<T> {
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
// 是否需要执行mock
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
if (value.length() == 0 || value.equalsIgnoreCase("false")) {
//no mock
result = this.invoker.invoke(invocation);
} else if (value.startsWith("force")) {
if (logger.isWarnEnabled()) {
logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
}
//force:direct mock
result = doMockInvoke(invocation, null);
} else {
//fail-mock
try {
result = this.invoker.invoke(invocation);
} catch (RpcException e) {
if (e.isBiz()) {
throw e;
} else {
if (logger.isWarnEnabled()) {
logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
}
result = doMockInvoke(invocation, e);
}
}
}
return result;
}
public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
private static final Logger logger = LoggerFactory
.getLogger(AbstractClusterInvoker.class);
protected final Directory<T> directory;
protected final boolean availablecheck;
private AtomicBoolean destroyed = new AtomicBoolean(false);
private volatile Invoker<T> stickyInvoker = null;
public Result invoke(final Invocation invocation) throws RpcException {
// 检查是否停止
checkWhetherDestroyed();
// 负载均衡 (稍后单独分析)
LoadBalance loadbalance;
// 获取invokers
List<Invoker<T>> invokers = list(invocation);
// 获取负载均衡策略
if (invokers != null && invokers.size() > 0) {
// 从方法上获取
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
.getMethodParameter(invocation.getMethodName(), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
} else {
// 默认为随机
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return doInvoke(invocation, invokers, loadbalance);
}
protected void checkWhetherDestroyed() {
if (destroyed.get()) {
throw new RpcException("Rpc cluster invoker for " + getInterface() + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ " is now destroyed! Can not invoke any more.");
}
}
protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
LoadBalance loadbalance) throws RpcException;
// 从服务目录中获取invokers
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
List<Invoker<T>> invokers = directory.list(invocation);
return invokers;
}接着分析核心代码 directory.list(invocation);
此时 RegistryDirectory 根据调用的class method 查找invoker
AbstractDirectory
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
// 判断是否已关闭
if (destroyed) {
throw new RpcException("Directory already destroyed .url: " + getUrl());
}
// 模板方法 交由子类实现
List<Invoker<T>> invokers = doList(invocation);
List<Router> localRouters = this.routers; // local reference
if (localRouters != null && localRouters.size() > 0) {
for (Router router : localRouters) {
try {
if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, true)) {
invokers = router.route(invokers, getConsumerUrl(), invocation);
}
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
}
}
return invokers;
}RegistryDirectory<T> extends AbstractDirectory<T>
public List<Invoker<T>> doList(Invocation invocation) {
if (forbidden) {
// 1. 没有服务提供者 2. 服务提供者被禁用
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION,
"No provider available from registry " + getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion() + ", may be providers disabled or not registered ?");
}
List<Invoker<T>> invokers = null;
// 直接从本地缓存中获取 (当服务提供者节点变化时 触发notify方法 进行refresh)
//此时此处不为空
Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; // local reference
if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) {
// 获取调用的方法名
String methodName = RpcUtils.getMethodName(invocation);
// 方法实参
Object[] args = RpcUtils.getArguments(invocation);
// 第一个参数时枚举时
if (args != null && args.length > 0 && args[0] != null
&& (args[0] instanceof String || args[0].getClass().isEnum())) {
invokers = localMethodInvokerMap.get(methodName + "." + args[0]); // 可根据第一个参数枚举路由
}
//此时invokers肯定为null
if (invokers == null) {
// 从此处获取到invokers
invokers = localMethodInvokerMap.get(methodName);
}
if (invokers == null) {
invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);
}
if (invokers == null) {
Iterator<List<Invoker<T>>> iterator = localMethodInvokerMap.values().iterator();
if (iterator.hasNext()) {
invokers = iterator.next();
}
}
}
return invokers == null ? new ArrayList<Invoker<T>>(0) : invokers;
}参数介绍
localMethodInvokerMap
接着分析 return doInvoke(invocation, invokers, loadbalance);
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
List<Invoker<T>> copyinvokers = invokers;
checkInvokers(copyinvokers, invocation);
int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// retry loop.
RpcException le = null; // last exception.
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
//重试时,进行重新选择,避免重试时invoker列表已发生变化.
//注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
if (i > 0) {
checkWhetherDestroyed();
copyinvokers = list(invocation);
//重新检查一下
checkInvokers(copyinvokers, invocation);
}
// 通过父子啊均衡策略去获取invoker
Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
//执行
Result result = invoker.invoke(invocation);
if (le != null && logger.isWarnEnabled()) {
logger.warn("Although retry the method " + invocation.getMethodName()
+ " in the service " + getInterface().getName()
+ " was successful by the provider " + invoker.getUrl().getAddress()
+ ", but there have been failed providers " + providers
+ " (" + providers.size() + "/" + copyinvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
+ le.getMessage(), le);
}
return result;
} catch (RpcException e) {
if (e.isBiz()) { // biz exception.
throw e;
}
le = e;
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
providers.add(invoker.getUrl().getAddress());
}
}
throw new RpcException(le != null ? le.getCode() : 0, "Failed to invoke the method "
+ invocation.getMethodName() + " in the service " + getInterface().getName()
+ ". Tried " + len + " times of the providers " + providers
+ " (" + providers.size() + "/" + copyinvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+ Version.getVersion() + ". Last error is: "
+ (le != null ? le.getMessage() : ""), le != null && le.getCause() != null ? le.getCause() : le);
}
public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
private Invoker<T> doselect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
if (invokers == null || invokers.size() == 0)
return null;
if (invokers.size() == 1)
return invokers.get(0);
// 如果只有两个invoker,退化成轮循
if (invokers.size() == 2 && selected != null && selected.size() > 0) {
return selected.get(0) == invokers.get(0) ? invokers.get(1) : invokers.get(0);
}
// 通过负载均衡策略去获取
Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);
//如果 selected中包含(优先判断) 或者 不可用&&availablecheck=true 则重试.
if ((selected != null && selected.contains(invoker))
|| (!invoker.isAvailable() && getUrl() != null && availablecheck)) {
try {
Invoker<T> rinvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck);
if (rinvoker != null) {
invoker = rinvoker;
} else {
//看下第一次选的位置,如果不是最后,选+1位置.
int index = invokers.indexOf(invoker);
try {
//最后在避免碰撞
invoker = index < invokers.size() - 1 ? invokers.get(index + 1) : invoker;
} catch (Exception e) {
logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e);
}
}
} catch (Throwable t) {
logger.error("clustor relselect fail reason is :" + t.getMessage() + " if can not slove ,you can set cluster.availablecheck=false in url", t);
}
}
return invoker;
}
接着分析下负载均衡策略
RoundRobinLoadBalance 轮询
RandomLoadBalance 随机
LeastActiveLoadBalance 最少活跃度调用
ConsistentHashLoadBalance 一致性哈希 (每个节点虚拟出160个子节点)先从轮询算法开始一个个分析
RoundRobinLoadBalance 轮询算法(加权轮询)
private final ConcurrentMap<String, AtomicPositiveInteger> sequences =
new ConcurrentHashMap<String, AtomicPositiveInteger>();
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
int length = invokers.size(); // 总个数
int maxWeight = 0; // 最大权重
int minWeight = Integer.MAX_VALUE; // 最小权重
final LinkedHashMap<Invoker<T>, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<Invoker<T>, IntegerWrapper>();
// 总权重
int weightSum = 0;
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
maxWeight = Math.max(maxWeight, weight); // 累计最大权重
minWeight = Math.min(minWeight, weight); // 累计最小权重
if (weight > 0) {
invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight));
weightSum += weight;
}
}
// 查看当前第几次调用
AtomicPositiveInteger sequence = sequences.get(key);
if (sequence == null) {
sequences.putIfAbsent(key, new AtomicPositiveInteger());
sequence = sequences.get(key);
}
int currentSequence = sequence.getAndIncrement();
if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样
// 取模
int mod = currentSequence % weightSum;
for (int i = 0; i < maxWeight; i++) {
for (Map.Entry<Invoker<T>, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
final Invoker<T> k = each.getKey();
final IntegerWrapper v = each.getValue();
if (mod == 0 && v.getValue() > 0) {
return k;
}
if (v.getValue() > 0) {
v.decrement();
mod--;
}
}
}
}
// 取模轮循 权重相等时
return invokers.get(currentSequence % length);
}未完待续!!!!!!
- url级别
标注!!1 url参数合并
RegistryDirectory
private URL mergeUrl(URL providerUrl) {
providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // 合并消费端参数
}public static URL mergeUrl(URL remoteUrl, Map<String, String> localMap) {
Map<String, String> map = new HashMap<String, String>();
// 服务提供者url 参数
Map<String, String> remoteMap = remoteUrl.getParameters();
if (remoteMap != null && remoteMap.size() > 0) {
map.putAll(remoteMap);
//线程池配置不使用提供者的
map.remove(Constants.THREAD_NAME_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREAD_NAME_KEY);
map.remove(Constants.THREADPOOL_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREADPOOL_KEY);
map.remove(Constants.CORE_THREADS_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.CORE_THREADS_KEY);
map.remove(Constants.THREADS_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREADS_KEY);
map.remove(Constants.QUEUES_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.QUEUES_KEY);
map.remove(Constants.ALIVE_KEY);
map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.ALIVE_KEY);
}
if (localMap != null && localMap.size() > 0) {
map.putAll(localMap);
}
if (remoteMap != null && remoteMap.size() > 0) {
// 版本号使用提供者的
String dubbo = remoteMap.get(Constants.DUBBO_VERSION_KEY);
if (dubbo != null && dubbo.length() > 0) {
map.put(Constants.DUBBO_VERSION_KEY, dubbo);
}
String version = remoteMap.get(Constants.VERSION_KEY);
if (version != null && version.length() > 0) {
map.put(Constants.VERSION_KEY, version);
}
String group = remoteMap.get(Constants.GROUP_KEY);
if (group != null && group.length() > 0) {
map.put(Constants.GROUP_KEY, group);
}
String methods = remoteMap.get(Constants.METHODS_KEY);
if (methods != null && methods.length() > 0) {
map.put(Constants.METHODS_KEY, methods);
}
// 合并filter和listener
String remoteFilter = remoteMap.get(Constants.REFERENCE_FILTER_KEY);
String localFilter = localMap.get(Constants.REFERENCE_FILTER_KEY);
if (remoteFilter != null && remoteFilter.length() > 0
&& localFilter != null && localFilter.length() > 0) {
localMap.put(Constants.REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
}
String remoteListener = remoteMap.get(Constants.INVOKER_LISTENER_KEY);
String localListener = localMap.get(Constants.INVOKER_LISTENER_KEY);
if (remoteListener != null && remoteListener.length() > 0
&& localListener != null && localListener.length() > 0) {
localMap.put(Constants.INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
}
}
return remoteUrl.clearParameters().addParameters(map);
}
