Dubbo Configuration Rules Detailed
Welcome to Join Dubbo Group: 259566260
Research Dubbo also has been a half year, the majority of its source code analysis, as well as its internal mechanisms have a more in-depth understanding, as well as the implementation of the various modules. Dubbo contains a lot of content, if you want to understand Dubbo the first step is to start it, so that you can use it well, then how to better use it? You need to know the various configuration items of the Dubbo, and the ways in which they can be configured. Personal understanding of the configuration, like when the animal tamed, how good to tame a beast, it needs to know its various habits, thus adjusting, has reached its desired results. This article does not Dubbo which configuration items can be configured, but through this article, you should be able to know what configuration Dubbo can make. This article will analyze the Dubbo load configuration source code analysis, to make everyone on the configuration of Dubbo a more in-depth understanding. So as to "tame" the Dubbo so that it becomes your own Dubbo.
Dubbo in the configuration this piece is really perfect, offers a lot of parameters, and offers a variety of channels. Let's get to the bottom and see how Dubbo loads the configuration. Before you talk about this, let's introduce what classes are defined at the Dubbo source level to store the configuration items for each module, so that you know which modules Dubbo can configure.
Which things can be configured
Since most projects use spring, and Dubbo provides the configuration through spring, start here. Dubbo load Spring Integration is under Dubbo-config under the Dubbo-config-spring module, which has a class DubboNamespaceHandler
that implements the interface provided by spring NamespaceHandlerSupport
. So how does spring find the entire implementation class? There are two files in the Meta-inf folder of the module: Spring.handlers and Spring.schemas, the location of the Dubbo namespace XSD file in the two files and Dubbo namespace by DubboNamespaceHandler
to handle parsing. That's a lot of crap, just to show how spring is <dubbo:.../>
configured.
Knowing how Dubbo and Spring are integrated when configuring a piece, then you should not be surprised how spring is so smart and able to parse Dubbo's namespace. Now let's see DubboNamespaceHandler
what's in the class.
<!--Lang:java-->public class Dubbonamespacehandler extends Namespacehandlersupport {static {Version.chec Kduplicate (Dubbonamespacehandler.class); } public void Init () {Registerbeandefinitionparser ("Application", New Dubbobeandefinitionparser (applicationconf Ig.class, True)); Registerbeandefinitionparser ("module", New Dubbobeandefinitionparser (Moduleconfig.class, true)); Registerbeandefinitionparser ("Registry", New Dubbobeandefinitionparser (Registryconfig.class, true)); Registerbeandefinitionparser ("Monitor", New Dubbobeandefinitionparser (Monitorconfig.class, true)); Registerbeandefinitionparser ("Provider", New Dubbobeandefinitionparser (Providerconfig.class, true)); Registerbeandefinitionparser ("Consumer", New Dubbobeandefinitionparser (Consumerconfig.class, true)); Registerbeandefinitionparser ("Protocol", new Dubbobeandefinitionparser (Protocolconfig.class, true)); Registerbeandefinitionparser ("service", new DUbbobeandefinitionparser (Servicebean.class, true)); Registerbeandefinitionparser ("Reference", New Dubbobeandefinitionparser (Referencebean.class, false)); Registerbeandefinitionparser ("annotation", New Dubbobeandefinitionparser (Annotationbean.class, true)); }}
You can see init
that a method is called inside a method registerBeanDefinitionParser
, but the parameters are slightly different. The registerBeanDefinitionParser
first parameter of the Dubbo method is the namespace of the following node name, and the second parameter is the node whose resolution is determined by whom. For example: registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
parsing <dubbo:application../>
configuration information, and so on through spring can be configured <dubbo:module../>
, and so on <dubbo:registry../>
, not listed. As for the role of each label configuration, because it is not the content of this article, so here do not do too much introduction.
By the above should know clearly what Dubbo can be configured? This question should not bother you any more. Here's a look at how Dubbo loads these configuration items.
How to read our configuration read through spring's bean configuration
In the project, spring XML is configured (although Dubbo also supports annotation forms, but the individual is not very respected, because this will integrate Dubbo into your project source code, and my advice is not to say Dubbo and your project tied too tightly, my proposal is Dubbo configuration and project isolation, To facilitate management, the project will not use Dubbo after joining, and the use of other distributed RPC framework, the adjustment of the project is relatively small), such as often through the following configuration items refer to a remote service:
<!--lang:xml--><dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" timeout="2000" check="false"/>
Through the above, you should know that it dubbo:reference
will be new DubboBeanDefinitionParser(ReferenceBean.class, false)
parsed (although it looks like all configurations are DubboBeanDefinitionParser
parsed, but very different). Then look at DubboBeanDefinitionParser
what's going on in the class.
<!--lang:java-->public class DubboBeanDefinitionParser implements BeanDefinitionParser {private static final Logger logger = LoggerFactory.getLogger(DubboBeanDefinitionParser.class);private final Class<?> beanClass;private final boolean required;public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) { this.beanClass = beanClass; this.required = required;}public BeanDefinition parse(Element element, ParserContext parserContext) { return parse(element, parserContext, beanClass, required);}@SuppressWarnings("unchecked")private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {....}}
Look at the definition of the class first, Dubbobeandefinitionparser
implements the spring Beandefinitionparser
interface, This interface is specifically used to parse the Bean's definition (which should be known by the class name) and implements the public beandefinition parse (element element, ParserContext ParserContext)
method (although the entire method returns a beandefinition
object, spring does not take advantage of the entire returned object, you can see the spring source, So to inject the bean definition into the spring container, we need to inject it manually into spring, because spring does not do this for us. ), and then call the static method private static Beandefinition parse (...)
, then the class is mostly on a static method parse
. Because the content of this method is too long, inconvenient to paste out all the content, I only analyze the main part. There is a class<?> beanclass
parameter on the Dubbobeandefinitionparser
constructor parameter, which specifies that the contents of the current label configuration are converted to the corresponding class. beandefinition
and injected into the spring container.
<!--lang:java-->private static beandefinition Parse (element element, ParserContext ParserContext, class<? > Beanclass, Boolean required) {rootbeandefinition beandefinition = new Rootbeandefinition (); Beandefinition.setbeanclass (Beanclass); Beandefinition.setlazyinit (FALSE); String id = element.getattribute ("id"); if ((id = = NULL | | id.length () = = 0) && required) {//construct a bean ID} .... parsercontext.getregistry (). Registerbeandefinition (ID, beandefinition); .... for (Method setter:beanClass.getMethods ()) {String name = Setter.getname (); if (Name.length () > 3 && name.startswith ("set") && Modifier.ispublic (setter.getmodifiers ()) && setter.getparametertypes (). length = = 1) {class<?> type = Setter.getparamet Ertypes () [0]; String property = Stringutils.cameltosplitname (Name.substring (3, 4). toLowerCase () + name.substring (4), "-"); Props.add (property); Method getter = null; try {getter = Beanclass.getmethod ("Get" + name.substring (3), new class<?>[0]); } catch (Nosuchmethodexception e) {try {getter = Beanclass.getmethod ("is" + Name.subst Ring (3), new class<?>[0]); } catch (Nosuchmethodexception e2) {}} if (getter = = NULL | |! Modifier.ispublic (Getter.getmodifiers ()) | | ! Type.equals (Getter.getreturntype ())) {continue; } if ("Parameters". Equals (property)) {parameters = Parseparameters (Element.getchildnodes (), Bea Ndefinition); } else if ("methods". Equals property) {Parsemethods (ID, element.getchildnodes (), Beandefinition, Parserco ntext); } else if ("arguments". Equals property) {parsearguments (ID, element.getchildnodes(), beandefinition, ParserContext); } ..... beandefinition.getpropertyvalues (). Addpropertyvalue (property, reference); ......
It is clear from the above code that the method of getting the class is obtained through reflection, get/set
so that the parameter can be injected into the spring, added to the beanDefinition
spring container, and injected into it. The above is the mechanism for loading the configuration from spring.
Get the configuration from the Java Run command-D and properties
The above shows what modules Dubbo can configure, and which classes are used to store the configuration information, such as:,, ReferenceBean
RegistryConfig
etc., ServiceBean
if you look inside the definition of these classes and see that they inherit the AbstractConfig
abstract class, the method is defined in the abstract class. protected static void appendProperties(AbstractConfig config)
Parameter when one implements its own subclass, next look at what it does:
<!--lang:java-->protected static void appendproperties (Abstractconfig config) {if (config = = null) {Retu Rn } String prefix = "Dubbo." + Gettagname (Config.getclass ()) + "."; Method[] methods = Config.getclass (). GetMethods (); for (Method method:methods) {try {String name = Method.getname (); if (Name.length () > 3 && name.startswith ("set") && Modifier.ispublic (Method.getmodifiers ()) && method.getparametertypes (). length = = 1 && isprimitive (method.getparametertypes () [0])) { String property = Stringutils.cameltosplitname (Name.substring (3, 4). toLowerCase () + name.substring (4), "-"); String value = null; if (config.getid () = null && Config.getid (). Length () > 0) {String pn = prefix + config.get Id () + "." + property; Value = System.getproperty (PN); if (! Stringutils.iSblank (value) {logger.info ("Use System property" + pn + "to config Dubbo"); }} if (value = = NULL | | value.length () = = 0) {String pn = prefix + Pro Perty; Value = System.getproperty (PN); if (! Stringutils.isblank (value) {logger.info ("Use System property" + pn + "to config Dubbo"); }} if (value = = NULL | | value.length () = = 0) {Method Gett Er try {getter = Config.getclass (). GetMethod ("Get" + name.substring (3), new class<?>[0]); } catch (Nosuchmethodexception e) {try {getter = Config . GetClass (). GetMethod ("is" + name.substring (3), new class<?>[0]); } catch (Nosuchmethodexception E2) {getter= NULL; }} if (getter = null) {if (Getter.invoke (config, new objec T[0]) = = null) {if (Config.getid () = null && Config.getid (). Length () > 0) { Value = configutils.getproperty (prefix + config.getid () + "." + property); } if (value = = NULL | | value.length () = = 0) {value = Conf Igutils.getproperty (prefix + property); } if (value = = NULL | | value.length () = = 0) {String Legacykey = Legacyproperties.get (prefix + property); if (Legacykey! = null && legacykey.length () > 0) {value = Convertlegacyvalu E (Legacykey, Configutils.getproperty (Legacykey)); } }}}} if (value! = null && V Alue.length () > 0) {method.invoke (config, new object[] {convertprimitive (Method.getparametertypes () [0], value)}); }}} catch (Exception e) {logger.error (E.getmessage (), E); } }}
The above method begins with the production of the current configuration prefix String prefix = "dubbo." + getTagName(config.getClass()) + "."
, where you can see that all of the configuration items of Dubbo are dubbo.
started, followed by getTagName
methods to generate the configuration name of the current configuration class, in getTagName
order to see how each configuration class generated the respective configuration name.
<!--lang:java-->private static final String[] SUFFIXS = new String[] {"Config", "Bean"};private static String getTagName(Class<?> cls) { String tag = cls.getSimpleName(); for (String suffix : SUFFIXS) { if (tag.endsWith(suffix)) { tag = tag.substring(0, tag.length() - suffix.length()); break; } } tag = tag.toLowerCase(); return tag;}
Parsing the above code clearly knows how to generate the configuration name of the respective configuration class, such as: Referencebean
This method returns reference
. So the configuration for referencing a remote bean is in dubbo.reference.
Start with. After the prefix for the current configuration class is generated, all set
methods of the current class are reflected by management, followed by System.getproperty
, if none of them are removed from the Configutils.getproperty the
. It is important to note that the value from system.getproperty
does not determine whether the current property has a value (injected through spring), and the configutils.getproperty
The fetch will determine if there is a value, if it is not, it can be explained that the priority of the Dubbo configuration item java-d takes precedence over the spring configuration, and the spring configuration takes precedence over the configuration of the properties
file. This also conforms to the general project's rules . I don't know if you noticed. Either system.getproperty
or configutils.getproperty
takes two times, one time is String pn = Prefix + config.getid () + "." + Property
, another time String pn = prefix + Property
, the difference between the two is one more config.g Etid ()
, might be curious config.getid ()
What is it? When it comes to spring loading configuration, it should be known that the Config
object is actually inside the spring container, and the getId
here is actually the ID that we configured when we configured spring's bean. For example:
<!--lang:java--><dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" timeout="2000" check="false" />
This configuration produces an ReferenceBean
object, so this is the config.getId()
case demoService
. So String pn = prefix + config.getId() + "." + property
the purpose of the configuration is to have no configuration item for the current bean. For example: Configure the Dubbo consumption end time, generally through dubbo.reference.timeout
, this is the specified consumer end of all beans time-out. Sometimes we need to specify that a bean time-out can be dubbo.reference.{beanId}.timeout
specified by, for example, the time-out that can be configured on the dubbo.reference.demoService.timeout
bean above.
To this Dubbo all the configuration of the way and its principles are analyzed and introduced, it seems to have not said how to find out what Dubbo configuration. Here we teach you how to find out what configuration Dubbo has. As described above, Dubbo sets the configuration item to the entity of each configuration class by judging whether there is a get/set
method, and here everyone should know how to find out? is if you want to know the configuration of a Dubbo module, go directly to the corresponding configuration class to see what fields it has, know its field name, and determine the scope you want to configure, whether it is a global or a bean, and what path you want to configure, Follow the rules provided by Dubbo to determine how the corresponding fields are configured. Then you might say that the field when a word knows how to configure, then if the field when more than one word combination of it? Since Java's coding style is generally the same as the hump format: The first letter of the initial lowercase words, then the first letter capitalized, then this case corresponds to Dubbo how to get the configuration item? See below:
<!--lang:java--> //name是get/set方法名 String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");
It is not difficult to find the hump, Dubbo when the word -
character to separate the words. In fact, here can basically be very good Configuration Dubbo, but there is a way above if you need to adjust the parameters need to restart the application, not to dynamic adjustment, so Dubbo to be able to meet the project does not restart the situation can be dynamically adjusted configuration parameters.
Add dynamic configurations with Dubbo management apps
The main principle of this approach is to publish the dynamic parameters to the registry (zookeeper) through the manager, then each node can obtain the latest configuration changes and then make dynamic adjustments. To know this piece of content, you need to take a look at the implementation of the class RegistryDirectory
, which implements it NotifyListener
. Then it can monitor any changes to the registry. RegistryDirectory
before you get to know it, let's look at what information Dubbo stores in the registry for each service. If you use the zookeeper, then you will see a few directories under each service node directory, consumers
, providers
configurators
routers
. Where the dynamic configuration is placed in the configurators
node directory. The service consumer listens configurators
for directory changes, and the method is called if the change is made RegistryDirectory
void notify(List<URL> urls)
. When you listen to a configurators
directory change-triggered void notify(List<URL> urls)
method, urls
It is similar override://...
, indicating that some configuration that invokes the service is overwritten (all invocation configurations in Dubbo are shown in the form of URLs), The parameter information above the URL is replaced by the URL on the calling server, and the object of the service is reconstructed to Invoke
update the parameters.
Parameters can be configured for the method of the interface
The whole scenario exists in the actual project, for example, there are multiple methods for an interface, sometimes it is not enough to say that the parameter configuration is now the interface level, and it needs to be accurate to the method level, such as the timeout setting for the interface call. Dubbo provides two ways to configure method-level configurations.
How Spring beans are configured
如下进行配置:<!--lang:xml--><dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" timeout="2000" check="false" > <dubbo:method name="sayHello" timeout="1000"/></dubbo:reference>
Implemented by multiple nested dubbo:method
tags.
Dynamic configuration
The Dubbo Manager provides dynamic configuration functionality by adding dynamic configuration and specifying the consumer of the notification to specify a method for a service to adjust parameters. It is there to configure the rule when the method name plus the name of the configuration item, for example: Key is configured as: sayHello.timeout
, value= "10000". The manager then adds a node to the registry's corresponding service configurators
override://...?sayHello.timeout=10000
, specifying that the consumer will listen to the change and execute the process of the above content.
There may be some areas where the Dubbo configuration has been introduced, and there are doubts as to what is not clearly stated. If you have questions, please ask questions or take a look at the relevant Dubbo source code, it will be more clearly understood.
Dubbo Configuration Rules Detailed