继上一篇Dubbo2.7.6之服务暴露流程 之后,这里就详细讨论服务暴露的过程。由于官方建议注册中心为zookeeper。那么这里就以zookeeper为注册中心。来看一下暴露服务到zookeeper中的详细过程。
在ServiceConfig中,暴露服务的核心逻辑就是三行代码。如下:
//1 使用ProxyFactory来生产一个Invoker实例
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
//2 使用DelegateProviderMetaDataInvoker来包装Invoker,将Invoker委派给DelegateProviderMetaDataInvoker
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
//3 使用Protocol实例来暴露服务
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
那么下面就分三步来研究:
- 生成Invoker实例
实际调用的是StubProxyFactoryWrapper#getInvoker(T proxy, Class type, URL url)方法。
参数解释:
proxy 服务接口的实现类
type 服务接口,必须是接口
URL 服务注册的所有配置信息
具体实现:
public class StubProxyFactoryWrapper implements ProxyFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(StubProxyFactoryWrapper.class);
private final ProxyFactory proxyFactory;
private Protocol protocol;
public StubProxyFactoryWrapper(ProxyFactory proxyFactory) {
this.proxyFactory = proxyFactory;
}
public void setProtocol(Protocol protocol) {
this.protocol = protocol;
}
...
/**
*
* 调用被包装的ProxyFactory实例的getInvoker方法
* 也就是JavassistProxyFactory#getInvoker(T proxy, Class<T> type, URL url)
**/
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
return proxyFactory.getInvoker(proxy, type, url);
}
private <T> Exporter<T> export(T instance, Class<T> type, URL url) {
return protocol.export(proxyFactory.getInvoker(instance, type, url));
}
}
其实具体逻辑还是在JavassistProxyFactory中,那就继续看它的实现:
public class JavassistProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
//生成接口的Wrapper类,这里又会通过字节码技术,重新生产一个对应服务接口的wrapper类class实例
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
//构建一个AbstractProxyInvoker实例,这里又使用了模版设计模式。自实现模版方法doInvoke
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);
}
};
}
}
也就是说,第一步产生了一个AbstractProxyInvoker实例。
- 创建Invoker包装类 DelegateProviderMetaDataInvoker
DelegateProviderMetaDataInvoker是一个Invoker的包装类,它的作用就是将服务接口的Invoker实例和ServiceConfig实例包装在一起。
/**
*
* A Invoker wrapper that wrap the invoker and all the metadata (ServiceConfig)
*/
public class DelegateProviderMetaDataInvoker<T> implements Invoker {
protected final Invoker<T> invoker;
private ServiceConfig<?> metadata;
public DelegateProviderMetaDataInvoker(Invoker<T> invoker, ServiceConfig<?> metadata) {
this.invoker = invoker;
this.metadata = metadata;
}
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
/**
* Inocation就是对要调用方法的包装。里面包含的接口方法的名称,参数类型,参数等信息
*
* 这里就是对要调用具体方法的执行逻辑
**/
@Override
public Result invoke(Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
public ServiceConfig<?> getMetadata() {
return metadata;
}
}
- export服务
这是Protocol在暴露服务接口时,默认的实现结构图。
在使用PROTOCOL获取暴露接口时,实际上PROTOCOL是一个包装类。最底层包含了DubboProtocol。 使用QosProtocolWrapper,ProtocolFilterWrapper,ProtocolListenerWrapper这三个包装类一层一层的包装DubboProtocol 。这里就使用到了装饰者设计模式。在每一层都会添加额外的处理逻辑。结构如下:
下面先来看源码QosProtocolWrapper:
public class QosProtocolWrapper implements Protocol {
private final Logger logger = LoggerFactory.getLogger(QosProtocolWrapper.class);
private static AtomicBoolean hasStarted = new AtomicBoolean(false);
private Protocol protocol;
public QosProtocolWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
...
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
//如果是应用注册,则启动Qos服务
if (UrlUtils.isRegistry(invoker.getUrl())) {
startQosServer(invoker.getUrl());
return protocol.export(invoker);
}
//暴露接口就直接调用自己包装的Protocol实例的export方法
return protocol.export(invoker);
}
...
}
可以看到在暴露具体接口服务时,这个wrapper是直接调用ProtocolFilterWrapper#export(),相当于没有执行任何逻辑。下面继续看ProtocolFilterWrapper#export
public class ProtocolFilterWrapper implements Protocol {
private final Protocol protocol;
public ProtocolFilterWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
//如果是应用注册,就调下一层Protocol实例
if (UrlUtils.isRegistry(invoker.getUrl())) {
return protocol.export(invoker);
}
//如果暴露接口服务,就构建InvokerChain
return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
}
//获取所有的可激活的filter,然后一层一层包装Invoker实例,构成一个InvokerChian
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult;
try {
asyncResult = filter.invoke(next, invocation);
} catch (Exception e) {
if (filter instanceof ListenableFilter) {
ListenableFilter listenableFilter = ((ListenableFilter) filter);
try {
Filter.Listener listener = listenableFilter.listener(invocation);
if (listener != null) {
listener.onError(e, invoker, invocation);
}
} finally {
listenableFilter.removeListener(invocation);
}
} else if (filter instanceof Filter.Listener) {
Filter.Listener listener = (Filter.Listener) filter;
listener.onError(e, invoker, invocation);
}
throw e;
} finally {
}
return asyncResult.whenCompleteWithContext((r, t) -> {
if (filter instanceof ListenableFilter) {
ListenableFilter listenableFilter = ((ListenableFilter) filter);
Filter.Listener listener = listenableFilter.listener(invocation);
try {
if (listener != null) {
if (t == null) {
listener.onResponse(r, invoker, invocation);
} else {
listener.onError(t, invoker, invocation);
}
}
} finally {
listenableFilter.removeListener(invocation);
}
} else if (filter instanceof Filter.Listener) {
Filter.Listener listener = (Filter.Listener) filter;
if (t == null) {
listener.onResponse(r, invoker, invocation);
} else {
listener.onError(t, invoker, invocation);
}
}
});
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
ProtocolFilterWrapper将Filter封装进Invoker中之后,再调用被它包装的Protocol实例ProtocolListenerWrapper的export方法。
下面来看下这里面的实现逻辑:
public class ProtocolListenerWrapper implements Protocol {
private final Protocol protocol;
public ProtocolListenerWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
...
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
//如果应用注册,就跳过此Wrapper逻辑。
if (UrlUtils.isRegistry(invoker.getUrl())) {
return protocol.export(invoker);
}
//如果服务接口注册,则获取到所有的可激活的ExporterListener实例。使用ListenerExporterWrapper再此wrapper起来
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), EXPORTER_LISTENER_KEY)));
}
}
直接看ListenerExporterWrapper实现:
public class ListenerExporterWrapper<T> implements Exporter<T> {
private static final Logger logger = LoggerFactory.getLogger(ListenerExporterWrapper.class);
private final Exporter<T> exporter;
private final List<ExporterListener> listeners;
public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners) {
if (exporter == null) {
throw new IllegalArgumentException("exporter == null");
}
this.exporter = exporter;
this.listeners = listeners;
if (CollectionUtils.isNotEmpty(listeners)) {
RuntimeException exception = null;
for (ExporterListener listener : listeners) {
if (listener != null) {
try {
listener.exported(this);
} catch (RuntimeException t) {
logger.error(t.getMessage(), t);
exception = t;
}
}
}
if (exception != null) {
throw exception;
}
}
}
@Override
public Invoker<T> getInvoker() {
return exporter.getInvoker();
}
...
}
可以看到,在ListenerExporterWrapper的构造方法中,对ExporterListener进行了逐个调用。但是目前ExporterListener 的没有具体实现。也就是这段逻辑就是包装了一下exporter实例。