blob: edd9824de323ad14c7149020fd1296810bf4a536 [file] [log] [blame]
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – Dubbo Developer Guide</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/</link><description>Recent content in Dubbo Developer Guide on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://dubbo.apache.org/en/docs/v2.7/dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: Source Code Build</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/build/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/build/</guid><description>
&lt;h2 id="checkout">Checkout&lt;/h2>
&lt;p>checkout the lastest project source code with commands blow:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>git clone https://github.com/apache/dubbo.git dubbo
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="branches">Branches&lt;/h2>
&lt;p>We use &lt;code>master&lt;/code> as the major branch for new feature development, and use other branches for maintenance. Tags for all versions can be checked via &lt;a href="https://github.com/apache/dubbo/tags">https://github.com/apache/dubbo/tags&lt;/a>.&lt;/p>
&lt;h2 id="building">Building&lt;/h2>
&lt;p>Dubbo relies on &lt;a href="http://maven.apache.org">maven&lt;/a> as the building tool.&lt;/p>
&lt;p>Requirements:&lt;/p>
&lt;ul>
&lt;li>Java above 1.8 version&lt;/li>
&lt;li>Maven version 2.2.1 or above&lt;/li>
&lt;/ul>
&lt;p>The following &lt;code>MAVEN_OPTS&lt;/code>should be configured before building:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b58900">export&lt;/span> &lt;span style="color:#268bd2">MAVEN_OPTS&lt;/span>&lt;span style="color:#719e07">=&lt;/span>-Xmx1024m -XX:MaxPermSize&lt;span style="color:#719e07">=&lt;/span>512m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>build with below command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn clean install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>skip testing using below building command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn install -Dmaven.test.skip
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="building-jar-package-of-source-code">Building jar package of source code&lt;/h2>
&lt;p>build Dubbo source code jar package with below command.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn clean source:jar install -Dmaven.test.skip
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>and modify the dubbo dependency in your sample project to the SANPSHOT version of the local repository, and then use remote debugger to debug dubbo.&lt;/p>
&lt;h2 id="ide-support">IDE support&lt;/h2>
&lt;p>use below command to generate IDE.&lt;/p>
&lt;h3 id="intellij-idea">Intellij Idea&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn idea:idea
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="eclipse">Eclipse&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn eclipse:eclipse
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Importing into eclipse&lt;/p>
&lt;p>Firstly, a maven repository needs to be configured in eclipse. Define &lt;code>M2_REPO&lt;/code> and point it to the local maven repository by clicking &lt;code>Preferences -&amp;gt; Java -&amp;gt; Build Path -&amp;gt; Classpath&lt;/code>.&lt;/p>
&lt;p>Use the following maven command as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>mvn eclipse:configure-workspace -Declipse.workspace&lt;span style="color:#719e07">=&lt;/span>/path/to/the/workspace/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>view the source code through &lt;a href="https://github.com/apache/dubbo">https://github.com/apache/dubbo&lt;/a>&lt;/li>
&lt;li>path under UNIX is ${HOME}/.m2/repository, path under Windows is C:\Documents and Settings&amp;lt;user&amp;gt;.m2\repository&lt;/li>
&lt;/ol></description></item><item><title>Docs: Framework Design</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/design/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/design/</guid><description>
&lt;h2 id="overall-design">Overall design&lt;/h2>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-framework.jpg" alt="/dev-guide/images/dubbo-framework.jpg">&lt;/p>
&lt;p>Image description:&lt;/p>
&lt;ul>
&lt;li>Left area with light blue background shows service consumer interfaces, Right area with light green background shows service provider interfaces, center area shows both side interfaces.&lt;/li>
&lt;li>The image is divided into 10 layers from the bottom to the top, and the layers are one-way dependence. The black arrow on the right represents the dependency between layers, and each layer can be stripped from the upper layer to be reused, the Service and Config layers are API, and the other layers are SPI.&lt;/li>
&lt;li>Green boxes are extension interfaces, blue boxes are implementation classes, image only shows implementation class of associated layers.&lt;/li>
&lt;li>The blue dashed line is the initialization process, which is assembly chain when starting, red line for the method call process, which is calling chain when running, purple triangle arrow is inherited, can treat subclass as the same node of parent class, text of lines are the method invocation.&lt;/li>
&lt;/ul>
&lt;h2 id="layer-description">Layer description&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>config layer&lt;/strong>: external config interface, &lt;code>ServiceConfig&lt;/code> and &lt;code>ReferenceConfig&lt;/code> is the center of the layer, you can directly initialize config class, also can generate config class by spring.&lt;/li>
&lt;li>&lt;strong>proxy layer&lt;/strong>: transparent proxy of service interface, generate client Stub of service and server Skeletion of service, &lt;code>ServiceProxy&lt;/code> is the center, extension interface is &lt;code>ProxyFactory&lt;/code>.&lt;/li>
&lt;li>&lt;strong>registry layer&lt;/strong>: encapsulation of service registry and discovery, service URL is the center, extension interfaces are &lt;code>RegistryFactory&lt;/code>, &lt;code>Registry&lt;/code> and &lt;code>RegistryService&lt;/code>.&lt;/li>
&lt;li>&lt;strong>cluster layer&lt;/strong>: encapsulation of cluster of muliple providers and load balance, and bridging registration center, &lt;code>Invoker&lt;/code> is the center, extension interfaces are &lt;code>Cluster&lt;/code>, &lt;code>Directory&lt;/code>, &lt;code>Router&lt;/code>, &lt;code>LoadBalance&lt;/code>.&lt;/li>
&lt;li>&lt;strong>monitor layer&lt;/strong>: monitor of RPC call times and call execute time, &lt;code>Statistics&lt;/code> is the center, extension interface are &lt;code>MonitorFactory&lt;/code>, &lt;code>Monitor&lt;/code>, &lt;code>MonitorService&lt;/code>&lt;/li>
&lt;li>&lt;strong>protocol layer&lt;/strong>: encapsulation of RPC, &lt;code>Invocation&lt;/code> and &lt;code>Result&lt;/code> are the center, extension interfaces are &lt;code>Protocol&lt;/code>, &lt;code>Invoker&lt;/code>, &lt;code>Exporter&lt;/code>&lt;/li>
&lt;li>&lt;strong>exchange layer&lt;/strong>: encapsulation of request and response, synchronous transfer asynchronous, &lt;code>Request&lt;/code> and &lt;code>Response&lt;/code> are the center, extension interfaces are &lt;code>Exchanger&lt;/code>, &lt;code>ExchangeChannel&lt;/code>, &lt;code>ExchangeClient&lt;/code>, &lt;code>ExchangeServer&lt;/code>&lt;/li>
&lt;li>&lt;strong>transport layer&lt;/strong>: abstraction of mina and netty, &lt;code>Message&lt;/code> is the center, extension interfaces are &lt;code>Channel&lt;/code>, &lt;code>Transporter&lt;/code>, &lt;code>Client&lt;/code>, &lt;code>Server&lt;/code>, &lt;code>Codec&lt;/code>&lt;/li>
&lt;li>&lt;strong>serialize layer&lt;/strong>: reusable tools, extension interfaces are &lt;code>Serialization&lt;/code>, &lt;code>ObjectInput&lt;/code>, &lt;code>ObjectOutput&lt;/code>, &lt;code>ThreadPool&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="relationship-description">Relationship description&lt;/h2>
&lt;ul>
&lt;li>In RPC, Protocol is the core layer, it means that you can complete RPC calling by Protocol + Invoker + Exporter, then filter at the main process of Invoker.&lt;/li>
&lt;li>Consumer and Provider are abstraction concepts, just want you have a more intuitive understanding of which classes belong to the client and server side, the reason not use Client and Server is that Dubbo uses Provider, Consumer, Registry, Monitor divide logical topology node in many scenes, keep the concept of unity.&lt;/li>
&lt;li>Cluster is external concept, the purpose of Cluster is that make various Invoker disguise to one Invoker, so that we just pay attention to the Invoker in Protocol layer, adding Cluster or removing Cluster will not affect other layers, because we don&amp;rsquo;t need Cluster when only have one provider.&lt;/li>
&lt;li>The Proxy layer encapsulates the transparent proxy for all interfaces, and in other layers with Invoker as the center, turn Invoker into interface, or turn interface implementation into Invoker by Proxy only when exposuring to user. RPC still work even removing Proxy layer, but not so transparent, making remote service calling don&amp;rsquo;t look like local service calling.&lt;/li>
&lt;li>Remoting is the implemetation of Dubbo protocols, you can remove Remoting if choosing RMI. The Remoting is divided into Transport layer and Exchange layer, Transport layer is responsible for one-way message transmission, it&amp;rsquo;s abstraction of Mina, Netty, Grizzly, it also can extend UDP transmission. The Exchange layer encapsulates the Request-Response semantics over the transport layer.&lt;/li>
&lt;li>Actually Registry and Monitor are not at the same layer, they are independent nodes, draw them together by layer just for global view.&lt;/li>
&lt;/ul>
&lt;h2 id="modules-packaging">Modules packaging&lt;/h2>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-modules.jpg" alt="/dev-guide/images/dubbo-modules.jpg">&lt;/p>
&lt;p>Modules description:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>dubbo-common module&lt;/strong>: includes Util classes and common modules.&lt;/li>
&lt;li>&lt;strong>dubbo-remoting module&lt;/strong>: is Dubbo protocol implementation, no need to use this module if using RMI for RPC.&lt;/li>
&lt;li>&lt;strong>dubbo-rpc module&lt;/strong>: abstraction of various protocols, and dynamic proxy, only one to one call, not concerned with the management of cluster.&lt;/li>
&lt;li>&lt;strong>dubbo-cluster module&lt;/strong>: disguise many service providers as one provider, including load balancing, fault tolerance, routing, etc. the address list of clusters can be either static or send by registry.&lt;/li>
&lt;li>&lt;strong>dubbo-registry module&lt;/strong>: Based on the cluster of registry send address and the abstraction of various registry centers.&lt;/li>
&lt;li>&lt;strong>dubbo-monitor module&lt;/strong>: statistics of service call times, call time, call chain tracked services.&lt;/li>
&lt;li>&lt;strong>dubbo-config module&lt;/strong>: is Dubbo external API, users use Dubbo by Config, hide Dubbo details.&lt;/li>
&lt;li>&lt;strong>dubbo-container module&lt;/strong>: is a Standlone container, just use Main method to load Spring, because usually service no need Tomcat/JBoss features.&lt;/li>
&lt;/ul>
&lt;p>Package dividing according to the layer structure, and the difference with layer dividing:&lt;/p>
&lt;ul>
&lt;li>container is service container, for service running deployment, not showed in the image.&lt;/li>
&lt;li>protocol layer and proxy layer are placed in RPC module, they are the core of RPC module, you can use these 2 layers complete RPC call when only have 1 provider.&lt;/li>
&lt;li>transport layer and exchange layer are placed in remoting module, for RPC call base comminucation.&lt;/li>
&lt;li>serialize layer is placed in common module, for reuse.&lt;/li>
&lt;/ul>
&lt;h2 id="dependence-relationship">Dependence relationship&lt;/h2>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-relation.jpg" alt="/dev-guide/images/dubbo-relation.jpg">&lt;/p>
&lt;p>Image description:&lt;/p>
&lt;ul>
&lt;li>The boxes in image, Protocol, Cluster, Proxy, Service, Container, Registry, Monitor represent layer or module, the blues mean interactive with business, the greens mean only internal interactive with Dubbo.&lt;/li>
&lt;li>The backgroud boxes in image, Consumer, Provider, Registry, Monitor represent deployment logical topology node.&lt;/li>
&lt;li>The blue dashed line in the image is called for initialization, the red dashed line is called asynchronously for runtime, and the red line is called synchronously for runtime.&lt;/li>
&lt;li>The image only includes RPC layer, don&amp;rsquo;t includes Remoting layer, the whole Remoting hides in Protocol layer.&lt;/li>
&lt;/ul>
&lt;h2 id="call-chain">Call chain&lt;/h2>
&lt;p>Expand the red call chain of the overall design map:&lt;/p>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-extension.jpg" alt="/dev-guide/images/dubbo-extension.jpg">&lt;/p>
&lt;h2 id="expose-service-sequence">Expose service sequence&lt;/h2>
&lt;p>Expand the initialization chain of service provider exposes service which at the left of the overall design map, the sequence diagram shows below:&lt;/p>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-export.jpg" alt="/dev-guide/images/dubbo-export.jpg">&lt;/p>
&lt;h2 id="reference-service-sequence">Reference service sequence&lt;/h2>
&lt;p>Expand the initialization chain of service consumer references service which at the right of the overall design map, the sequence diagram shows below:&lt;/p>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-refer.jpg" alt="/dev-guide/images/dubbo-refer.jpg">&lt;/p>
&lt;h2 id="domain-model">Domain model&lt;/h2>
&lt;p>The core domain models of Dubbo:&lt;/p>
&lt;ul>
&lt;li>Protocol is service domain, it is the main function entrance of Invoker exposure and reference, it is responsible for the life cycle management of Invoker.&lt;/li>
&lt;li>Invoker is entity domain, it is the core model of Dubbo, all the other models are disturbed, or converted to it, it represents an executable, you can call it by calling invoke, it can be a local implementation, a remote implementation, or a cluster implementation.&lt;/li>
&lt;li>Invocation is session domain, it holds variables in the calling process, such as the method name, the parameters, and so on.&lt;/li>
&lt;/ul>
&lt;h2 id="base-design-principle">Base design principle&lt;/h2>
&lt;ul>
&lt;li>Use Microkernel + Plugin design pattern,Microkernel only responsible for assembly Plugin, the functions of Dubbo are implemented by extension points, it means that all functions of Dubbo can be replaced by self defined extension by user.&lt;/li>
&lt;li>Use URL to be the startdard format of config information, all extension points transfer config information by URL.&lt;/li>
&lt;/ul>
&lt;p>More design principles refer to: &lt;a href="../principals">Framework design principle&lt;/a>&lt;/p></description></item><item><title>Docs: SPI Loading</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/spi/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/spi/</guid><description>
&lt;h2 id="spi-config">SPI Config&lt;/h2>
&lt;h3 id="source">Source:&lt;/h3>
&lt;p>Dubbo SPI is inherited from standard JDK SPI(Service Provider Interface) and makes it more powerful.&lt;/p>
&lt;p>Dubbo fixed below issues of the standard JDK SPI:&lt;/p>
&lt;ul>
&lt;li>The standard JDK SPI will load and instantize all the implementations at once. It will be a waste of resources if one implementation is timecosted, but never be used.&lt;/li>
&lt;li>We can&amp;rsquo;t accquire the SPI name, if loading the SPI implementation is failed.For example: standard JDK ScriptEngine, get script type by invoking method getName(). RubyScriptEngine class will load failed if the depenency jar jruby.jar is missing, and the real error info will be lost. When user executes ruby scripts, the program throws exception that doesn&amp;rsquo;t support ruby, but it is not the real cause.&lt;/li>
&lt;li>Enhance the SPI functionality by supporting IoC and AOP, one SPI can be easily injected by another SPI simply using setter.&lt;/li>
&lt;/ul>
&lt;h3 id="appointment">Appointment:&lt;/h3>
&lt;p>In the jar file containing extension class &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>, places a config file &lt;code>META-INF/dubbo/full interface name&lt;/code>, file content pattern: &lt;code>SPI name=the fully qualified name for the extension class&lt;/code>, use new line seperator for multiple implementation.&lt;/p>
&lt;h3 id="example">Example:&lt;/h3>
&lt;p>To extend Dubbo Protocol, place a text file in the extension jar file: &lt;code>META-INF/dubbo/org.apache.dubbo.rpc.Protocol&lt;/code>, content:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-properties" data-lang="properties">&lt;span style="display:flex;">&lt;span>xxx&lt;span style="color:#719e07">=&lt;/span>&lt;span style="color:#2aa198">com.alibaba.xxx.XxxProtocol&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>content of the implementation &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">package&lt;/span> com.alibaba.xxx&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.rpc.Protocol&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">XxxProtocol&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> Protocol &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuration-in-config-module">Configuration in config module&lt;/h3>
&lt;p>In Dubbo config module, all SPI points have related attributes or labels, we can choose the specific SPI implementation by using its name. Like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-xml" data-lang="xml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">&amp;lt;dubbo:protocol&lt;/span> name=&lt;span style="color:#2aa198">&amp;#34;xxx&amp;#34;&lt;/span> &lt;span style="color:#268bd2">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="spi-features">SPI Features&lt;/h2>
&lt;h3 id="spi-auto-wrap">SPI Auto Wrap&lt;/h3>
&lt;p>Auto wrap the SPI&amp;rsquo;s Wrapper class. &lt;code>ExtensionLoader&lt;/code> loads the SPI implementation, if the SPI has a copy instructor, it will be regarded as the SPI&amp;rsquo;s Wrapper class.&lt;/p>
&lt;p>Wrapper class content:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">package&lt;/span> com.alibaba.xxx&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.rpc.Protocol&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">XxxProtocolWrapper&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> Protocol &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Protocol impl&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">XxxProtocolWrapper&lt;/span>&lt;span style="color:#719e07">(&lt;/span>Protocol protocol&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span> impl &lt;span style="color:#719e07">=&lt;/span> protocol&lt;span style="color:#719e07">;&lt;/span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">//after interface method is executed, the method in extension will be executed
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">refer&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">//... some operation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> impl&lt;span style="color:#719e07">.&lt;/span>refer&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ... some operation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Wrapper class also implements the same SPI interface, but Wrapper is not the real implementation. It is used for wrap the real implementation returned from the &lt;code>ExtensionLoader&lt;/code>. The real returned instance by &lt;code>ExtensionLoader&lt;/code> is the Wrapper class instance, Wrapper holder the real SPI implementation class.&lt;/p>
&lt;p>There can be many Wrapper for one spi, simply add one if you need.&lt;/p>
&lt;p>With Wrapper class, you will be able to move same logics into Wrapper for all SPIs. Newly added Wrapper class add external logics for all SPIs, looks like AOP, Wrapper acts as a proxy for SPI.&lt;/p>
&lt;h3 id="spi-auto-load">SPI Auto Load&lt;/h3>
&lt;p>when loading the SPI, Dubbo will auto load the depency SPI. When one SPI implementation contains attribute which is also an SPI of another type,&lt;code>ExtensionLoader&lt;/code> will automatically load the depency SPI. &lt;code>ExtensionLoader&lt;/code> knows all the members of the specific SPI by scanning the setter method of all implementation class.&lt;/p>
&lt;p>Demo: two SPI &lt;code>CarMaker&lt;/code>(car maker)、&lt;code>WheelMaker&lt;/code> (wheel maker)&lt;/p>
&lt;p>Intefaces look like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">CarMaker&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Car &lt;span style="color:#268bd2">makeCar&lt;/span>&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">WheelMaker&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Wheel &lt;span style="color:#268bd2">makeWheel&lt;/span>&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>CarMaker&lt;/code>&amp;rsquo;s implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">RaceCarMaker&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> CarMaker &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> WheelMaker wheelMaker&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">setWheelMaker&lt;/span>&lt;span style="color:#719e07">(&lt;/span>WheelMaker wheelMaker&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">this&lt;/span>&lt;span style="color:#719e07">.&lt;/span>wheelMaker &lt;span style="color:#719e07">=&lt;/span> wheelMaker&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> Car &lt;span style="color:#268bd2">makeCar&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> Wheel wheel &lt;span style="color:#719e07">=&lt;/span> wheelMaker&lt;span style="color:#719e07">.&lt;/span>makeWheel&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#719e07">new&lt;/span> RaceCar&lt;span style="color:#719e07">(&lt;/span>wheel&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#719e07">...);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>when &lt;code>ExtensionLoader&lt;/code> loads &lt;code>CarMaker&lt;/code>&amp;rsquo;s implementation &lt;code>RaceCarMaker&lt;/code>, the method &lt;code>setWheelMaker&lt;/code> needs paramType &lt;code>WheelMaker&lt;/code> which is also a SPI, It will be automatically loaded.&lt;/p>
&lt;p>This brings a new question:How &lt;code>ExtensionLoader&lt;/code> determines which implementation to use when load the injected SPI. As for this demo, when existing multi &lt;code>WheelMaker&lt;/code> implementation, which one should the &lt;code>ExtensionLoader&lt;/code> chooses.&lt;/p>
&lt;p>Good question, we will explain it in the following chapter: SPI Auto Adaptive.&lt;/p>
&lt;h3 id="spi-auto-adaptive">SPI Auto Adaptive&lt;/h3>
&lt;p>The depency SPI that &lt;code>ExtensionLoader&lt;/code> injects is an instance of &lt;code>Adaptive&lt;/code>, the real spi implementation is known until the adaptive instance is executed.&lt;/p>
&lt;p>Dubbo use URL (containing Key-Value) to pass the configuration.&lt;/p>
&lt;p>The SPI method invocation has the URL parameter(Or Entity that has URL attribute)&lt;/p>
&lt;p>In this way depended SPI can get configuration from URL, after config all SPI key needed, configuration information will be passed from outer by URL. URL acts as a bus when passing the config information.&lt;/p>
&lt;p>Demo: two SPI &lt;code>CarMaker&lt;/code>、&lt;code>WheelMaker&lt;/code>&lt;/p>
&lt;p>interface looks like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">CarMaker&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Car &lt;span style="color:#268bd2">makeCar&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">WheelMaker&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Wheel &lt;span style="color:#268bd2">makeWheel&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>CarMaker&lt;/code>&amp;rsquo;s implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">RaceCarMaker&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> CarMaker &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> WheelMaker wheelMaker&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">setWheelMaker&lt;/span>&lt;span style="color:#719e07">(&lt;/span>WheelMaker wheelMaker&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">this&lt;/span>&lt;span style="color:#719e07">.&lt;/span>wheelMaker &lt;span style="color:#719e07">=&lt;/span> wheelMaker&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> Car &lt;span style="color:#268bd2">makeCar&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> Wheel wheel &lt;span style="color:#719e07">=&lt;/span> wheelMaker&lt;span style="color:#719e07">.&lt;/span>makeWheel&lt;span style="color:#719e07">(&lt;/span>url&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#719e07">new&lt;/span> RaceCar&lt;span style="color:#719e07">(&lt;/span>wheel&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#719e07">...);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>when execute the code above&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>Wheel wheel &lt;span style="color:#719e07">=&lt;/span> wheelMaker&lt;span style="color:#719e07">.&lt;/span>makeWheel&lt;span style="color:#719e07">(&lt;/span>url&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>, the injected &lt;code>Adaptive&lt;/code> object determine which &lt;code>WheelMaker&lt;/code>&amp;rsquo;s &lt;code>makeWheel&lt;/code> method will be executed by predefined Key. Such as &lt;code>wheel.type&lt;/code>, key &lt;code>url.get(&amp;quot;wheel.type&amp;quot;)&lt;/code> will determine &lt;code>WheelMake&lt;/code> implementation. The logic of&lt;code>Adaptive&lt;/code> instance of fixed, getting the predefined Key of the URL, dynamically creating the real implementation and execute it.&lt;/p>
&lt;p>For Dubbo, the SPI &lt;code>Adaptive&lt;/code> implementation in &lt;code>ExtensionLoader&lt;/code> is dynamically created when dubbo is loading the SPI. Get the Key from URL, the Key will be provided through &lt;code>@Adaptive&lt;/code> annotation for the interface method definition.&lt;/p>
&lt;p>Below is Dubbo Transporter SPI codes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">Transporter&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">@Adaptive&lt;/span>&lt;span style="color:#719e07">({&lt;/span>&lt;span style="color:#2aa198">&amp;#34;server&amp;#34;&lt;/span>&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">&amp;#34;transport&amp;#34;&lt;/span>&lt;span style="color:#719e07">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Server &lt;span style="color:#268bd2">bind&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">,&lt;/span> ChannelHandler handler&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#268bd2">throws&lt;/span> RemotingException&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">@Adaptive&lt;/span>&lt;span style="color:#719e07">({&lt;/span>&lt;span style="color:#2aa198">&amp;#34;client&amp;#34;&lt;/span>&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">&amp;#34;transport&amp;#34;&lt;/span>&lt;span style="color:#719e07">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Client &lt;span style="color:#268bd2">connect&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">,&lt;/span> ChannelHandler handler&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#268bd2">throws&lt;/span> RemotingException&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>for the method bind(), Adaptive will firstly search &lt;code>server&lt;/code> key, if no Key were founded then will search &lt;code>transport&lt;/code> key, to determine the implementation that the proxy represent for.&lt;/p>
&lt;h3 id="spi-auto-activation">SPI Auto Activation&lt;/h3>
&lt;p>As for Collections SPI, such as: &lt;code>Filter&lt;/code>, &lt;code>InvokerListener&lt;/code>, &lt;code>ExportListener&lt;/code>, &lt;code>TelnetHandler&lt;/code>, &lt;code>StatusChecker&lt;/code> etc, multi implementations can be loaded at one time. User can simplify configuration by using auto activation, Like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.common.extension.Activate&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.rpc.Filter&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Activate&lt;/span> &lt;span style="color:#586e75">// Active for any condition
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">XxxFilter&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> Filter &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Or:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.common.extension.Activate&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.rpc.Filter&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Activate&lt;/span>&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;xxx&amp;#34;&lt;/span>&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#586e75">// when configed xxx parameter and the parameter has a valid value,the SPI is activated, for example configed cache=&amp;#34;lru&amp;#34;, auto acitivate CacheFilter.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">XxxFilter&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> Filter &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Or:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.common.extension.Activate&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">import&lt;/span> org.apache.dubbo.rpc.Filter&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Activate&lt;/span>&lt;span style="color:#719e07">(&lt;/span>group &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#2aa198">&amp;#34;provider&amp;#34;&lt;/span>&lt;span style="color:#719e07">,&lt;/span> value &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#2aa198">&amp;#34;xxx&amp;#34;&lt;/span>&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#586e75">// only activate for provider, group can be &amp;#34;provider&amp;#34; or &amp;#34;consumer&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">XxxFilter&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> Filter &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Note: The config file here is in you own jar file, not in dubbo release jar file, Dubbo will scan all jar files with the same filename in classpath and then merge them together&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>Note: SPI will be loaded in singleton pattern(Please ensure thread safety), cached in &lt;code>ExtensionLoader&lt;/code>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Docs: Implementation details</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/implementation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/implementation/</guid><description>
&lt;h2 id="initialization-details">Initialization details&lt;/h2>
&lt;h3 id="service-parsing">Service parsing&lt;/h3>
&lt;p>Based on &lt;code>META-INF/spring.handlers&lt;/code> config in dubbo.jar, Spring calls &lt;code>DubboNamespaceHandler&lt;/code> when meeting dubbo namespace.&lt;/p>
&lt;p>All Dubbo tags are parsed by &lt;code>DubboBeanDefinitionParser&lt;/code>, based on one to one attribute mapping, the XML label is parsed as a Bean object.&lt;/p>
&lt;p>Transfer Bean object to URL, and transfer all attributes of Bean to URL parameters when &lt;code>ServiceConfig.export()&lt;/code> or &lt;code>ReferenceConfig.get()&lt;/code> initialization.&lt;/p>
&lt;p>Then pase URL to &lt;a href="../impls/protocol">Protocol extension point&lt;/a>, based on &lt;a href="../spi/">Extension point adaptive mechanism&lt;/a> of extension point, processing service exposure or reference for different protocols according to URL protocol header.&lt;/p>
&lt;h3 id="service-exposure">Service Exposure&lt;/h3>
&lt;h4 id="1-only-expose-service-port">1. Only expose service port:&lt;/h4>
&lt;p>Direct exposing to provider when have not Registry, &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>, the URL format which parsing by &lt;code>ServiceConfig&lt;/code>:
&lt;code>dubbo://service-host/com.foo.FooService?version=1.0.0&lt;/code>.&lt;/p>
&lt;p>Based on extension point adaptive mechanism, call &lt;code>export()&lt;/code> method of &lt;code>DubboProtocol&lt;/code> and open server port by identifying &lt;code>dubbo://&lt;/code> protocol header of URL.&lt;/p>
&lt;h4 id="2-expose-to-registry">2. Expose to Registry:&lt;/h4>
&lt;p>Expose provider address to Registry &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>, the URL format which parsing by &lt;code>ServiceConfig&lt;/code>: &lt;code>registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode(&amp;quot;dubbo://service-host/com.foo.FooService?version=1.0.0&amp;quot;)&lt;/code>,&lt;/p>
&lt;p>Based on extension point adaptive mechanism, call &lt;code>export()&lt;/code> method of &lt;code>RegistryProtocol&lt;/code> by identifying &lt;code>registry://&lt;/code> protocol header, register the provider URL parameter of &lt;code>export&lt;/code> to Registry.&lt;/p>
&lt;p>Resend to &lt;code>Protocol&lt;/code> extension point to do exposure: &lt;code>dubbo://service-host/com.foo.FooService?version=1.0.0&lt;/code>, then based on extension point adaptive mechanism, call &lt;code>export()&lt;/code> method of &lt;code>DubboProtocol&lt;/code> and open server port by identifying &lt;code>dubbo://&lt;/code> protocol header of provider URL.&lt;/p>
&lt;h3 id="service-reference">Service Reference&lt;/h3>
&lt;h4 id="1-direct-connect-service">1. Direct connect service&lt;/h4>
&lt;p>Direct connect provider when have not Registry &lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>, the URL format which parsing by &lt;code>ReferenceConfig&lt;/code>: &lt;code>dubbo://service-host/com.foo.FooService?version=1.0.0&lt;/code>.&lt;/p>
&lt;p>Based on extension point adaptive mechanism, call &lt;code>refer()&lt;/code> method of &lt;code>DubboProtocol&lt;/code> by identifying &lt;code>dubbo://&lt;/code> protocol header of URL, and return provider reference.&lt;/p>
&lt;h4 id="2-service-registry-discovery">2. Service Registry discovery&lt;/h4>
&lt;p>Discover provider address by Registry &lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>, the URL format which parsing by &lt;code>ReferenceConfig&lt;/code>:
&lt;code>registry://registry-host/org.apache.dubbo.registry.RegistryService?refer=URL.encode(&amp;quot;consumer://consumer-host/com.foo.FooService?version=1.0.0&amp;quot;)&lt;/code>.&lt;/p>
&lt;p>Based on extension point adaptive mechanism, call &lt;code>refer()&lt;/code> method of &lt;code>RegistryProtocol&lt;/code> by identifying &lt;code>registry://&lt;/code> protocol header of URL, then based on the condition of parameter of &lt;code>refer&lt;/code> to search provider URL, for example: &lt;code>dubbo://service-host/com.foo.FooService?version=1.0.0&lt;/code>.&lt;/p>
&lt;p>Then based on extension point adaptive mechanism, call &lt;code>refer()&lt;/code> method of &lt;code>DubboProtocol&lt;/code> to get provider reference by identifying &lt;code>dubbo://&lt;/code> protocol header of provider URL.&lt;/p>
&lt;p>Then &lt;code>RegistryProtocol&lt;/code> disguise various provider references to single provider by &lt;code>Cluster&lt;/code> extension point and return.&lt;/p>
&lt;h3 id="service-filter">Service Filter&lt;/h3>
&lt;p>Based on extension point adaptive mechanism, all &lt;code>Protocol&lt;/code> extension points are auto wrapped &lt;code>Wrapper&lt;/code> class.&lt;/p>
&lt;p>Based on &lt;code>ProtocolFilterWrapper&lt;/code> class, make all &lt;code>Filter&lt;/code> as chain, call the real reference at the end of the chain.&lt;/p>
&lt;p>Based on &lt;code>ProtocolListenerWrapper&lt;/code> class, make all &lt;code>InvokerListener&lt;/code> and &lt;code>ExporterListener&lt;/code> as list, perform call back before and after exposure and reference.&lt;/p>
&lt;p>All additional functions would be implementated by &lt;code>Filter&lt;/code>, including Monitor.&lt;/p>
&lt;h2 id="rpc-details">RPC details&lt;/h2>
&lt;h3 id="the-detail-process-of-exposing-service-by-service-provider">The detail process of exposing service by service provider&lt;/h3>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo_rpc_export.jpg" alt="/dev-guide/images/dubbo_rpc_export.jpg">&lt;/p>
&lt;p>The above image shows the main process of exposing service by service provider:&lt;/p>
&lt;p>First &lt;code>ServiceConfig&lt;/code> class get the actual class &lt;code>ref&lt;/code> that provides service(e.g. 如:HelloWorldImpl), then generating a &lt;code>AbstractProxyInvoker&lt;/code> instance by the &lt;code>getInvoker&lt;/code> method of &lt;code>ProxyFactory&lt;/code> class, to this step, complete the transformation of specific service to &lt;code>Invoker&lt;/code>, next is the process of converting &lt;code>Invoker&lt;/code> to &lt;code>Exporter&lt;/code>.&lt;/p>
&lt;p>The key of Dubbo processing service exposure is the process of converting &lt;code>Invoker&lt;/code> to &lt;code>Exporter&lt;/code>, the red part in the above image. Here we introduce the implementation of the two typical protocols, Dubbo and RMI:&lt;/p>
&lt;h4 id="dubbo-implementation">Dubbo implementation&lt;/h4>
&lt;p>The transformation from &lt;code>Invoker&lt;/code> of Dubbo protocol to &lt;code>Exporter&lt;/code> takes place in the &lt;code>export&lt;/code> method of &lt;code>DubboProtocol&lt;/code> class, it mainly opens the socket to listen service and receive all kinds of requests sent by the client, and the communication details are implementated by Dubbo itself.&lt;/p>
&lt;h4 id="rmi-implementation">RMI implementation&lt;/h4>
&lt;p>The transformation from &lt;code>Invoker&lt;/code> of RMI protocol to &lt;code>Exporter&lt;/code> takes place in the &lt;code>export&lt;/code> method of &lt;code>RmiProtocol&lt;/code> class, the RMI service is implementated by Spring, Dubbo or JDK, and the communication details are implementated by JDK, which saves a lot of work.&lt;/p>
&lt;h3 id="the-detail-process-of-serving-service-for-service-consumer">The detail process of serving service for service consumer&lt;/h3>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo_rpc_refer.jpg" alt="/dev-guide/images/dubbo_rpc_refer.jpg">&lt;/p>
&lt;p>The above image is the main process of service consumption:&lt;/p>
&lt;p>First, the &lt;code>init&lt;/code> method of &lt;code>ReferenceConfig&lt;/code> class calls the &lt;code>refer&lt;/code> method of &lt;code>Protocol&lt;/code> to generate &lt;code>Invoker&lt;/code> instance(such as the red part in the above image), which is the key of service consumption. Then the &lt;code>Invoker&lt;/code> is converted to the interface required by the client (such as: HelloWorld).&lt;/p>
&lt;p>For each protocol such as RMI/Dubbo/Web service, the details they call &lt;code>refer&lt;/code> method generate &lt;code>Invoker&lt;/code> instance are similar to the previous section.&lt;/p>
&lt;h3 id="invoker-everywhere">Invoker everywhere&lt;/h3>
&lt;p>Because of &lt;code>Invoker&lt;/code> is a very important concept in the Dubbo domain model, many of the design ideas are close to it. This makes &lt;code>Invoker&lt;/code> permeate the entire implementation code, and it&amp;rsquo;s really easy to mix up for people who have just started Dubbo.&lt;/p>
&lt;p>Let&amp;rsquo;s use a simple image below to describe the 2 important &lt;code>Invoker&lt;/code>: service provider &lt;code>Invoker&lt;/code> and service consumer &lt;code>Invoker&lt;/code>:&lt;/p>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo_rpc_invoke.jpg" alt="/dev-guide/images/dubbo_rpc_invoke.jpg">&lt;/p>
&lt;p>To better explain the above image, we provide the below code examples of service consumption and providers:&lt;/p>
&lt;p>Service consumer code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">DemoClientAction&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">private&lt;/span> DemoService demoService&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">setDemoService&lt;/span>&lt;span style="color:#719e07">(&lt;/span>DemoService demoService&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">this&lt;/span>&lt;span style="color:#719e07">.&lt;/span>demoService &lt;span style="color:#719e07">=&lt;/span> demoService&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">start&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> String hello &lt;span style="color:#719e07">=&lt;/span> demoService&lt;span style="color:#719e07">.&lt;/span>sayHello&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;world&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>DemoService&lt;/code> in above code is the proxy of service consumer in above image, user can call &lt;code>Invoker&lt;/code> &lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup> which implementate the real RPC by the proxy.&lt;/p>
&lt;p>Service provider code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">DemoServiceImpl&lt;/span> &lt;span style="color:#268bd2">implements&lt;/span> DemoService &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> String &lt;span style="color:#268bd2">sayHello&lt;/span>&lt;span style="color:#719e07">(&lt;/span>String name&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#268bd2">throws&lt;/span> RemoteException &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#2aa198">&amp;#34;Hello &amp;#34;&lt;/span> &lt;span style="color:#719e07">+&lt;/span> name&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above class would be encapsulated to be a &lt;code>AbstractProxyInvoker&lt;/code> instance, and create a new &lt;code>Exporter&lt;/code> instance, then find corresponding &lt;code>Exporter&lt;/code> instance and call its corresponding &lt;code>AbstractProxyInvoker&lt;/code> instance when network communication layer recieve request, so that real call service provider code. There are some other &lt;code>Invoker&lt;/code> classes, but the above 2 are the most important.&lt;/p>
&lt;h2 id="remote-communication-details">Remote communication details&lt;/h2>
&lt;h3 id="protocol-header-agreement">Protocol header agreement&lt;/h3>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo_protocol_header.png" alt="/dev-guide/images/dubbo_protocol_header.jpg">&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Magic - Magic High &amp;amp; Magic Low (16 bits)&lt;/p>
&lt;p>Identify protocol version, Dubbo protocol: 0xdabb&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Req/Res (1 bit)&lt;/p>
&lt;p>Identify a request or response. request: 1; response: 0.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>2 Way (1 bit)&lt;/p>
&lt;p>Only useful when Req/Res is 1(request), identifying if you expect to return a value from the server. Set to 1 if a return value from the server is required.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Event (1 bit)&lt;/p>
&lt;p>Identifies whether it is an event message, for example, a heartbeat event. Set to 1 if this is an event.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Serialization ID (5 bit)&lt;/p>
&lt;p>Identifies the serialization type: for example, the value of fastjson is 6.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Status (8 bits)&lt;/p>
&lt;p>Only useful when Req/Res is 0 (response), used to identify the status of the response&lt;/p>
&lt;ul>
&lt;li>20 - OK&lt;/li>
&lt;li>30 - CLIENT_TIMEOUT&lt;/li>
&lt;li>31 - SERVER_TIMEOUT&lt;/li>
&lt;li>40 - BAD_REQUEST&lt;/li>
&lt;li>50 - BAD_RESPONSE&lt;/li>
&lt;li>60 - SERVICE_NOT_FOUND&lt;/li>
&lt;li>70 - SERVICE_ERROR&lt;/li>
&lt;li>80 - SERVER_ERROR&lt;/li>
&lt;li>90 - CLIENT_ERROR&lt;/li>
&lt;li>100 - SERVER_THREADPOOL_EXHAUSTED_ERROR&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Request ID (64 bits)&lt;/p>
&lt;p>Identifies the only request, the type is long.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Data Length (32 bits)&lt;/p>
&lt;p>The length of the serialized content (variable part), counted in bytes, the type is int.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Variable Part&lt;/p>
&lt;p>After being serialized by a specific serialization type (identified by the serialization ID), each part is a byte [] or byte.&lt;/p>
&lt;ul>
&lt;li>If it is a request packet (Req/Res = 1), each part is:
&lt;ul>
&lt;li>Dubbo version&lt;/li>
&lt;li>Service name&lt;/li>
&lt;li>Service version&lt;/li>
&lt;li>Method name&lt;/li>
&lt;li>Method parameter types&lt;/li>
&lt;li>Method arguments&lt;/li>
&lt;li>Attachments&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>If it is a response packet (Req/Res = 0), each part is:
&lt;ul>
&lt;li>Return value&amp;rsquo;s type (byte), identifying the type of value returned from the server:
&lt;ul>
&lt;li>Return null: RESPONSE_NULL_VALUE 2&lt;/li>
&lt;li>Normal response value: RESPONSE_VALUE 1&lt;/li>
&lt;li>Exception: RESPONSE_WITH_EXCEPTION 0&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Return value: response bytes returned from the server&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Note:&lt;/strong> For the variable part, when uses json serialization in current version of Dubbo framework, an additional line break is added as a separator between each part of the content. Please add a new line break after each part of the variable part, such as:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Dubbo version bytes (line break)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Service name bytes (line break)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="thread-dispatch-model">Thread dispatch model&lt;/h3>
&lt;p>&lt;img src="https://dubbo.apache.org/imgs/dev/dubbo-protocol.jpg" alt="/dev-guide/images/dubbo-protocol.jpg">&lt;/p>
&lt;ul>
&lt;li>Dispather: &lt;code>all&lt;/code>, &lt;code>direct&lt;/code>, &lt;code>message&lt;/code>, &lt;code>execution&lt;/code>, &lt;code>connection&lt;/code>&lt;/li>
&lt;li>ThreadPool: &lt;code>fixed&lt;/code>, &lt;code>cached&lt;/code>&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>is &lt;code>&amp;lt;dubbo:service regisrty=&amp;quot;N/A&amp;quot; /&amp;gt;&lt;/code> or &lt;code>&amp;lt;dubbo:registry address=&amp;quot;N/A&amp;quot; /&amp;gt;&lt;/code>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>is &lt;code>&amp;lt;dubbo:registry address=&amp;quot;zookeeper://10.20.153.10:2181&amp;quot; /&amp;gt;&lt;/code>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>is &lt;code>&amp;lt;dubbo:reference url=&amp;quot;dubbo://service-host/com.foo.FooService?version=1.0.0&amp;quot; /&amp;gt;&lt;/code>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>is &lt;code>&amp;lt;dubbo:registry address=&amp;quot;zookeeper://10.20.153.10:2181&amp;quot; /&amp;gt;&lt;/code>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>is one of &lt;code>DubboInvoker&lt;/code>, &lt;code>HessianRpcInvoker&lt;/code>, &lt;code>InjvmInvoker&lt;/code>, &lt;code>RmiInvoker&lt;/code>, &lt;code>WebServiceInvoker&lt;/code>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Docs: Dubbo Design Principals</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/principals/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/principals/</guid><description>
&lt;p>The design principles in this chapter are taken from a series of articles published by Liang Fei on javaeye.&lt;/p></description></item><item><title>Docs: SPI Extension Implementations</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/impls/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/impls/</guid><description>
&lt;p>SPI extension interface is used for system integration, it&amp;rsquo;s also useful for dubbo contributor to extend dubbo functionality.&lt;/p></description></item><item><title>Docs: Public Agreement</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/contract/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/contract/</guid><description>
&lt;p>This document is Dubbo public agreement, we expect all extension points comply with it.&lt;/p>
&lt;h2 id="url">URL&lt;/h2>
&lt;ul>
&lt;li>All extension points must include URL parameter, design URL as a context information which throughouts the whole extension point design system.&lt;/li>
&lt;li>URL standard style: &lt;code>protocol://username:password@host:port/path?key=value&amp;amp;key=value&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="logging">Logging&lt;/h2>
&lt;ul>
&lt;li>Print &lt;code>ERROR&lt;/code> log for unrecoverable and NEED TO ALARM situation.&lt;/li>
&lt;li>Print &lt;code>WARN&lt;/code> log for recoverable exception or transient state inconsistency.&lt;/li>
&lt;li>Print &lt;code>INFO&lt;/code> log for normally status.&lt;/li>
&lt;/ul></description></item><item><title>Docs: Versions</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/release/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/release/</guid><description>
&lt;p>&lt;strong>New feature development&lt;/strong> and &lt;strong>stability improvement&lt;/strong> are equally important to product. But adding new features will affect stability, dubbo uses the following version development pattern to achieve a good balance.&lt;/p>
&lt;h2 id="two-versions-evolving-at-the-same-time">Two versions evolving at the same time&lt;/h2>
&lt;ul>
&lt;li>BugFix Version:low version,e.g. &lt;code>2.4.x&lt;/code>. This is called the GA version, which can be applied in production. We are supposed only to fix bugs in this version, and increase the third version number when release.&lt;/li>
&lt;li>Feature Version:high version, e.g. &lt;code>2.5.x&lt;/code>. We add new features to this version, so applications have opportunities try new features.&lt;/li>
&lt;/ul>
&lt;p>When features in &lt;code>2.5.x&lt;/code> are proved stable enough, we will announce &lt;code>2.5.x&lt;/code> as a beta release.&lt;/p>
&lt;p>When &lt;code>2.5.x&lt;/code> proved stable after enough test on enough applications:&lt;/p>
&lt;ul>
&lt;li>&lt;code>2.5.x&lt;/code>, the GA Version, only do BugFix, the main version to be used. We can try to promote applications to upgrade to GA at the desired time.&lt;/li>
&lt;li>&lt;code>2.4.x&lt;/code>, no longer maintained. When bugs appear, applications have no choice but upgrade to the latest stable version- Sunset Clause&lt;/li>
&lt;li>We create a new branch &lt;code>2.6.0&lt;/code> based on &lt;code>2.5.x&lt;/code> for new features.&lt;/li>
&lt;/ul>
&lt;h2 id="pros">Pros&lt;/h2>
&lt;ul>
&lt;li>GA Version are promised stable:
&lt;ul>
&lt;li>only BugFix&lt;/li>
&lt;li>GA Version got enough tests before promotion&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>New features can respond quickly in Feature Version and allow applications to try that&lt;/li>
&lt;li>Significantly reduces development and maintenance costs&lt;/li>
&lt;/ul>
&lt;h2 id="the-responsibilities-of-users">The responsibilities of users&lt;/h2>
&lt;p>Users should always keep in track with the GA Version, make sure all bugs were fixed.&lt;/p>
&lt;p>There is a fake proposition: regular upgrades bring more risks. Here&amp;rsquo;s the reasons:&lt;/p>
&lt;ul>
&lt;li>GA remains stable after a trial period.&lt;/li>
&lt;li>Bugs find on GA will be fixed immediately.&lt;/li>
&lt;li>Comparing with the on-need-upgrade (only upgrade when find a serious problem, and may span multiple versions), upgrade periodically can flat risk. Experienced a long cycle of large projects, students will have such an experience, the tripartite library version does not upgrade for a long time, the result of the problem had to upgrade to the new version (across multiple versions) a huge risk.&lt;/li>
&lt;/ul></description></item><item><title>Docs: Checklist</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/checklist/</guid><description>
&lt;h2 id="checklist-before-release">Checklist before release&lt;/h2>
&lt;ul>
&lt;li>github milestones&lt;/li>
&lt;li>github change lists&lt;/li>
&lt;li>Travis CI&lt;/li>
&lt;li>test code&lt;/li>
&lt;li>find bugs&lt;/li>
&lt;/ul>
&lt;h2 id="checklist-for-bigfix-versions">Checklist for bigfix versions&lt;/h2>
&lt;ul>
&lt;li>Create a &lt;em>github issue&lt;/em> before coding&lt;/li>
&lt;li>Create &lt;em>unit test&lt;/em> before bugfix&lt;/li>
&lt;li>Review&lt;/li>
&lt;li>Test your code (Normal process / Abnormal process)&lt;/li>
&lt;li>Record your design on &lt;em>github issue&lt;/em>&lt;/li>
&lt;li>Complete javadoc and comment in code&lt;/li>
&lt;li>Manager for every version, responsible for scope and check&lt;/li>
&lt;/ul></description></item><item><title>Docs: Bad Smell</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/code-smell/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/code-smell/</guid><description>
&lt;p>Ugly Dubbo design or implementation will be record here.&lt;/p>
&lt;h2 id="url-convertion">URL Convertion&lt;/h2>
&lt;h3 id="1-point-to-point-service-export-and-refer">1. Point to Point Service export and refer&lt;/h3>
&lt;p>service directly export:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>EXPORT(dubbo://provider-address/com.xxx.XxxService?version=1.0.0&amp;#34;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>service directly refer:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>REFER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="2-export-servie-by-registry">2. Export servie by registry&lt;/h3>
&lt;p>export service to registry:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>EXPORT(registry://registry-address/org.apache.dubbo.registry.RegistrySerevice?registry=dubbo&amp;amp;export=ENCODE(dubbo://provider-address/com.xxx.XxxService?version=1.0.0))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>accquire registry:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.setProtocol(url.getParameter(&amp;#34;registry&amp;#34;, &amp;#34;dubbo&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GETREGISTRY(dubbo://registry-address/org.apache.dubbo.registry.RegistrySerevice)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>registry service address:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.getParameterAndDecoded(&amp;#34;export&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>REGISTER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-refer-service-from-registry">3. Refer service from registry&lt;/h3>
&lt;p>refer service from registry:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>REFER(registry://registry-address/org.apache.dubbo.registry.RegistrySerevice?registry=dubbo&amp;amp;refer=ENCODE(version=1.0.0))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>accquire registry:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.setProtocol(url.getParameter(&amp;#34;registry&amp;#34;, &amp;#34;dubbo&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GETREGISTRY(dubbo://registry-address/org.apache.dubbo.registry.RegistrySerevice)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>subscribe service address:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.addParameters(url.getParameterAndDecoded(&amp;#34;refer&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SUBSCRIBE(dubbo://registry-address/com.xxx.XxxService?version=1.0.0)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>notify service address:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.addParameters(url.getParameterAndDecoded(&amp;#34;refer&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NOTIFY(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="4-registry-push-route-rule">4. Registry push route rule&lt;/h3>
&lt;p>registry push route rule:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>NOTIFY(route://registry-address/com.xxx.XxxService?router=script&amp;amp;type=js&amp;amp;rule=ENCODE(function{...}))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>accquire routers:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.setProtocol(url.getParameter(&amp;#34;router&amp;#34;, &amp;#34;script&amp;#34;))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GETROUTE(script://registry-address/com.xxx.XxxService?type=js&amp;amp;rule=ENCODE(function{...}))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="5-load-route-rule-from-file">5. Load route rule from file&lt;/h3>
&lt;p>load route rule from file:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>GETROUTE(file://path/file.js?router=script)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>accquire routers:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>url.setProtocol(url.getParameter(&amp;#34;router&amp;#34;, &amp;#34;script&amp;#34;)).addParameter(&amp;#34;type&amp;#34;, SUFFIX(file)).addParameter(&amp;#34;rule&amp;#34;, READ(file))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GETROUTE(script://path/file.js?type=js&amp;amp;rule=ENCODE(function{...}))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="invoke-parameters">Invoke parameters&lt;/h2>
&lt;ul>
&lt;li>path service path&lt;/li>
&lt;li>group service group&lt;/li>
&lt;li>version service version&lt;/li>
&lt;li>dubbo current dubbo release version&lt;/li>
&lt;li>token verify token&lt;/li>
&lt;li>timeout invocation timeout&lt;/li>
&lt;/ul>
&lt;h2 id="spi-loading">SPI Loading&lt;/h2>
&lt;h3 id="1-spi-auto-adaptive">1. SPI Auto Adaptive&lt;/h3>
&lt;p>When ExtensionLoader loads SPI, It will check spi attributes(using set method) . If one attribute is SPI, ExtensionLoader will load the SPI implementation. Auto injected object is an adaptive instance(proxy) ,because the real implementation is confirmed only in execution stage.。when adaptive spi is invoked, Dubbo will choose the real implementation and executes it. Dubbo choose the right implementation according to the parameters that the mehod defines.&lt;/p>
&lt;p>All the inner SPIs that Dubbo defines have the URL parameter defined for the method invocation. Adaptive SPI uses URL to determine which implementation is needed. One specific Key and Value in the URL confirms the usage of the specific implementation, All these is done by adding &lt;code>@Adaptive&lt;/code> annotation.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Extension&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">Car&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">@Adaptive&lt;/span>&lt;span style="color:#719e07">({&lt;/span>&lt;span style="color:#2aa198">&amp;#34;http://10.20.160.198/wiki/display/dubbo/car.type&amp;#34;&lt;/span>&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">&amp;#34;http://10.20.160.198/wiki/display/dubbo/transport.type&amp;#34;&lt;/span>&lt;span style="color:#719e07">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">run&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL url&lt;span style="color:#719e07">,&lt;/span> Type1 arg1&lt;span style="color:#719e07">,&lt;/span> Type2 arg2&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For the rules above,ExtensionLoader will create a adaptive instance for each SPI injected.&lt;/p>
&lt;p>ExtensionLoader generated adaptive classes look like :&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">package&lt;/span> &amp;lt;package name &lt;span style="color:#719e07">for&lt;/span> SPI interface&lt;span style="color:#719e07">&amp;gt;;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &amp;lt;&lt;span style="color:#268bd2">SPI&lt;/span> &lt;span style="color:#268bd2">interface&lt;/span> &lt;span style="color:#268bd2">name&lt;/span>&lt;span style="color:#719e07">&amp;gt;&lt;/span>$Adpative &lt;span style="color:#268bd2">implements&lt;/span> &lt;span style="color:#719e07">&amp;lt;&lt;/span>SPI interface&lt;span style="color:#719e07">&amp;gt;&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#719e07">&amp;lt;&lt;/span>contains &lt;span style="color:#268bd2">@Adaptive&lt;/span> annotation method&lt;span style="color:#719e07">&amp;gt;(&amp;lt;&lt;/span>parameters&lt;span style="color:#719e07">&amp;gt;)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span>&lt;span style="color:#719e07">(&lt;/span>parameters containing URL Type&lt;span style="color:#719e07">?)&lt;/span> using URL parameter
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">else&lt;/span> &lt;span style="color:#268bd2">if&lt;/span>&lt;span style="color:#719e07">(&lt;/span>method returns URL&lt;span style="color:#719e07">)&lt;/span> using the &lt;span style="color:#719e07">return&lt;/span> URL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> # &lt;span style="color:#719e07">&amp;lt;&lt;/span>&lt;span style="color:#719e07">else&lt;/span> &lt;span style="color:#719e07">throw&lt;/span> exception&lt;span style="color:#719e07">,&lt;/span>inject SPI fail!&lt;span style="color:#719e07">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span>&lt;span style="color:#719e07">(&lt;/span>URL accquired &lt;span style="color:#719e07">==&lt;/span> &lt;span style="color:#cb4b16">null&lt;/span>&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">throw&lt;/span> &lt;span style="color:#719e07">new&lt;/span> IllegalArgumentException&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;url == null&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> According to the Key order from &lt;span style="color:#268bd2">@Adaptive&lt;/span> annotation,get the Value from the URL as the real SPI name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> no value is found then use the &lt;span style="color:#719e07">default&lt;/span> SPI implementation。If no SPI point, &lt;span style="color:#719e07">throw&lt;/span> &lt;span style="color:#719e07">new&lt;/span> IllegalStateException&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;Fail to get extension&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Invoke the method using the spi and &lt;span style="color:#719e07">return&lt;/span> the result&lt;span style="color:#719e07">.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#719e07">&amp;lt;&lt;/span>method having annotation &lt;span style="color:#268bd2">@Adaptive&lt;/span>&lt;span style="color:#719e07">&amp;gt;(&amp;lt;&lt;/span>parameters&lt;span style="color:#719e07">&amp;gt;)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">throw&lt;/span> &lt;span style="color:#719e07">new&lt;/span> UnsupportedOperationException&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;is not adaptive method!&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>@Adaptive&lt;/code> annotation usage:&lt;/p>
&lt;p>If no value is configed for those Keys in URL,default SPI implementation is used。For example ,String[] {&amp;ldquo;key1&amp;rdquo;, &amp;ldquo;key2&amp;rdquo;},firstly Dubbo will look up value for key1 and use it as SPI name;if key1 value is not founded then look up for key2,if value of key2 is also not found ,then use default spi implementation. If no default implementation is configed, then the method will throw IllegalStateException。if not configed , then default implement is lower case of the interface class full package name. For Extension interface &lt;code>org.apache.dubbo.xxx.YyyInvokerWrapper&lt;/code> , default value is &lt;code>new String[] {&amp;quot;yyy.invoker.wrapper&amp;quot;}&lt;/code>&lt;/p>
&lt;h2 id="callback-function">Callback Function&lt;/h2>
&lt;h3 id="1-parameter-callback">1. Parameter Callback&lt;/h3>
&lt;p>main theory : in the persistent connection for one consumer-&amp;gt;provider,export a service in Consumer side,provider side can reversely call the instance in consumer side.&lt;/p>
&lt;p>Implement details:&lt;/p>
&lt;ul>
&lt;li>For exchanging interface instance in transmition, auto export and auto refer is implemented in DubboCodec . Need to seperate business logic and codec logic.&lt;/li>
&lt;li>you will need to judge whether needing callback when getting exporter from invocation,if needed, get the callback instance id from the attachments. By using this method, consumer side can implement the callback interface with different implementations.&lt;/li>
&lt;/ul>
&lt;h3 id="2-event-notification">2. Event Notification&lt;/h3>
&lt;p>main theory : when Consumer executing invoke method,judging if any configuration for onreturn/onerror&amp;hellip; put the method for onreturn to the callback list of the async invocatioin.&lt;/p>
&lt;p>Implement details:parameters is passed using URL,but string-object is not supported for URL, so the method is stored in staticMap,it needs to be optimized.&lt;/p>
&lt;h2 id="lazy-connection">Lazy Connection&lt;/h2>
&lt;p>DubboProtocol specific features, default disabled&lt;/p>
&lt;p>When client creating proxy for server, do not establish TCP persistent connection at first, only init the connecton when data is needing transmision.&lt;/p>
&lt;p>This feather will disable the connection retry policy , resend the data again(if connection is lost when sending data ,try to establish a new connection to send data)&lt;/p>
&lt;h2 id="share-connection">Share Connection&lt;/h2>
&lt;p>DubboProtocol specific features, default enabled。&lt;/p>
&lt;p>JVM A export many services,JVM B refer more than one services of A,Share Connection means those different services invocations between A and B uses the same TCP connection to transmit data, reducing server connections.&lt;/p>
&lt;p>Implement details:when using share connection for the same address,you need pay more attention to the invoker&amp;rsquo;s destroy action.on one hand, you should close the connection when all the invokers refering the same address is destroyed, on another hand ,you should not close the connection when not all of the invokers are destroyed. In design implementation, we uses a strategy called reference count , we create a connection called Lazy connection for exceptions not affacting business when closing the connection just in case.&lt;/p>
&lt;h2 id="sticky-policy">sticky policy&lt;/h2>
&lt;p>when existing many providers and configing the sticky policy,invocation will be sent to the same provider as last invocation. Sticky Policy opens the lazy attribute of connection, for avoiding open useless connectons.&lt;/p>
&lt;h2 id="provider-selecting-logic">provider selecting logic&lt;/h2>
&lt;ol start="0">
&lt;li>existing multi providers,firstly select by Loadbalance 。If the selected provider is available ,then just doing the invocation&lt;/li>
&lt;li>If the selected provider is not available in stage 1, then choose from the remaining ,if available then doing the inovation&lt;/li>
&lt;li>If all providers are not available , rescan the list(not choosen invoker first),juding if any provider is available, if existing,doing the invocatiion.&lt;/li>
&lt;li>If no available provider in stage 3, then the next invoker of the invoker of stage 1 will be choosen(if not the last one),avoiding collision.&lt;/li>
&lt;/ol></description></item><item><title>Docs: Coding Convention</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/coding/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/coding/</guid><description>
&lt;h2 id="code-style">Code style&lt;/h2>
&lt;p>The source and JavaDoc of Dubbo follow below specifications:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html">Code Conventions for the Java Programming Language&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html">How to Write Doc Comments for the Javadoc Tool&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="exception-and-logging">Exception and Logging&lt;/h2>
&lt;ul>
&lt;li>Log more context information as possible, such as error reason, error server address, client address, registry center address, dubbo version and so on.&lt;/li>
&lt;li>Try to put the main cause at the front, and display all other context information with key-value paris after it.&lt;/li>
&lt;li>Log is not printed where the exception is thrown, log level is determined by the final exception handler, and must print log when dicarding exception.&lt;/li>
&lt;li>&lt;code>ERROR&lt;/code> log means NEED TO ALARM, &lt;code>WARN&lt;/code> log means COULD AUTO RECOVERY, &lt;code>INFO&lt;/code> long mean NORMAL.&lt;/li>
&lt;li>Suggestion: config &lt;code>ERROR&lt;/code> log in Monitor center for real-time alarm, summary and send &lt;code>WARN&lt;/code> log weekly.&lt;/li>
&lt;li>&lt;code>RpcException&lt;/code> is the ONLY external exception of Dubbo,all internal exceptions mush be transfered to &lt;code>RpcException&lt;/code> if need to throw out to user.&lt;/li>
&lt;li>&lt;code>RpcException&lt;/code> CAN NOT have sub-class, all types of information are identified with ErrorCode in order to keep compatible.&lt;/li>
&lt;/ul>
&lt;h2 id="configuration-and-url">Configuration and URL&lt;/h2>
&lt;ul>
&lt;li>Use initials and camelCase for multiple words for object properties &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/li>
&lt;li>Use lowercase and split by &amp;lsquo;-&amp;rsquo; for multiple words for config properties &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>.&lt;/li>
&lt;li>Use lowercase and split by &amp;lsquo;.&amp;rsquo; for multiple words for URL properties &lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>.&lt;/li>
&lt;li>Use URL transfer parameters as possible, Don&amp;rsquo;t define Map or other types, config information also transfer to URL style.&lt;/li>
&lt;li>Minimize URL nesting to keep URL simplicity.&lt;/li>
&lt;/ul>
&lt;h2 id="unit-testing-and-integration-testing">Unit testing and integration testing&lt;/h2>
&lt;ul>
&lt;li>Use JUnit and EasyMock for unit testing, use TestNG for integration testing, use DBUnit for database testing.&lt;/li>
&lt;li>Don&amp;rsquo;t put large integration test case in unit testing for running speed of unit test case.&lt;/li>
&lt;li>Use &lt;code>try...finally&lt;/code> or &lt;code>tearDown&lt;/code> to release resource for all test cases of unit testing.&lt;/li>
&lt;li>Minimize test case that with &lt;code>while&lt;/code> loop which need waiting repsonse, use to make the logic in timer as function for timer and net testing.&lt;/li>
&lt;li>For fail-safe testing, unified use &lt;code>LogUtil&lt;/code> assertion log output.&lt;/li>
&lt;/ul>
&lt;h2 id="extension-point-base-class-and-aop">Extension point base class and AOP&lt;/h2>
&lt;ul>
&lt;li>AOP class should be named as &lt;code>XxxWrapper&lt;/code>,Base class should be named as &lt;code>AbstractXxx&lt;/code>.&lt;/li>
&lt;li>Use AOP for combine relationship between extension points, &lt;code>ExtensionLoader&lt;/code> only loads extension points, including AOP extension.&lt;/li>
&lt;li>Try to use Ioc inject dependency of extension points, Don&amp;rsquo;t direct dependent on factory method of &lt;code>ExtensionLoader&lt;/code>.&lt;/li>
&lt;li>Try to use AOP implement the common action of extension points, instead of using base class, such as the &lt;code>isAvailable&lt;/code> checking before load balancing, which is independent of load balance. Close the URL paramters which no need to check.&lt;/li>
&lt;li>Use base class for abstaction for a variety of similar types, such as RMI, Hessian 3rd protocols which have generated interface proxy, only transfer interface proxy to &lt;code>Invoker&lt;/code> to complete bridging, and public base class can do the logic.&lt;/li>
&lt;li>The base class is also part of the SPI, and each extension should have a convenient base class support.&lt;/li>
&lt;/ul>
&lt;h2 id="module-and-packaging">Module and packaging&lt;/h2>
&lt;ul>
&lt;li>Base on reusability for packaging, dividing the interface, base class and large implementation into separate modules.&lt;/li>
&lt;li>Put all interfaces under the base package of module, and put base classes in support subpackage, different implementations are placed under the subpackage named by extension point.&lt;/li>
&lt;li>Try to keep subpackage dependent on parent package, NOT reverse.&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Java convention&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>Spring convention&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>Dubbo convention&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Docs: Compatibility Test</title><link>https://dubbo.apache.org/en/docs/v2.7/dev/tck/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs/v2.7/dev/tck/</guid><description>
&lt;p>Dubbo&amp;rsquo;s protocol, communication, serialization, registry, load balancing and other SPI all offer alternative strategies for different application scenarios while our test cases are very scattered. Ours is always uncertain whether it can satisfy the complete contract of the extension point when users need to add a new implementation.&lt;/p>
&lt;p>Thus we need to use TCK (Technology Compatibility Kit) for the core extension points. When users add a new implementaion, compatibility with the rest of the framework can be ensured with TCK. This can effectively improve the overall health and also facilitate the access of the third party extenders, which accelerates the maturity of the open source community.&lt;/p>
&lt;p>Xingzhi from the open source community is already working on this part. His preliminary idea is to build a TCK framework for Dubbo drawing on the CDI-TCK of JBoss first, then realize the TCK implementing case of Dubbo.&lt;/p>
&lt;p>Reference:http://docs.jboss.org/cdi/tck/reference/1.0.1-Final/html/introduction.html&lt;/p>
&lt;p>Anyone interested is welcomed to work on this together.&lt;/p>
&lt;h4 id="protocol-tck">Protocol TCK&lt;/h4>
&lt;blockquote>
&lt;p>TODO&lt;/p>
&lt;/blockquote>
&lt;h4 id="registry-tck">Registry TCK&lt;/h4>
&lt;blockquote>
&lt;p>TODO&lt;/p>
&lt;/blockquote></description></item></channel></rss>