ReferenceBean实现了InitializingBean接口,Spring初始化时会调用afterPropertiesSet()
public void afterPropertiesSet() throws Exception {
if (getConsumer() == null) {
/*省略代码,读取consumerConfig,然后set到该Bean中*/
setConsumer(consumerConfig);
}
/*省略代码,类似上述过程,读取applicationConfig、moduleConfig、registryConfigs、monitorConfig,然后set到该Bean中*/
//如果consumerConfig或者该bean配置了init,则直接getObject()
Boolean b = isInit();
if (b == null && getConsumer() != null) {
b = getConsumer().isInit();
}
if (b != null && b.booleanValue()) {
getObject();
}
}
如果没有配置init,由于ReferenceBean实现了FactoryBean接口,所以会在实例化时调用getObject()方法。
public Object getObject() throws Exception {
return get();
}
public synchronized T get() {
if (destroyed) {
throw new IllegalStateException("Already destroyed!");
}
//如果为空则初始化
if (ref == null) {
init();
}
return ref;
}
ReferenceConfig#init(),init方法对dubbo的配置进行了封装
private void init() {
//避免重复初始化
if (initialized) {
return;
}
initialized = true;
if (interfaceName == null || interfaceName.length() == 0) {
throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
}
//判断ConsumerConfig是否为空,为空则创建新对象,然后通过系统变量或dubbo.properties填充属性
checkDefault();
//系统变量或dubbo.properties填充属性
appendProperties(this);
//判断是否是Generic,缺省使用Consumer配置
if (getGeneric() == null && getConsumer() != null) {
setGeneric(getConsumer().getGeneric());
}
//Generic则设置interfaceClass
if (ProtocolUtils.isGeneric(getGeneric())) {
interfaceClass = GenericService.class;
} else {
try {
//类加载
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, methods);
}
//获取系统变量中interfaceName对应的属性
String resolve = System.getProperty(interfaceName);
String resolveFile = null;
if (resolve == null || resolve.length() == 0) {
//从系统变量中获得resolveFile
resolveFile = System.getProperty("dubbo.resolve.file");
//没获取到就从用户目录下获得dubbo-resolve.properties
if (resolveFile == null || resolveFile.length() == 0) {
File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
if (userResolveFile.exists()) {
resolveFile = userResolveFile.getAbsolutePath();
}
}
//文件不为空则加载属性
if (resolveFile != null && resolveFile.length() > 0) {
Properties properties = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(resolveFile));
properties.load(fis);
} catch (IOException e) {
throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e);
} finally {
try {
if (null != fis) fis.close();
} catch (IOException e) {
logger.warn(e.getMessage(), e);
}
}
resolve = properties.getProperty(interfaceName);
}
}
//如果resolve则复制给url
if (resolve != null && resolve.length() > 0) {
url = resolve;
/*省略代码,logger*/
}
//从consumer、module、application加载属性,覆盖策略体现
if (consumer != null) {
if (application == null) {
application = consumer.getApplication();
}
if (module == null) {
module = consumer.getModule();
}
if (registries == null) {
registries = consumer.getRegistries();
}
if (monitor == null) {
monitor = consumer.getMonitor();
}
}
if (module != null) {
if (registries == null) {
registries = module.getRegistries();
}
if (monitor == null) {
monitor = module.getMonitor();
}
}
if (application != null) {
if (registries == null) {
registries = application.getRegistries();
}
if (monitor == null) {
monitor = application.getMonitor();
}
}
//检查Application,为空则创建新对象,然后通过系统变量或dubbo.properties填充属性
checkApplication();
//检查本地存根 http://dubbo.apache.org/zh-cn/docs/user/demos/local-stub.html 和 mock http://dubbo.apache.org/zh-cn/docs/user/demos/local-mock.html
checkStubAndMock(interfaceClass);
//new一个存放属性的map
Map<String, String> map = new HashMap<String, String>();
Map<Object, Object> attributes = new HashMap<Object, Object>();
//添加side、dubbo版本信息、时间戳和进程号等信息到map中
map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
map.put(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
}
if (!isGeneric()) {
String revision = Version.getVersion(interfaceClass, version);
//添加版本到map中
if (revision != null && revision.length() > 0) {
map.put("revision", revision);
}
//添加接口方法列表到map中
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if (methods.length == 0) {
logger.warn("NO method found in service interface " + interfaceClass.getName());
map.put("methods", Constants.ANY_VALUE);
} else {
map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
}
}
//添加接口名称到map中
map.put(Constants.INTERFACE_KEY, interfaceName);
//添加application、module、consumer和本引用的属性到map中
appendParameters(map, application);
appendParameters(map, module);
appendParameters(map, consumer, Constants.DEFAULT_KEY);
appendParameters(map, this);
String prefix = StringUtils.getServiceKey(map);
if (methods != null && !methods.isEmpty()) {
//遍历MethodConfig http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-method.html
for (MethodConfig method : methods) {
appendParameters(map, method, method.getName());
String retryKey = method.getName() + ".retry";
//判断map是否包含methodName.retry
if (map.containsKey(retryKey)) {
String retryValue = map.remove(retryKey);
//添加重试次数属性
if ("false".equals(retryValue)) {
map.put(method.getName() + ".retries", "0");
}
}
// 添加MethodConfig中的属性到attributes
appendAttributes(attributes, method, prefix + "." + method.getName());
checkAndConvertImplicitConfig(method, map, attributes);
}
}
//获取ip地址
String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY);
if (hostToRegistry == null || hostToRegistry.length() == 0) {
hostToRegistry = NetUtils.getLocalHost();
} else if (isInvalidLocalHost(hostToRegistry)) {
throw new IllegalArgumentException("Specified invalid registry ip from property:" + Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
}
map.put(Constants.REGISTER_IP_KEY, hostToRegistry);
//存储attributes到SystemContext
StaticContext.getSystemContext().putAll(attributes);
//创建代理
ref = createProxy(map);
//根据服务名,ReferenceConfig,代理类构建ConsumerModel
//并将ConsumerModel存入到ApplicationModel中
ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods());
ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel);
}
ReferenceConfig#createProxy(Map<String, String>)
private T createProxy(Map<String, String> map) {
//创建一个临时的URL
URL tmpUrl = new URL("temp", "localhost", 0, map);
final boolean isJvmRefer;
if (isInjvm() == null) {
if (url != null && url.length() > 0) { //如果指定了url,则不进行本地引用
isJvmRefer = false;
// 根据url的属性判断是否需要本地引用,scope和injvm参数等
// 默认情况下,如果本地启动服务,则引用本地服务
} else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
isJvmRefer = true;
} else {
isJvmRefer = false;
}
} else {
isJvmRefer = isInjvm().booleanValue();
}
if (isJvmRefer) {
//生成本地引用URL,injvm协议
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
//生成InjvmInvoker实例,本地就不看了
invoker = refprotocol.refer(interfaceClass, url);
/*省略代码,logger*/
} else {
//指定URL参数的逻辑
if (url != null && url.length() > 0) {
//用户指定的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())) {
//生成URL并添加到对象变量中
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
} else {
//也是生成URL,但合并了一些属性
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
} else {
//加载注册中心URL,和服务暴露类似
List<URL> us = loadRegistries(false);
if (us != null && !us.isEmpty()) {
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.isEmpty()) {
/*省略代码,throw*/
}
}
if (urls.size() == 1) {
//单个注册中心
//构建invoker实例
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
//多个注册中心或指定URL
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
//生成所有注册中心的invoker
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // 使用最后一个注册URL
}
}
if (registryURL != null) { // 如果注册中心URL可用
//仅在注册中心群集可用时才使用AvailableCluster
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
//创建StaticDirectory实例,Cluster合并多个Invoker
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*/
}
if (logger.isInfoEnabled()) {
/*省略代码,logger*/
}
// 创建服务代理
return (T) proxyFactory.getProxy(invoker);
}
无论单注册中心或者多注册中心,都会先生成invoker,上述refprotocol.refer()实际调用Protocol$Adaptive#refer(Class ,com.alibaba.dubbo.common.URL ),和服务暴露相同,通过Adaptive的机制会获得一个实例,因为URL的protocol为registry,所以会获得RegistryProtocol的一个包装类。
最终调用RegistryProtocol#refer(Class, URL)
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
//因为我使用了zookeeper,所以Protocol设置为zookeeper,然后生成一个新的URL
url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
//registryFactory是SPI扩展类,获得Registry和服务暴露相同,跳过
Registry registry = registryFactory.getRegistry(url);
if (RegistryService.class.equals(type)) {
return proxyFactory.getInvoker((T) registry, type, url);
}
//还原refer的map,就是刚才new出来存放属性的map
Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
//获取 group 配置
//group="a,b" or group="*"
String group = qs.get(Constants.GROUP_KEY);
if (group != null && group.length() > 0) {
if ((Constants.COMMA_SPLIT_PATTERN.split(group)).length > 1
|| "*".equals(group)) {
//getMergeableCluster()通过SPI机制获得MergeableCluster实例
return doRefer(getMergeableCluster(), registry, type, url);
}
}
return doRefer(cluster, registry, type, url);
}
RegistryProtocol#doRefer(Cluster, Registry, Class, URL)
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//封装接口和注册中心URL,URL中有服务消费者的属性,key=refer
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
directory.setRegistry(registry);
directory.setProtocol(protocol);
//key=refer的所有属性
Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
//生成消费者URL
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
&& url.getParameter(Constants.REGISTER_KEY, true)) {
//注册消费者,在consumers目录注册新节点,和服务暴露相同
registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
Constants.CHECK_KEY, String.valueOf(false)));
}
//订阅PROVIDERS、CONFIGURATORS、ROUTERS等节点数据,先往下看
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
//cluster合并服务,一个服务可能会有多个节点
Invoker invoker = cluster.join(directory);
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker;
}
subscribeUrl.addParameter()向URL中添加了category属性,订阅了这些数据。directory.subscribe()调用了RegistryDirectory#subscribe(URL)
public void subscribe(URL url) {
//set到对象变量
setConsumerUrl(url);
registry.subscribe(url, this);
}
registry.subscribe()调用ZookeeperRegistry的父类FailbackRegistry#subscribe(URL, NotifyListener)
public void subscribe(URL url, NotifyListener listener) {
// 将回调方法缓存到对象变量ConcurrentMap<URL, Set<NotifyListener>> subscribed
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.isEmpty()) {
notify(url, listener, urls);
/*省略代码,logger*/
} 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*/
} else {
/*省略代码,logger*/
}
}
// 将失败的注册请求记录到失败的列表中,定期重试
addFailedSubscribed(url, listener);
}
}
ZookeeperRegistry#doSubscribe(final URL , final NotifyListener )
protected void doSubscribe(final URL url, final NotifyListener listener) {
try {
//ANY_VALUE = *,监听/dubbo根目录,getServiceInterface()方法获得URL中interface的value,所以一般走else
if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
/*省略代码,一般会指定interface,所以直接看else*/
} else {
List<URL> urls = new ArrayList<URL>();
// 从URL取出订阅的PROVIDERS、CONFIGURATORS、ROUTERS节点数据,并分类
// 分类结果举例:
// /dubbo/接口路径/providers
for (String path : toCategoriesPath(url)) {
// 缓存中取,若为空则new ChildListener()
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() {
@Override
public void childChanged(String parentPath, List<String> currentChilds) {
ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
zkListener = listeners.get(listener);
}
// 创建zk目录
zkClient.create(path, false);
// 添加listener
List<String> children = zkClient.addChildListener(path, zkListener);
if (children != null) {
//生成provider的URL和其他URL(CONFIGURATORS、ROUTERS),添加到List中
urls.addAll(toUrlsWithEmpty(url, path, children));
}
}
//通知
notify(url, listener, urls);
}
} catch (Throwable e) {
/*省略代码,throw*/
}
}
FailbackRegistry#notify(URL , NotifyListener , List )
protected void notify(URL url, NotifyListener listener, List<URL> urls) {
/*省略代码,入参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);
/*省略代码,throw*/
}
}
FailbackRegistry#doNotify(URL , NotifyListener , List )
protected void doNotify(URL url, NotifyListener listener, List<URL> urls) {
super.notify(url, listener, urls);
}
调用FailbackRegistry的父类AbstractRegistry#notify(URL, NotifyListener, List)
protected void notify(URL url, NotifyListener listener, List<URL> urls) {
/*省略代码,入参null校验*/
// 过滤,以category为key添加到map中,key为providers等
Map<String, List<URL>> result = new HashMap<String, List<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);
}
}
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);
// 本地文件保存
saveProperties(url);
listener.notify(categoryList);
}
}
listener.notify(categoryList)调用RegistryDirectory#notify(List),小小绕了一圈又回到了RegistryDirectory这边
public synchronized void notify(List<URL> urls) {
List<URL> invokerUrls = new ArrayList<URL>();
List<URL> routerUrls = new ArrayList<URL>();
List<URL> configuratorUrls = new ArrayList<URL>();
// 分类添加到上面的List中
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*/
}
}
// configurators 跳过,以后再写
if (configuratorUrls != null && !configuratorUrls.isEmpty()) {
this.configurators = toConfigurators(configuratorUrls);
}
// routers 跳过,以后再写
if (routerUrls != null && !routerUrls.isEmpty()) {
List<Router> routers = toRouters(routerUrls);
if (routers != null) { // null - do nothing
setRouters(routers);
}
}
List<Configurator> localConfigurators = this.configurators; // local reference
// merge override parameters
this.overrideDirectoryUrl = directoryUrl;
if (localConfigurators != null && !localConfigurators.isEmpty()) {
for (Configurator configurator : localConfigurators) {
this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl);
}
}
// 刷新providers
refreshInvoker(invokerUrls);
}
RegistryDirectory#refreshInvoker(List )
private void refreshInvoker(List<URL> invokerUrls) {
// 入参为空
if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null
&& Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) {
this.forbidden = true; // Forbid to access
this.methodInvokerMap = null; // 清空Invoker Map
destroyAllInvokers(); // 关闭所有Invoker
} else {
this.forbidden = false; // Allow to access
// 对象变量缓存服务URL和Invoker的map
Map<String, Invoker<T>> oldUrlInvokerMap = this.urlInvokerMap;
// 缓存新的invokerUrls,比较方便
if (invokerUrls.isEmpty() && this.cachedInvokerUrls != null) {
invokerUrls.addAll(this.cachedInvokerUrls);
} else {
this.cachedInvokerUrls = new HashSet<URL>();
this.cachedInvokerUrls.addAll(invokerUrls);
}
if (invokerUrls.isEmpty()) {
return;
}
// 将URL list 转为Invoker map,先往下看这个
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);
Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 换方法名映射Invoker列表
// state change
// 如果计算错误,则不进行处理
if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) {
/*省略代码,logger*/
return;
}
this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
this.urlInvokerMap = newUrlInvokerMap;
try {
destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // 关闭未使用的Invoker
} catch (Exception e) {
/*省略代码,logger*/
}
}
}
RegistryDirectory#toInvokers(List ),将URL转换为Invoker,如果URL已被引用,则不会重新引用。
private Map<String, Invoker<T>> toInvokers(List<URL> urls) {
Map<String, Invoker<T>> newUrlInvokerMap = new HashMap<String, Invoker<T>>();
if (urls == null || urls.isEmpty()) {
return newUrlInvokerMap;
}
Set<String> keys = new HashSet<String>();
// 构造时传入的参数,获得Protocols
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*/
continue;
}
// 合并url参数,覆盖顺序为override > -D >Consumer > Provider
URL url = mergeUrl(providerUrl);
String key = url.toFullString(); // URL参数是排序的
// 判断本次是否重复
if (keys.contains(key)) {
continue;
}
keys.add(key);
// 缓存key为没有合并消费端参数的URL,不管消费端如何合并参数,如果服务端URL发生变化,则重新refer
Map<String, Invoker<T>> localUrlInvokerMap = this.urlInvokerMap; // 获取本地缓存
Invoker<T> invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.get(key);
// 缓存中没有,重新refer
if (invoker == null) {
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);
}
if (enabled) {
// protocol.refer生成Invoker,InvokerDelegate代理,先看refer
invoker = new InvokerDelegate<T>(protocol.refer(serviceType, url), url, providerUrl);
}
} catch (Throwable t) {
/*省略代码,logger*/
}
if (invoker != null) { // 将新的引用放入缓存
newUrlInvokerMap.put(key, invoker);
}
} else {
newUrlInvokerMap.put(key, invoker);
}
}
keys.clear();
return newUrlInvokerMap;
}
protocol.refer(serviceType, url)通过SPI机制获得Protocol包装类,最终调用DubboProtocol#refer(Class , URL )
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// 创建rpc invoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
getClients(url),调用了DubboProtocol#getClients(URL )
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;
}
getSharedClient(url)调用DubboProtocol#getSharedClient(URL )
private ExchangeClient getSharedClient(URL url) {
String key = url.getAddress();
// 引用计数
ReferenceCountExchangeClient client = referenceClientMap.get(key);
if (client != null) {
if (!client.isClosed()) {
client.incrementAndGetCount();
return client;
} else {
referenceClientMap.remove(key);
}
}
// 如果为空,或者已关闭
locks.putIfAbsent(key, new Object());
synchronized (locks.get(key)) {
if (referenceClientMap.containsKey(key)) {
return referenceClientMap.get(key);
}
// 创建 ExchangeClient 客户端,会创建一个nettyClient,该部分以后再讲
ExchangeClient exchangeClient = initClient(url);
client = new ReferenceCountExchangeClient(exchangeClient, ghostClientMap);
referenceClientMap.put(key, client);
ghostClientMap.remove(key);
locks.remove(key);
return client;
}
}
回到protocol.refer(serviceType, url)
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// 构造DubboInvoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
层层return,层层封装回到refreshInvoker(List invokerUrls)
private void refreshInvoker(List<URL> invokerUrls) {
// 入参为空
if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null
/*省略代码,之前提到过*/
} else {
/*省略代码,之前提到过*/
// 将URL list 转为Invoker map,先往下看这个
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);
Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 转换方法名映射Invoker列表
// state change
// 如果计算错误,则不进行处理
if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) {
/*省略代码,logger*/
return;
}
this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
this.urlInvokerMap = newUrlInvokerMap;
try {
destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // 关闭未使用的Invoker
} catch (Exception e) {
/*省略代码,logger*/
}
}
}
newUrlInvokerMap结构如下,因为只有一个服务,所以map只有一个kv
toMethodInvokers(newUrlInvokerMap)会转换方法名映射Invoker列表,如下:
最终回到createProxy(Map<String, String> map)
private T createProxy(Map<String, String> map) {
/*省略代码,上面提到过*/
if (isJvmRefer) {
/*省略代码,上面提到过*/
} else {
/*省略代码,上面提到过*/
if (urls.size() == 1) {
//单个注册中心
//构建invoker实例
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
//多个注册中心或指定URL
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
//生成所有注册中心的invoker
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // 使用最后一个注册URL
}
}
if (registryURL != null) { // 如果注册中心URL可用
//仅在注册中心群集可用时才使用AvailableCluster
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
//创建StaticDirectory实例,Cluster合并多个Invoker
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*/
}
if (logger.isInfoEnabled()) {
/*省略代码,logger*/
}
// 创建服务代理
return (T) proxyFactory.getProxy(invoker);
}
单个注册中心生成Invoker如下:
invoker生成后,接下来调用proxyFactory.getProxy(invoker)创建代理
ProxyFactory通过SPI机制获得StubProxyFactoryWrapper,调用com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper#getProxy(com.alibaba.dubbo.rpc.Invoker),该包装类默认包装了JavassistProxyFactory,也可以使用JdkProxyFactory
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
T proxy = proxyFactory.getProxy(invoker);
/*省略代码,本地存根*/
return proxy;
}
proxyFactory.getProxy(invoker)调用JavassistProxyFactory的父类,getProxy(Invoker , boolean )用来获取 interfaces 数组
public abstract class AbstractProxyFactory implements ProxyFactory {
@Override
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
return getProxy(invoker, false);
}
@Override
public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
Class<?>[] interfaces = null;
// 获取接口列表
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};
}
// 为 http 和 hessian 协议提供泛化调用支持
if (!invoker.getInterface().equals(GenericService.class) && generic) {
int len = interfaces.length;
Class<?>[] temp = interfaces;
interfaces = new Class<?>[len + 1];
System.arraycopy(temp, 0, interfaces, 0, len);
interfaces[len] = GenericService.class;
}
return getProxy(invoker, interfaces);
}
public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types);
}
public abstract T getProxy(Invoker , Class<?>[] )调用JavassistProxyFactory#getProxy(Invoker , Class<?>[] )
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
InvokerInvocationHandler就是jdk代理那个handler,主要看Proxy.getProxy(interfaces)
public static Proxy getProxy(Class<?>... ics) {
return getProxy(ClassHelper.getClassLoader(Proxy.class), ics);
}
这段比较复杂,直接复制了官方注释
public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
if (ics.length > 65535)
throw new IllegalArgumentException("interface limit exceeded");
StringBuilder sb = new StringBuilder();
// 遍历接口列表
for (int i = 0; i < ics.length; i++) {
String itf = ics[i].getName();
// 检测类型是否为接口
if (!ics[i].isInterface())
throw new RuntimeException(itf + " is not a interface.");
Class<?> tmp = null;
try {
// 重新加载接口类
tmp = Class.forName(itf, false, cl);
} catch (ClassNotFoundException e) {
}
// 检测接口是否相同,这里 tmp 有可能为空
if (tmp != ics[i])
throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
// 拼接接口全限定名,分隔符为 ;
sb.append(itf).append(';');
}
// 使用拼接后的接口名作为 key
String key = sb.toString();
Map<String, Object> cache;
synchronized (ProxyCacheMap) {
cache = ProxyCacheMap.get(cl);
if (cache == null) {
cache = new HashMap<String, Object>();
ProxyCacheMap.put(cl, cache);
}
}
Proxy proxy = null;
synchronized (cache) {
do {
// 从缓存中获取 Reference<Proxy> 实例
Object value = cache.get(key);
if (value instanceof Reference<?>) {
proxy = (Proxy) ((Reference<?>) value).get();
if (proxy != null) {
return proxy;
}
}
// 并发控制,保证只有一个线程可以进行后续操作
if (value == PendingGenerationMarker) {
try {
// 其他线程在此处进行等待
cache.wait();
} catch (InterruptedException e) {
}
} else {
// 放置标志位到缓存中,并跳出 while 循环进行后续操作
cache.put(key, PendingGenerationMarker);
break;
}
}
while (true);
}
long id = PROXY_CLASS_COUNTER.getAndIncrement();
String pkg = null;
ClassGenerator ccp = null, ccm = null;
try {
// 创建 ClassGenerator 对象
ccp = ClassGenerator.newInstance(cl);
Set<String> worked = new HashSet<String>();
List<Method> methods = new ArrayList<Method>();
for (int i = 0; i < ics.length; i++) {
// 检测接口访问级别是否为 protected 或 privete
if (!Modifier.isPublic(ics[i].getModifiers())) {
// 获取接口包名
String npkg = ics[i].getPackage().getName();
if (pkg == null) {
pkg = npkg;
} else {
if (!pkg.equals(npkg))
// 非 public 级别的接口必须在同一个包下,否者抛出异常
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
// 添加接口到 ClassGenerator 中
ccp.addInterface(ics[i]);
// 遍历接口方法
for (Method method : ics[i].getMethods()) {
// 获取方法描述,可理解为方法签名
String desc = ReflectUtils.getDesc(method);
// 如果方法描述字符串已在 worked 中,则忽略。考虑这种情况,
// A 接口和 B 接口中包含一个完全相同的方法
if (worked.contains(desc))
continue;
worked.add(desc);
int ix = methods.size();
// 获取方法返回值类型
Class<?> rt = method.getReturnType();
// 获取参数列表
Class<?>[] pts = method.getParameterTypes();
// 生成 Object[] args = new Object[1...N]
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
for (int j = 0; j < pts.length; j++)
// 生成 args[1...N] = ($w)$1...N;
code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
// 生成 InvokerHandler 接口的 invoker 方法调用语句,如下:
// Object ret = handler.invoke(this, methods[1...N], args);
code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
// 返回值不为 void
if (!Void.TYPE.equals(rt))
// 生成返回语句,形如 return (java.lang.String) ret;
code.append(" return ").append(asArgument(rt, "ret")).append(";");
methods.add(method);
// 添加方法名、访问控制符、参数列表、方法代码等信息到 ClassGenerator 中
ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
}
}
if (pkg == null)
pkg = PACKAGE_NAME;
// 构建接口代理类名称:pkg + ".proxy" + id,比如 org.apache.dubbo.proxy0
String pcn = pkg + ".proxy" + id;
ccp.setClassName(pcn);
ccp.addField("public static java.lang.reflect.Method[] methods;");
// 生成 private java.lang.reflect.InvocationHandler handler;
ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
// 为接口代理类添加带有 InvocationHandler 参数的构造方法,比如:
// porxy0(java.lang.reflect.InvocationHandler arg0) {
// handler=$1;
// }
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
// 为接口代理类添加默认构造方法
ccp.addDefaultConstructor();
// 生成接口代理类
Class<?> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// 构建 Proxy 子类名称,比如 Proxy1,Proxy2 等
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
ccm.setClassName(fcn);
ccm.addDefaultConstructor();
ccm.setSuperClass(Proxy.class);
// 为 Proxy 的抽象方法 newInstance 生成实现代码,形如:
// public Object newInstance(java.lang.reflect.InvocationHandler h) {
// return new org.apache.dubbo.proxy0($1);
// }
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
// 生成 Proxy 实现类
Class<?> pc = ccm.toClass();
// 通过反射创建 Proxy 实例
proxy = (Proxy) pc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (ccp != null)
// 释放资源
ccp.release();
if (ccm != null)
ccm.release();
synchronized (cache) {
if (proxy == null)
cache.remove(key);
else
// 写缓存
cache.put(key, new WeakReference<Proxy>(proxy));
// 唤醒其他等待线程
cache.notifyAll();
}
}
return proxy;
}
return 出去,就没有了!