Remote call rmi protocol
Objective: to introduce the design and implementation of rmi protocol and the source code of Dubbo RPC rmi.
Preface
dubbo supports RMI protocol, which is mainly implemented based on the org.springframework.remoting.rmi package encapsulated by spring. Of course, the most primitive is the java.rmi. * package that relies on the JDK standard, which adopts blocking short connection and JDK standard serialization. For the introduction of RMI protocol, please refer to the official documents of dubbo.
Address: http://dubbo.apache.org/zh-cn...
Source code analysis
(I) RmiRemoteInvocation
This class inherits RemoteInvocation, mainly adding the additional values required by dubbo itself on the basis of RemoteInvocation to avoid these additional values not being passed, in order to do some validation processing.
public class RmiRemoteInvocation extends RemoteInvocation { private static final long serialVersionUID = 1L; private static final String dubboAttachmentsAttrName = "dubbo.attachments"; /** * executed on consumer side */ public RmiRemoteInvocation(MethodInvocation methodInvocation) { super(methodInvocation); // Add dubbo added value attribute addAttribute(dubboAttachmentsAttrName, new HashMap<String, String>(RpcContext.getContext().getAttachments())); } /** * Need to restore context on provider side (Though context will be overridden by Invocation's attachment * when ContextFilter gets executed, we will restore the attachment when Invocation is constructed, check more * The context needs to be recovered on the provider side (although the context will be overwritten by the attachment of the Invocation * When ContextFilter executes, we will restore the attachment when constructing the Invocation, and check more * from {@link com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler} */ @SuppressWarnings("unchecked") @Override public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { // Get context RpcContext context = RpcContext.getContext(); // Setting parameters context.setAttachments((Map<String, String>) getAttribute(dubboAttachmentsAttrName)); try { return super.invoke(targetObject); } finally { // Empty parameters context.setAttachments(null); } } }
(II) RmiProtocol
This class inherits the AbstractProxyProtocol class and is the core of rmi protocol implementation. Like other protocols, it also implements its own service exposure and service reference methods.
1.doExport
@Override protected <T> Runnable doExport(final T impl, Class<T> type, URL url) throws RpcException { // rmi exposures final RmiServiceExporter rmiServiceExporter = new RmiServiceExporter(); // Set port rmiServiceExporter.setRegistryPort(url.getPort()); // Set service name rmiServiceExporter.setServiceName(url.getPath()); // Setting up interfaces rmiServiceExporter.setServiceInterface(type); // Set up service implementation rmiServiceExporter.setService(impl); try { // Execute when initializing bean rmiServiceExporter.afterPropertiesSet(); } catch (RemoteException e) { throw new RpcException(e.getMessage(), e); } return new Runnable() { @Override public void run() { try { // Destruction rmiServiceExporter.destroy(); } catch (Throwable e) { logger.warn(e.getMessage(), e); } } }; }
This method is a logical implementation of service exposure.
2.doRefer
@Override @SuppressWarnings("unchecked") protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException { // FactoryBean for RMI proxy, supports traditional RMI service and RMI caller to create RmiProxyFactoryBean object final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean(); // RMI needs extra parameter since it uses customized remote invocation object // Testing version if (url.getParameter(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()).equals(Version.getProtocolVersion())) { // Check dubbo version on provider, this feature only support // Set RemoteInvocationFactory for this accessor rmiProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() { @Override public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { // Custom call factories can add more context information to calls return new RmiRemoteInvocation(methodInvocation); } }); } // Set the URL of the target service for this remote visitor. The URL must be compatible with the rules of a specific remoting provider. rmiProxyFactoryBean.setServiceUrl(url.toIdentityString()); // Set the interface of the service to be accessed. The interface must be suitable for specific services and remoting strategies rmiProxyFactoryBean.setServiceInterface(serviceType); // Set whether to cache the RMI stub after it is found rmiProxyFactoryBean.setCacheStub(true); // Set whether to find RMI stubs at startup rmiProxyFactoryBean.setLookupStubOnStartup(true); // Set whether to refresh the RMI stub when the connection fails rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true); // //Execute when initializing bean rmiProxyFactoryBean.afterPropertiesSet(); return (T) rmiProxyFactoryBean.getObject(); }
This method is a logical implementation of the service reference.
Epilogue
Related source resolution address of this part: https://github.com/CrazyHZM/i...
This article explains the part about rmi protocol implementation in remote call, and the logic is relatively simple. Next, I will start to explain the section about thrift protocol of rpc module.