Dubbo 服务暴露过程是通过 com.alibaba.dubbo.config.spring.ServiceBean 来实现的。Spring 容器 refresh() 完成后,会发送 ContextRefreshedEvent,ServiceBean 会接收到这个 event 然后调用 export()。
Dubbo 服务暴露过程:
1)获取 Invoker Invoker<?> invoker = proxyFactory.getInvoker(T proxy, Class type, com.alibaba.dubbo.common.URL url); 这个 Invoker 就是 Provider 接收到服务调用的 Request 之后,最终要调用的 invoker。
2)通过 Protocol 调用 export() Exporter<?> exporter = protocol.export(com.alibaba.dubbo.rpc.Invoker invoker); 默认会使用 DubboProtocol 做服务暴露,过程中会启动 Netty Server 监听端口。
// JavassistProxyFactory.classpublic <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
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 {
// 通过 wrapper 类去调用服务提供者的真实方法。(避免使用反射,提高效率)
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
服务注册
通过之前 Dubbo Protocol & Filter 的学习,我们知道这里的 protocol 是一个 Wrappered Protocol,所以 protocol.export() 方法会先调用 Protocol SPI 扩展中的 wrapper 类的 export() 。 其中,ProtocolFilterWrapper#export(Invoker invoker) 代码如下:
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// 如果 URL 的 protocol 是注册协议的话,就执行服务注册流程
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
// 服务暴露过程中,会添加 group="provider" 的 Filter
return protocol.export(