之前文章讲到了ReferenceBean的依赖注入,但没有看ReferenceBean的实例化,现在接着看到ReferenceAnnotationBeanPostProcessor的doGetInjectedBean方法
@Override
protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
//构建ReferencedBeanNam
String referencedBeanName = buildReferencedBeanName(reference, injectedType);
//创建ReferenceBean
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
cacheInjectedReferenceBean(referenceBean, injectedElement);
//实际依赖注入的是proxy
Object proxy = buildProxy(referencedBeanName, referenceBean, injectedType);
return proxy;
}
private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference,
Class<?> referencedType, ClassLoader classLoader)
throws Exception {
//先从referenceBeanCache中拿
ReferenceBean<?> referenceBean = referenceBeanCache.get(referencedBeanName);
if (referenceBean == null) {
//拿不到 则是第一次实例化该ReferenceBean
//传入了reference注解 和 referencedType接口类型
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(reference, classLoader, applicationContext)
.interfaceClass(referencedType);
//实例化ReferenceBean(这里构建出来的bean将reference注解的各个属性值填充进来了)
referenceBean = beanBuilder.build();
referenceBeanCache.put(referencedBeanName, referenceBean);
}
return referenceBean;
}
private void cacheInjectedReferenceBean(ReferenceBean referenceBean,
InjectionMetadata.InjectedElement injectedElement) {
//建立需要依赖注入的element和referenceBean的映射关系
if (injectedElement.getMember() instanceof Field) {
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
} else if (injectedElement.getMember() instanceof Method) {
injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
}
}
private Object buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class<?> injectedType) {
//jdk动态代理 , InvocationHandler 对象持有了referencedBeanName 和 referenceBean
InvocationHandler handler = buildInvocationHandler(referencedBeanName, referenceBean);
Object proxy = Proxy.newProxyInstance(getClassLoader(), new Class[]{injectedType}, handler);
return proxy;
}
private InvocationHandler buildInvocationHandler(String referencedBeanName, ReferenceBean referenceBean) {
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
if (handler == null) {
handler = new ReferenceBeanInvocationHandler(referenceBean);
}
if (applicationContext.containsBean(referencedBeanName)) {
//本地reference引用
localReferenceBeanInvocationHandlerCache.put(referencedBeanName, handler);
} else {
//远程调用的referenceBean
//初始化referenceBean
handler.init();
}
return handler;
}
private static class ReferenceBeanInvocationHandler implements InvocationHandler {
private final ReferenceBean referenceBean;
private Object bean;
private ReferenceBeanInvocationHandler(ReferenceBean referenceBean) {
this.referenceBean = referenceBean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
if (bean == null) { // If the bean is not initialized, invoke init()
// issue: https://github.com/apache/incubator-dubbo/issues/3429
init();
}
//是bean对象调用方法,不是referenceBean对象
result = method.invoke(bean, args);
} catch (InvocationTargetException e) {
// re-throws the actual Exception.
throw e.getTargetException();
}
return result;
}
//bean 初始化
private void init() {
this.bean = referenceBean.get();
}
}
ReferenceConfig
public synchronized T get() {
//省略大段配置属性值(系统变量,配置文件,注解属性)填充到map中的逻辑,和ServiceBean的类似,可以参考前面ServiceBean的文章
//看到ref的生成
ref = createProxy(map);
ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods());
ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel);
}
private T createProxy(Map<String, String> map) {
//先生成一个临时的url对象,map中的属性填充到url中。
URL tmpUrl = new URL("temp", "localhost", 0, map);
final boolean isJvmRefer;
//判断是否为本机调用
if (isInjvm() == null) {
if (url != null && url.length() > 0) { // if a url is specified, don't do local reference
isJvmRefer = false;
}
//判断url的scope属性是否为local 或者 injvm属性值为true ,则为本机调用
else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
// by default, reference local service if there is
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属性
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())) {
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
} else {
//将map的属性填充到url中
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
} else {
//获取注册协议的url,消费者也需要进行注册.
//多个注册中心,则可以拿到多个。
List<URL> us = loadRegistries(false);
//设置Monitor属性
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 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) {
//调用Protocol$Adaptive的refer方法,此时的url协议属性是registry
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; // use last registry url
}
}
if (registryURL != null) { // registry url is available
// use AvailableCluster only when register's cluster is available
URL u = registryURL.addParameterIfAbsent(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // not a registry 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()) {
// make it possible for consumer to retry later if provider is temporarily unavailable
initialized = false;
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());
}
//对invoker生成代理对象返回,这里的proxyFactory为ProxyFactory$Adaptive,默认拿到的是JavassistProxyFactory,有一个包装类StubProxyFactoryWrapper
return (T) proxyFactory.getProxy(invoker);
}
Protocol的包装类之前的文章已经看过了,虽然是服务提供方的,不过逻辑一致,这里不再赘述了,直接看到RegistryProtocol。
@Override
@SuppressWarnings("unchecked")
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
//从url中获取registry属性(注册中心的类型属性,我自己测试用的zk),设置到url的protocol属性中,再移除掉url的registry属性
url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
//根据url获取注册中心对象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);
}
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//实现了NotifyListener接口,监听节点修改本地服务配置信息。
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
//设置注册中心对象ZookeeperRegistry
directory.setRegistry(registry);
//设置协议对象(Protocol$Adaptive)
directory.setProtocol(protocol);
//获取url的属性包装为map
Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
//生成消费者的url,将map的属性值填充到url中
//这里的协议头为consumer
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)) {
//设置url的category属性为consumers,,需要向zk的consumers节点写下该url的信息
URL registeredConsumerUrl = getRegisteredConsumerUrl(subscribeUrl, url);
//这里的注册方法在之前文章的服务注册流程看过了(ZookeeperRegistry),需要向zk对应的节点中写下该url的信息
registry.register(registeredConsumerUrl);
//directory
directory.setRegisteredConsumerUrl(registeredConsumerUrl);
}
//服务监听的代码前文也讲过了
//这里监听对应服务的 节点 (providers configurators routers) 变化,并更新到本地对应的属性中。
//初始会调用一次notify方法更新本地远程服务信息
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
//cluster从dubbo的spi注入进来的,不赘述了,这里的cluster为动态生成的,默认拿failover的cluster,但是有包装类MockClusterWrapper
//获得invoker对象。MockClusterInvoker---》FailoverClusterInvoker---》directory
Invoker invoker = cluster.join(directory);
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker;
}
StubProxyFactoryWrapper
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
T proxy = proxyFactory.getProxy(invoker);
//处理本地存根
if (GenericService.class != invoker.getInterface()) {
String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY));
if (ConfigUtils.isNotEmpty(stub)) {
Class<?> serviceType = invoker.getInterface();
//如果配置的"true"或者"default",则stub默认为原方法名+"Stub"
if (ConfigUtils.isDefault(stub)) {
if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) {
stub = serviceType.getName() + "Stub";
} else {
stub = serviceType.getName() + "Local";
}
}
try {
//反射获取到stub类
Class<?> stubClass = ReflectUtils.forName(stub);
if (!serviceType.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName());
}
try {
//stub类必须要有一个构造函数,参数为referenceBean的接口类型
Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType);
//实例化stub类,持有了proxy(referenceBean),返回的proxy 为stub实例
proxy = (T) constructor.newInstance(new Object[]{proxy});
URL url = invoker.getUrl();
if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)) {
url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString());
try {
export(proxy, (Class) invoker.getInterface(), url);
} catch (Exception e) {
LOGGER.error("export a stub service error.", e);
}
}
} catch (NoSuchMethodException e) {
throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), e);
}
} catch (Throwable t) {
LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t);
// ignore
}
}
}
return proxy;
}
JavassistProxyFactory
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
//这里实例化了一个InvokerInvocationHandler持有了invoker对象
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
InvokerInvocationHandler
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
}
@Override
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]);
}
//调用invoker的invoke方法,方法和参数封装为RpcInvocation
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}
MockClusterInvoker
@Override
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
//获取url中的mock属性
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
//没有mock属性,直接调用invoke
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);
}
//进行远程调用,出现RpcException ,再降级
else {
//fail-mock
try {
result = this.invoker.invoke(invocation);
} catch (RpcException e) {
if (e.isBiz()) {
throw e;
} else {
if (logger.isWarnEnabled()) {
logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
}
result = doMockInvoke(invocation, e);
}
}
}
return result;
}
private Result doMockInvoke(Invocation invocation, RpcException e) {
Result result = null;
Invoker<T> minvoker;
//从服务列表中获取可用的MockInvoker
List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
if (mockInvokers == null || mockInvokers.isEmpty()) {
//实例化一个MockInvoker
minvoker = (Invoker<T>) new MockInvoker(directory.getUrl());
} else {
//拿第一个
minvoker = mockInvokers.get(0);
}
try {
result = minvoker.invoke(invocation);
} catch (RpcException me) {
if (me.isBiz()) {
result = new RpcResult(me.getCause());
} else {
throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
}
} catch (Throwable me) {
throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
}
return result;
}
MockInvoker
@Override
public Result invoke(Invocation invocation) throws RpcException {
//获取url的方法级别的mock属性
String mock = getUrl().getParameter(invocation.getMethodName() + "." + Constants.MOCK_KEY);
if (invocation instanceof RpcInvocation) {
((RpcInvocation) invocation).setInvoker(this);
}
//获取url的mock属性
if (StringUtils.isBlank(mock)) {
mock = getUrl().getParameter(Constants.MOCK_KEY);
}
if (StringUtils.isBlank(mock)) {
throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url));
}
//对mock内容进行转换
/**
* <ol>
* <li>return => return null</li>
* <li>fail => default</li>
* <li>force => default</li>
* <li>fail:throw/return foo => throw/return foo</li>
* <li>force:throw/return foo => throw/return foo</li>
* </ol>
*/
mock = normalizeMock(URL.decode(mock));
//如果以return开头
if (mock.startsWith(Constants.RETURN_PREFIX)) {
//拿到return的值
mock = mock.substring(Constants.RETURN_PREFIX.length()).trim();
try {
//方法的返回类型
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
//将值转换为对应的返回类型
Object value = parseMockValue(mock, returnTypes);
//包装为RpcResult返回
return new RpcResult(value);
} catch (Exception ew) {
throw new RpcException("mock return invoke error. method :" + invocation.getMethodName()
+ ", mock:" + mock + ", url: " + url, ew);
}
}
//如果以throw开头
else if (mock.startsWith(Constants.THROW_PREFIX)) {
mock = mock.substring(Constants.THROW_PREFIX.length()).trim();
if (StringUtils.isBlank(mock)) {
throw new RpcException("mocked exception for service degradation.");
} else {
//反射获取到对应的Throwable类并实例化
Throwable t = getThrowable(mock);
throw new RpcException(RpcException.BIZ_EXCEPTION, t);
}
}
else {
try {
//反射实例化对应的mock类,再包装为Invoker对象
Invoker<T> invoker = getInvoker(mock);
//完成降级方法调用
return invoker.invoke(invocation);
} catch (Throwable t) {
throw new RpcException("Failed to create mock implementation class " + mock, t);
}
}
}
FailoverClusterInvoker的父类AbstractClusterInvoker
@Override
public Result invoke(final Invocation invocation) throws RpcException {
checkWhetherDestroyed();
LoadBalance loadbalance = null;
// binding attachments into invocation.
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
if (contextAttachments != null && contextAttachments.size() != 0) {
((RpcInvocation) invocation).addAttachments(contextAttachments);
}
//获取invokers(可以进行远程调用的服务列表信息)
List<Invoker<T>> invokers = list(invocation);
if (invokers != null && !invokers.isEmpty()) {
//拿到负载均衡策略的扩展类,不配置的话,默认为Constants.DEFAULT_LOADBALANCE (random)
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
.getMethodParameter(RpcUtils.getMethodName(invocation), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
//调用子类的doInvoke方法
return doInvoke(invocation, invokers, loadbalance);
}
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
//从RegistryDirectory中拿服务列表
List<Invoker<T>> invokers = directory.list(invocation);
return invokers;
}
protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
if (invokers == null || invokers.isEmpty())
return null;
String methodName = invocation == null ? "" : invocation.getMethodName();
//获取sticky参数值,不配置的话默认为false
boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName, Constants.CLUSTER_STICKY_KEY, Constants.DEFAULT_CLUSTER_STICKY);
{
//ignore overloaded method
if (stickyInvoker != null && !invokers.contains(stickyInvoker)) {
stickyInvoker = null;
}
//如果sticky 为true, 且stickyInvoker可用,直接返回stickyInvoker ,不再调用doSelect选择一个invoker去调用
if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) {
if (availablecheck && stickyInvoker.isAvailable()) {
return stickyInvoker;
}
}
}
//负载均衡策略选择一个invoker
Invoker<T> invoker = doSelect(loadbalance, invocation, invokers, selected);
//如果sticky为true
if (sticky) {
//则stickyInvoker被赋值为invoker
stickyInvoker = invoker;
}
return invoker;
}
private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
if (invokers == null || invokers.isEmpty())
return null;
//只有一个invoker,直接返回该invoker
if (invokers.size() == 1)
return invokers.get(0);
if (loadbalance == null) {
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
}
//负载均衡选择invoker (loadbalance的代码直接看官网https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/)
Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);
//If the `invoker` is in the `selected` or invoker is unavailable && availablecheck is true, reselect.
//selected 存在该 invoker,则说明是调用过的,也就是调用失败的。
if ((selected != null && selected.contains(invoker))
|| (!invoker.isAvailable() && getUrl() != null && availablecheck)) {
try {
//选择出来的invoker是不可用的,重新使用可用的invokers去负载均衡一个
Invoker<T> rinvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck);
if (rinvoker != null) {
invoker = rinvoker;
}
//reselect返回为空
else {
//Check the index of current selected invoker, if it's not the last one, choose the one at index+1.
int index = invokers.indexOf(invoker);
try {
//选择下一个,如果是最后一个,则选择第一个。
invoker = index < invokers.size() - 1 ? invokers.get(index + 1) : invokers.get(0);
} catch (Exception e) {
logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e);
}
}
} catch (Throwable t) {
logger.error("cluster reselect fail reason is :" + t.getMessage() + " if can not solve, you can set cluster.availablecheck=false in url", t);
}
}
return invoker;
}
获取服务列表
//AbstractDirectory
@Override
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
if (destroyed) {
throw new RpcException("Directory already destroyed .url: " + getUrl());
}
//调用子类的doList获取invokers
List<Invoker<T>> invokers = doList(invocation);
//获取路由进行invokers的过滤
List<Router> localRouters = this.routers; // local reference
if (localRouters != null && !localRouters.isEmpty()) {
for (Router router : localRouters) {
try {
//判断router 的 url的runtime是否为true,TagRouter的该参数默认为true
if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
invokers = router.route(invokers, getConsumerUrl(), invocation);
}
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
}
}
return invokers;
}
//RegistryDirectory
@Override
public List<Invoker<T>> doList(Invocation invocation) {
if (forbidden) {
// 1. No service provider 2. Service providers are disabled
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() + ", please check status of providers(disabled, not registered or in blacklist).");
}
List<Invoker<T>> invokers = null;
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]); // The routing can be enumerated according to the first parameter
}
//使用方法名称methodInvokerMap获取到invokers
if (invokers == null) {
invokers = localMethodInvokerMap.get(methodName);
}
//方法名称拿不到对应的invokers,则用"*"拿
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;
}
FailoverClusterInvoker
@Override
@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);
//获取被调用的方法名
String methodName = RpcUtils.getMethodName(invocation);
//获取总共的调用次数,默认 2次重试 + 1次基础调用
int len = getUrl().getMethodParameter(methodName, Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// retry loop.
RpcException le = null; // last exception.
//记录已经调用过的Invoker
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++) {
//大于0,调用失败了
if (i > 0) {
checkWhetherDestroyed();
//重新拿一次invokers,可能服务信息发生了变化并且更新到本地了。
copyinvokers = list(invocation);
checkInvokers(copyinvokers, invocation);
}
//负载均衡策略选择一个invoker , 调用到父类AbstractClusterInvoker的select方法
Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
//调用过的加入invoked
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
//调用invoker的invoke方法完成远程调用。这里最终是DubboInvoker,有包装类和拦截器链。
Result result = invoker.invoke(invocation);
if (le != null && logger.isWarnEnabled()) {
logger.warn("Although retry the method " + methodName
+ " 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 "
+ methodName + " 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);
}
RegistryDirectory
//消费者更新本地的远程服务的相关信息
@Override
public synchronized void notify(List<URL> urls) {
//监听了3个节点
List<URL> invokerUrls = new ArrayList<URL>();
List<URL> routerUrls = new ArrayList<URL>();
List<URL> configuratorUrls = new ArrayList<URL>();
for (URL url : urls) {
//从url中获取protocol 和 category属性 ,判断被更新的节点, 将更新的url放入到对应的list中
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.isEmpty()) {
this.configurators = toConfigurators(configuratorUrls);
}
// 更新本地routes属性
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);
}
}
//更新本地 服务提供方的信息
refreshInvoker(invokerUrls);
}
private void refreshInvoker(List<URL> invokerUrls) {
//如果是protocol属性为empty,将forbidden设置为true(消费方提供后,还没有提供方时)
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; // Set the method invoker map to null
destroyAllInvokers(); // Close all invokers
}
else {
//修改为false
this.forbidden = false; // Allow to access
Map<String, Invoker<T>> oldUrlInvokerMap = this.urlInvokerMap; // local reference
if (invokerUrls.isEmpty() && this.cachedInvokerUrls != null) {
//如果cachedInvokerUrls 已经有值了 , 将cachedInvokerUrls的值添加到 invokerUrls
invokerUrls.addAll(this.cachedInvokerUrls);
} else {
//向cachedInvokerUrls 中添加 invokerUrls (服务提供方url)
this.cachedInvokerUrls = new HashSet<URL>();
this.cachedInvokerUrls.addAll(invokerUrls);//Cached invoker urls, convenient for comparison
}
if (invokerUrls.isEmpty()) {
return;
}
//建立 服务调用url 和 Invoker的映射关系
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map
//建立 服务被调用的方法 和 Invoker的映射关系
Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // Change method name to map Invoker Map
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;
}
//将newMethodInvokerMap 赋值给 methodInvokerMap
this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
//将newUrlInvokerMap 赋值给 urlInvokerMap
this.urlInvokerMap = newUrlInvokerMap;
try {
//对比oldUrlInvokerMap和newUrlInvokerMap,从oldUrlInvokerMap中取出多余的invoker,调用invoker的destroy方法销毁(后面文章讲到服务下线的时候再来看到destroy)
destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker
} catch (Exception e) {
logger.warn("destroyUnusedInvokers error. ", e);
}
}
}
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>();
//queryMap为消费方的配置属性
//获取消费方配置的protocol属性(可以不配置,不会去匹配可用的服务方url),和服务方url的protocol进行匹配的。
String queryProtocols = this.queryMap.get(Constants.PROTOCOL_KEY);
for (URL providerUrl : urls) {
// If protocol is configured at the reference side, only the matching protocol is selected
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;
}
}
//跳过protoco为empty的服务方url
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;
}
//将queryMap的属性替换调用服务方url中相同的配置属性。显然消费方的配置优先级应该更高
//此时url的配置属性全面的url。
URL url = mergeUrl(providerUrl);
//url的map作为key
String key = url.toFullString(); // The parameter urls are sorted
if (keys.contains(key)) { // Repeated url
continue;
}
keys.add(key);
//先获取之前本地缓存的map urlInvokerMap
Map<String, Invoker<T>> localUrlInvokerMap = this.urlInvokerMap; // local reference
//获取url对应的invoker,如果url没有发生配置变更,则和之前的一致,使用之前的invoker
Invoker<T> invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.get(key);
if (invoker == null) { // Not in the cache, refer again
try {
boolean enabled = true;
//禁用的服务方不生成invoker
if (url.hasParameter(Constants.DISABLED_KEY)) {
enabled = !url.getParameter(Constants.DISABLED_KEY, false);
} else {
enabled = url.getParameter(Constants.ENABLED_KEY, true);
}
if (enabled) {
//这里最终调用到DubboProtocol的refer方法生成invoker
//url为dubbo协议
//之前服务注册的文章已经看过类似的逻辑(Protocol$Adaptive的export方法,这里是refer方法)
invoker = new InvokerDelegate<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) { // Put new invoker in cache
//建立 消费方生成的url 和 invoker 的映射关系
newUrlInvokerMap.put(key, invoker);
}
}
//之前本地已经生过invoker了。
else {
newUrlInvokerMap.put(key, invoker);
}
}
keys.clear();
return newUrlInvokerMap;
}
private Map<String, List<Invoker<T>>> toMethodInvokers(Map<String, Invoker<T>> invokersMap) {
Map<String, List<Invoker<T>>> newMethodInvokerMap = new HashMap<String, List<Invoker<T>>>();
List<Invoker<T>> invokersList = new ArrayList<Invoker<T>>();
if (invokersMap != null && invokersMap.size() > 0) {
//循环所有的invoker
for (Invoker<T> invoker : invokersMap.values()) {
//拿到url中的methods属性
String parameter = invoker.getUrl().getParameter(Constants.METHODS_KEY);
if (parameter != null && parameter.length() > 0) {
//接口下有多个方法, ","号分隔
String[] methods = Constants.COMMA_SPLIT_PATTERN.split(parameter);
if (methods != null && methods.length > 0) {
for (String method : methods) {
//method的值不为空,且不为*
if (method != null && method.length() > 0
&& !Constants.ANY_VALUE.equals(method)) {
//建立方法和Invoker的映射关系
List<Invoker<T>> methodInvokers = newMethodInvokerMap.get(method);
if (methodInvokers == null) {
methodInvokers = new ArrayList<Invoker<T>>();
newMethodInvokerMap.put(method, methodInvokers);
}
methodInvokers.add(invoker);
}
}
}
}
invokersList.add(invoker);
}
}
List<Invoker<T>> newInvokersList = route(invokersList, null);
//加入"*" 和 newInvokersList 的映射关系
newMethodInvokerMap.put(Constants.ANY_VALUE, newInvokersList);
//获取之前建立过的映射关系serviceMethods
if (serviceMethods != null && serviceMethods.length > 0) {
for (String method : serviceMethods) {
//如果本次有更新相同的方法,则更新对应的Invoker
List<Invoker<T>> methodInvokers = newMethodInvokerMap.get(method);
if (methodInvokers == null || methodInvokers.isEmpty()) {
methodInvokers = newInvokersList;
}
//route过滤出可以使用的invoker
newMethodInvokerMap.put(method, route(methodInvokers, method));
}
}
// sort and unmodifiable
for (String method : new HashSet<String>(newMethodInvokerMap.keySet())) {
List<Invoker<T>> methodInvokers = newMethodInvokerMap.get(method);
Collections.sort(methodInvokers, InvokerComparator.getComparator());
newMethodInvokerMap.put(method, Collections.unmodifiableList(methodInvokers));
}
return Collections.unmodifiableMap(newMethodInvokerMap);
}