Ugly Dubbo design or implementation will be record here.
service directly export:
EXPORT(dubbo://provider-address/com.xxx.XxxService?version=1.0.0")
service directly refer:
REFER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
export service to registry:
EXPORT(registry://registry-address/org.apache.dubbo.registry.RegistrySerevice?registry=dubbo&export=ENCODE(dubbo://provider-address/com.xxx.XxxService?version=1.0.0))
accquire registry:
url.setProtocol(url.getParameter("registry", "dubbo"))
GETREGISTRY(dubbo://registry-address/org.apache.dubbo.registry.RegistrySerevice)
registry service address:
url.getParameterAndDecoded("export"))
REGISTER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
refer service from registry:
REFER(registry://registry-address/org.apache.dubbo.registry.RegistrySerevice?registry=dubbo&refer=ENCODE(version=1.0.0))
accquire registry:
url.setProtocol(url.getParameter("registry", "dubbo"))
GETREGISTRY(dubbo://registry-address/org.apache.dubbo.registry.RegistrySerevice)
subscribe service address:
url.addParameters(url.getParameterAndDecoded("refer"))
SUBSCRIBE(dubbo://registry-address/com.xxx.XxxService?version=1.0.0)
notify service address:
url.addParameters(url.getParameterAndDecoded("refer"))
NOTIFY(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)
registry push route rule:
NOTIFY(route://registry-address/com.xxx.XxxService?router=script&type=js&rule=ENCODE(function{...}))
accquire routers:
url.setProtocol(url.getParameter("router", "script"))
GETROUTE(script://registry-address/com.xxx.XxxService?type=js&rule=ENCODE(function{...}))
load route rule from file:
GETROUTE(file://path/file.js?router=script)
accquire routers:
url.setProtocol(url.getParameter("router", "script")).addParameter("type", SUFFIX(file)).addParameter("rule", READ(file))
GETROUTE(script://path/file.js?type=js&rule=ENCODE(function{...}))
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.
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 @Adaptive
annotation.
@Extension
public interface Car {
@Adaptive({"http://10.20.160.198/wiki/display/dubbo/car.type", "http://10.20.160.198/wiki/display/dubbo/transport.type"})
public run(URL url, Type1 arg1, Type2 arg2);
}
For the rules above,ExtensionLoader will create a adaptive instance for each SPI injected.
ExtensionLoader generated adaptive classes look like :
package <package name for SPI interface>;
public class <SPI interface name>$Adpative implements <SPI interface> {
public <contains @Adaptive annotation method>(<parameters>) {
if(parameters containing URL Type?) using URL parameter
else if(method returns URL) using the return URL
# <else throw exception,inject SPI fail!>
if(URL accquired == null) {
throw new IllegalArgumentException("url == null");
}
According to the Key order from @Adaptive annotation,get the Value from the URL as the real SPI name
if no value is found then use the default SPI implementation。If no SPI point, throw new IllegalStateException("Fail to get extension");
Invoke the method using the spi and return the result.
}
public <method having annotation @Adaptive>(<parameters>) {
throw new UnsupportedOperationException("is not adaptive method!");
}
}
@Adaptive
annotation usage:
If no value is configed for those Keys in URL,default SPI implementation is used。For example ,String[] {“key1”, “key2”},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 org.apache.dubbo.xxx.YyyInvokerWrapper
, default value is new String[] {"yyy.invoker.wrapper"}
main theory : in the persistent connection for one consumer->provider,export a service in Consumer side,provider side can reversely call the instance in consumer side.
Implement details:
main theory : when Consumer executing invoke method,judging if any configuration for onreturn/onerror… put the method for onreturn to the callback list of the async invocatioin.
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.
DubboProtocol specific features, default disabled
When client creating proxy for server, do not establish TCP persistent connection at first, only init the connecton when data is needing transmision.
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)
DubboProtocol specific features, default enabled。
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.
Implement details:when using share connection for the same address,you need pay more attention to the invoker’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.
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.