Click “like” to see again, form a habit, wechat search [Three prince Aobing] to pay attention to the Internet tools of survival.

This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.

background

One day operation feedback, click a save, but three data appeared in the background, I thought at that time, should not ah, I have not moved this code for tens of thousands of years, I told him not to operate, reserve the scene, I go to check.

I took a look at the new code and right clicked to see the author


I didn’t expect that the new code of XX module had been changed, so I asked the new code of XX module whether you had moved it?

After a long silence, he wiped the sweat from his sideburns with leftover paper from the table, gulped and said, ‘Yes, I did. I changed dubbo’s XML configuration to annotations.’

What’s the matter? Now there’s a BUG?

Tell me about this change next time. I guess it’s a bug in dubbo’s source code. Don’t panic, let me see what’s wrong.

The body of the

Dubbo can be configured in many different ways, and the most popular is the XML configuration. If the number of retries is not required, we will add the number of retries to 0, because it is multiple by default.

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

Copy the code

Or use annotations

@Reference(retries =0

Copy the code

In fact, I already know what the reason is, but in order to confirm my guess, I started the following debug tour ~~~

Note: Dubbo version: 2.6.2

Firstly, under the condition of @reference:


Use the @reference annotation to configure the retry times

The first is that the code location for dubbo retries is found. (Starting the Dubbo project, when the interface is called, F5 enters the method, jumps to the Invoke method in InvokerInvocationHandler, continues tracing the invoke method in MockClusterInvoker, AbstractClusterInvoker invoke (FailoverClusterInvoker doInvoke)

The retries value is 0, but the retries value is null.

The value is null

So defaultValue will be returned, plus the time it called itself, and then it will be 3, as shown in the figure below:

A value of 3

So you can see that when retries is set to 0 using the @reference annotation, dubbo retries are two times (3 includes the call itself).

The dubbo: Reference tag is used:

Dubbo label mode

As shown in the following figure, when the attribute is obtained, you can see that the value obtained is 0, which is the same as the annotation configuration, as shown in the figure:

A value of 0

Plus the call itself, after the calculation will be 1, as shown in the figure:

The value is 1

Therefore, when retries is set to 0, the number of dubbo retries is 0 (1 is the call itself).

Cause analysis,

The first is the @reference annotation form:

Dubbo first parses each interface into a ReferenceBean, which implements the FactoryBean interface, so at injection time, the getObject method is called to generate the proxy object.

But that’s not the point, because by this point, all the attributes have been loaded, so you need to find the code location where Dubbo parses the attributes in the annotation.

Dubbo ReferenceAnnotationBeanPostProcessor will use custom drives to inject properties, And specific implementation of injected code position is ReferenceAnnotationBeanPostProcessor class postProcessPropertyValues method invokes the inject method of execution.

The important thing is that since the tag is injected with the @AutoWired annotation, it is injected in the spring native way, while the @Reference annotation is injected in the spring native way. Injection when they go to dubbo own ReferenceAnnotationBeanPostProcessor private inner class ReferenceFieldElement inject method, Then call buildReferenceBean to create the ReferenceBean.

As we get closer and closer to the cause, we can see that the retries value in the beanBuilder is still 0, indicating that it has not been resolved to null at this point, as shown in the figure below:

Retries to “0”

Continue to go down, call the build method of configureBean, in the first step preConfigureBean method, in this way can create AnnotationPropertyValuesAdapter object, in the object constructor invokes adapt method, Then go to the getAttributes method in AnnotationUtils, which has a key method, nullSafeEquals, that passes in the current attribute value and default value.

If they are equal, the attributes are ignored and the matching attributes are put into the actualAttributes map. Our REtries attribute is 0, the same as the default value, so the map does not store the value of the REtries attribute, only the timeout attribute. Hence the null value obtained later.

End of annotation mode DEBUG.

Map does not contain REtries

Dubbo: Reference tag form:

Said to the above, the label form to inject, forms and annotations are different, using the tag, dubbo will use a custom parser to parse the name of the space, it is easy to understand, spring also don’t know it inside the custom tag those stuff is what meaning, so dubbo will inherit the spring.

NamespaceHandlerSupport, using the custom DubboNamespaceHandler parser to parse the tag, as shown below:

Dubbo custom namespace resolver

It then calls the parse method of that class to parse the retries to get all the methods in the class (the class shown in green above is the class of the ReferenceBean whose parent has several set methods, including the setRetries method). Filter out the method starting with set, then cut out the attribute name and put it into the attribute pool. You can see that the parsed value here is 0, not null, as shown below:

Gets the location of the attribute name
Gets the REtries value 0

summary

Let me draw a simple picture:

A flowchart

conclusion

  • Note format: If retries is not configured or is set to 0, two retries are performed. Retries are not performed only when retries is set to -1 or smaller.

  • In the label format, the retries tries twice if the value is 0 or smaller.

Therefore, you are advised to set this parameter to -1 if you do not need to retry, such as the interface for add, delete, or modify operations. Otherwise, idempotency must be ensured. Set it to 1 or greater if you need to retry. This is part of the Dubbo dug. (I think so.)

That’s the end of it, and the call to getObject is the follow-up to service discovery and establishing a long connection with the server and returning the proxy object.

The reason for the occurrence of 3 pieces of data is that I defined the interface timeout time is short, but our new operation involving files takes a long time, but the thread is still there, so Dubbo tried three times, and all three times were successful.

I’ll change the file operation to asynchronous later, and then the main flow is synchronous and the time is much shorter.

Note: in the case of annotations, nullSafeEquals defaults to 2, so 0 can be saved to map.

I am Aobing, a tool to survive on the Internet.

The more you know, the more you don’t know, the talent of the [three] is the biggest impetus for the creation of c c, we will see you next time!

Note: If there are any mistakes or suggestions in this blog, please leave a comment.


[Information] [interview] [resume] I prepared the interview materials and resume template, this article GitHub github.com/JavaFamily has been included, there are big factory interview complete test site, welcome Star.