At the beginning
The previous section looked at how Dubbo is integrated with Spring and how to load the @Service and @Reference annotations. This section begins with dubbo’s core source code, Service export, which means that the server exposes its interface and parses it into a remote Service that can be invoked by the consumer.
The main process
1. Entrance, ServiceBean onApplicationEvent, ServiceBean to monitor the spring start events, after the start will invoke this method used to obtain a service
2. Prepare configuration parameters, such as priority and overwrite. Configuration parameters can be configured on both the consumer and server
3. Start the communication server, such as Tomcat or Netty, based on the URL, parameter, and protocol information
4. Register the service information to the register-Register Protocol
5. Listen to the path registry. Subscribe
Source process
www.processon.com/view/link/6…
1. The total entry
As you saw in the previous section, when Spring integrates dubbo, the bean on the server side generates a ServiceBean that implements the ApplicationListener interface, The onApplicationEvent method is called after Spring has started
@Override public void onApplicationEvent(ContextRefreshedEvent event) { if (! isExported() && ! isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } // Service export is important (service registration) export(); }}Copy the code
2. Prepare parameters
In the export method, the first line is to check and modify the configuration parameters checkAndUpdateSubConfigs(); There are a lot of parameters, so I won’t click on it
public synchronized void export() { checkAndUpdateSubConfigs(); if (! shouldExport()) { return; } if (shouldDelay()) { DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS); } else {// Export service doExport(); }}Copy the code
3. Start the communication server, such as Tomcat or Netty, based on the URL, parameter, and protocol information
Url: doExport->doExportUrls->doExportUrlsFor1Protocol (key), url: doExportUrlsFor1Protocol (key) Call protocol. The export will first call protocol wrapper class ProtocolFilterWrapper. Export method, as a result of the protocol type is the register, So the registerProtocol.export method is called.
Exporter<? > exporter = protocol.export(wrapperInvoker); @Override public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { if (REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) { return protocol.export(invoker); } return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER)); }Copy the code
In the registerProtocol. export method, there is a line of code that starts the communication server, which in turn calls the protocol.export method. Since the dubbo protocol is used, the dubboProtocol.export method is called
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker, providerUrl);
Copy the code
The dubboprotocol.export method, as you can see, starts the Netty server
@Override public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { URL url = invoker.getUrl(); // omit non-core code.. // Enable NettyServer openServer(url); return exporter; }Copy the code
4. Register the service information in the registry
After starting Netty, go back to the registerProtocol. export method, which registers the interface to the configuration center
If (register) {// Register (registryUrl, registeredProviderUrl); }Copy the code
When testing the registry is a zk, finally will call ZookeeperRegistry. DoRegister method
public void register(URL registryUrl, URL registeredProviderUrl) { Registry registry = registryFactory.getRegistry(registryUrl); Registry. register(registeredProviderUrl); }Copy the code
ZookeeperRegistry doRegister, you can see here is to use zk client zk server create nodes, the service information registration to zk, finally in zk node is a folder will see above, here are our demoService service
@Override public void doRegister(URL url) { try { zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true)); } catch (Throwable e) { throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); }}Copy the code
5. Listen to the path registry. Subscribe
In the registerProtocol.export method, this listens for the ZK node, Call chain FailBackRegistry – > ZookeeperRegistry. DoSubscribe – > notify notifies all listeners OverrideListener, such as url have change, will be back for service export
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
Copy the code
The difficulties in
The overall call is based on the protocol.export method, so how does Dubbo know whether the protocol at this time is registry or Dubbo type? Due to the SPI mechanism adopted, a wrapper class of protocol will be generated to track the source code. Arg0. GetUrl = arg0. GetUrl = arg0. GetUrl = arg0. Registry: / / XXXXXXXXXXXXXXX, dubbo: / / XXXXXXXXXXXXXXXXXXXX
package org.apache.dubbo.rpc; import org.apache.dubbo.common.extension.ExtensionLoader; public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol { public void destroy() { throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!" ); } public int getDefaultPort() { throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!" ); } public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null"); org.apache.dubbo.common.URL url = arg0.getUrl(); String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extN ame); return extension.export(arg0); } public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException { if (arg1 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg1; String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extN ame); return extension.refer(arg0, arg1); }}Copy the code
conclusion
The core is protocol.export, and you need to understand the invocation of SPI mechanism. This completes the process of registering the normal interface to the configuration center and providing the Dubbo service.