导出到远程入口
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
/**
* 前面的代码省略,从导出服务到远程的入口开始分析
*/
//导出服务的scope,即决定服务导出到local还是远程
String scope = url.getParameter(Constants.SCOPE_KEY);
// don't export when none is configured
// scope为none,则不导出
if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {
// export to local if the config is not remote (export to remote only when config is remote)
//为local则导出到local
if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
exportLocal(url);
}
// export to remote if the config is not local (export to local only when config is local)
//否则导出到远程
if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
//当注册url存在时
if (registryURLs != null && !registryURLs.isEmpty()) {
for (URL registryURL : registryURLs) {
url = url.addParameterIfAbsent(Constants.DYNAMIC_KEY, registryURL.getParameter(Constants.DYNAMIC_KEY));
URL monitorUrl = loadMonitor(registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
}
// For providers, this is used to enable custom proxy to generate invoker
String proxy = url.getParameter(Constants.PROXY_KEY);
if (StringUtils.isNotEmpty(proxy)) {
registryURL = registryURL.addParameter(Constants.PROXY_KEY, proxy);
}
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
} else {
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
}
}
this.urls.add(url);
}
导出服务
/**
* 导出服务到远程其中的一步:导出服务
* 在com.alibaba.dubbo.registry.integration.RegistryProtocol类中
* @param originInvoker
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
private <T> RegistryProtocol.ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {
//获取key
String key = getCacheKey(originInvoker);
/**
* 根据key值去bounds中去获取缓存
* bounds是一个ConcurrentHashMap<String, ExporterChangeableWrapper>
*/
ExporterChangeableWrapper<T> exporter = (RegistryProtocol.ExporterChangeableWrapper<T>) bounds.get(key);
//双重检查锁
if (exporter == null) {
synchronized (bounds) {
/**
* 如果从缓存bounds中获取不到则new一个InvokerDelegete对象,
* 并将其包装成ExporterChangeableWrapper对象并存储到缓存中,
* 最后返回从缓存中获取到的或者新创建的exporter
*/
exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
/**
* protocol指com.alibaba.dubbo.rpc.Protocol接口,
* 此处的实现类是根据采用的协议来选取的
* 如果协议为dubbo,则实现类为DubboProtocol
* 即通过dubbo协议进行服务的导出
*/
exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
bounds.put(key, exporter);
}
}
}
return exporter;
}
根据不同的协议导出服务,以dubbo举例
/**
* 当使用协议为dubbo时,使用此方法进行服务的导出
* 此方法是在com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol类中
* @param invoker
* @param <T>
* @return
* @throws RpcException
*/
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
/**
* invoker为调用者
* 从invoker中获取对应的url
*/
URL url = invoker.getUrl();
// export service.
/**
* 调用serviceKey方法拼接服务组名、服务名、服务版本、服务端口
* 在获取服务端口时,如果没有回取默认值
*/
String key = serviceKey(url);
/**
* 创建DubboExporter导出者
* exporterMap是一个缓存map,存放的数据为Exporter导出者
*/
DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
exporterMap.put(key, exporter);
//export an stub service for dispatching event
//本地存根相关代码
Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);
Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
if (isStubSupportEvent && !isCallbackservice) {
String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
if (logger.isWarnEnabled()) {
logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +
"], has set stubproxy support event ,but no stub methods founded."));
}
} else {
/**
* 如果存根服务方法存在,则存入缓存stubServiceMethodsMap中
* stubServiceMethodsMap是一个ConcurrentHashMap
* private final ConcurrentMap<String, String> stubServiceMethodsMap = new ConcurrentHashMap<String, String>();
*/
stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
}
}
//启动服务器
openServer(url);
//优化序列化
optimizeSerialization(url);
return exporter;
}
启动服务器
/**
* 开启服务器
* @param url
*/
private void openServer(URL url) {
// find server.
String key = url.getAddress();
//client can export a service which's only for server to invoke
/**
* 检查client是否能导出该服务
*/
boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
if (isServer) {
/**
* 首先从缓存serverMap中获取ExchangeServer
* serverMap是一个ConcurrentHashMap类型的容器
* private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>()
*/
ExchangeServer server = serverMap.get(key);
if (server == null) {
//如果server不存在,则调用createServer创建一个服务器实例并存入缓存
serverMap.put(key, createServer(url));
} else {
// server supports reset, use together with override
//如果server存在,需要进行重置
server.reset(url);
}
}
}
创建服务器实例
/**
* 创建服务器实例
* @param url
* @return
*/
private ExchangeServer createServer(URL url) {
// send readonly event when server closes, it's enabled by default
//添加服务器关闭时默认发送只读事件配置到url中
url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
// enable heartbeat by default
//添加心跳检测配置到url中
url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
/**
* 获取server参数,默认为netty
* 此处的String str变量在接下来会被多次赋值,
* 主要起一个临时变量的作用
*/
String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);
//通过SPI机制获取Transporter接口的实现类并检测其中是否包含str所代表的的实现类,如果没有则抛异常
if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))
throw new RpcException("Unsupported server type: " + str + ", url: " + url);
//添加编码解码器参数
url = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME);
/**
* 创建ExchangeServer实例
*/
ExchangeServer server;
try {
server = Exchangers.bind(url, requestHandler);
} catch (RemotingException e) {
throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
}
/**
* 获取client参数,然后通过SIP检测支持的类型中是否包含此类型,如果不包含则抛异常
*/
str = url.getParameter(Constants.CLIENT_KEY);
if (str != null && str.length() > 0) {
Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
if (!supportedTypes.contains(str)) {
throw new RpcException("Unsupported client type: " + str);
}
}
return server;
}
创建服务器实例续
/**
* 创建服务器实例
* @param url
* @param handler
* @return
* @throws RemotingException
*/
public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
if (url == null) {
throw new IllegalArgumentException("url == null");
}
if (handler == null) {
throw new IllegalArgumentException("handler == null");
}
url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
/**
* getExchanger()获取交换机,默认获取为header=com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchanger
*/
return getExchanger(url).bind(url, handler);
}