I found a bug in the Dubbo source code, and my colleagues said that I have something

I found a bug in the Dubbo source code, and my colleagues said that I have something

Like it and look again, develop a habit, search on WeChat [San Tai Zi Ao Bing] to follow this Internet tool man.
This article has been included on GitHub https://github.com/JavaFamily , with the complete test sites, materials and my series of articles for interviews with major companies.

background

One day the operation feedback, I clicked to save, but 3 pieces of data appeared in the background, I thought at the time, shouldn't, I haven't moved this code for tens of thousands of years, I told him to stop operating it and keep the scene. , I'll check it out.

I read the newly added code and right click to view the author
I found a bug in the Dubbo source code, and my colleagues said that I have something

Unexpectedly, Sanwai made changes, so I asked Sanwai, have you moved the new code of XX module?

He was silent for a long time without speaking, then grabbed the table and wiped the sweat left by the sideburns with the remaining paper, swallowed and said, yes, I changed it. I changed the xml configuration method of dubbo to the comment. the way.

what happened? BUG now?

You, you, tell me about this change next time, I guess it is a bug in the dubbo source code, don't panic, let me see what the problem is.

text

In fact, there are many ways to configure dubbo. The most commonly used is the xml configuration method. If the number of retries is not required, we will add the number of retries to 0, because it has multiple retries by default.

<dubbo:reference id="testService" interface="heiidea.trade.service.sdk.interfice.TestService" retries="0"/> 

Or use annotations

@Reference(retries =0) 

In fact, I already know the reason, but in order to confirm my guess, I started the next debug trip~~~

Note: dubbo version: 2.6.2

The first is under the condition of @Reference annotation:
I found a bug in the Dubbo source code, and my colleagues said that I have something

Use @Reference annotation to configure the number of retries

The first is to find the code location for dubbo retry (start the dubbo project, to call the interface, F5 enters the method, it will jump to the invoke method in the InvokerInvocationHandler, continue to track the invoke method in the MockClusterInvoker, and then enter the abstractClusterInvoker In the invoke method, here is mainly to get the configured load balancing strategy, which will be in the doInvoke method of FailoverClusterInvoker later).

The point is here, here will get the configured retries value, you can see that the above configuration is 0, but it is actually null when taken out, as shown in the figure:
I found a bug in the Dubbo source code, and my colleagues said that I have something

So the defaultValue will be returned, plus the one called by itself, it will be 3 after the calculation, as shown in the figure:
I found a bug in the Dubbo source code, and my colleagues said that I have something

Therefore, it can be found that when retries is configured as 0 in the form of @Reference annotation, the number of dubbo retries is 2 (3 includes the time it is called).

The following is the way to use the dubbo:reference tag:
I found a bug in the Dubbo source code, and my colleagues said that I have something

The method is as above. When getting the attribute, you can see that the obtained value is 0, which is consistent with the annotation form configuration, as shown in the figure:
I found a bug in the Dubbo source code, and my colleagues said that I have something

Add the call itself, and it will be 1 after calculation, as shown in the figure:
I found a bug in the Dubbo source code, and my colleagues said that I have something

So it can be found that when retries is set to 0 in the form of dubbo:reference tag, the number of dubbo retries is 0 (1 is the time it was called).

Cause Analysis

The first is the @Reference annotation form:

dubbo will first resolve each interface to ReferenceBean, and ReferenceBean implements the FactoryBean interface, so when injecting, it will call the getObject method to generate a proxy object.

But this is not the key, because by this step, all attributes have been loaded, so you need to find the code location of the attributes in the dubbo parsing annotation.

dubbo will use a custom driver ReferenceAnnotationBeanPostProcessor to inject properties, and the specific code location to execute the injection is executed by calling the inject method in the postProcessPropertyValues ​​method of the ReferenceAnnotationBeanPostProcessor class.

The point is here, because when using tags, @Autowired annotation injection is used, so spring native injection is used, and when @Reference annotations are used, the injection will go to the inject method of the private internal class ReferenceFieldElement in dubbo's own ReferenceAnnotationBeanPostProcessor , And then call buildReferenceBean to create a ReferenceBean.

The reason is getting closer. In this method, you can see that the retries value in beanBuilder is still 0, indicating that this step has not been resolved to null, as shown in the figure:
I found a bug in the Dubbo source code, and my colleagues said that I have something

Continue to go down, when calling configureBean in the build method, in the first step preConfigureBean method, the AnnotationPropertyValuesAdapter object will be created in this method, the adapt method will be called in the object construction method, and then go to the getAttributes method in AnnotationUtils , There is a key method nullSafeEquals, which will pass in the current attribute value and default value.

If they are equal, the attribute will be ignored, and then the qualified attributes will be put into the actualAttributes map, and our retries attribute is 0, which is consistent with the default value, so the value of the retries attribute will not be saved in the map, only the timeout attribute , So the value obtained later appears to be null.

The annotation method debug comes to an end.
I found a bug in the Dubbo source code, and my colleagues said that I have something

The form of the dubbo:reference tag follows:

As mentioned above, when the label form goes to inject, it will be different from the annotation form. When using this label, dubbo will use a custom namespace parser to parse it, which is easy to understand, and spring does not know what its custom label is. What do those things mean, so dubbo will inherit spring.

NamespaceHandlerSupport, uses a custom DubboNamespaceHandler parser to parse tags, as shown in the figure below:
I found a bug in the Dubbo source code, and my colleagues said that I have something

Then call the parse method in the class to parse, and the place to parse retries is to get the class (the class at this time is the class of the ReferenceBean marked in green above, and there are many set methods in its parent class, including the setRetries method) In all the methods, filter out the method at the beginning of set, then cut out the attribute name, put it into the attribute pool, you can see that the value parsed here is 0, not null, as shown below:
I found a bug in the Dubbo source code, and my colleagues said that I have something
I found a bug in the Dubbo source code, and my colleagues said that I have something

summary

Draw a simple picture:
I found a bug in the Dubbo source code, and my colleagues said that I have something

in conclusion

  • In the form of annotation: if retries is not configured or configured as 0, it will be retried twice. Only if the configuration is -1 or less, the retry will not be performed.
  • In the form of labels: if retries is not configured, it will retry twice, and if it is 0 or less, it will not retry.
    Therefore, it is recommended that you can set it to -1 when you do not need to retry, such as adding, deleting and modifying the interface of operations, otherwise you need to ensure idempotence. If you need to try again, set it to 1 or greater. In fact, this should be considered a dug of dubbo? (I think it is..)

This is the end, and calling the getObject method mentioned above is the subsequent service discovery and the establishment of a long connection with the server and returning the proxy object.

There are 3 data because I defined the interface timeout time is relatively short, but our new addition involves file operations, the process time is relatively long, but the thread is still there, so dubbo retried three times, and all three were successful Up.

I changed the file operation to asynchronous later, and the time for the main process to be synchronous was shortened a lot.

Supplement: Version 2.7.3 has been fixed, that is, in the case of annotations, the default value in the nullSafeEquals method is the same as that in the following, both are 2, so it can be saved in the map even when it is 0.

I'm Ao Bing, a tool man who has survived on the Internet.

The more you know, the more you don’t. The talents’ [three consecutive years] are the greatest motivation for Bingbing’s creation. See you next time!

Note: If there are any mistakes or suggestions in this blog, please leave a message, please say something!

The article is continuously updated, and you can search for "San Taizi Ao Bing" on WeChat to read it for the first time. This article has been included on GitHub https://github.com/JavaFamily . There are complete interview test sites for major companies. Welcome to Star.

Guess you like

Origin blog.51cto.com/14689292/2546543